Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / ext-all-debug.js
index 43cf393..8fc6dc0 100644 (file)
+/*
 
+This file is part of Ext JS 4
 
-Ext.DomHelper = function(){
-    var tempTableEl = null,
-        emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
-        tableRe = /^table|tbody|tr|td$/i,
-        confRe = /tag|children|cn|html$/i,
-        tableElRe = /td|tr|tbody/i,
-        cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
-        endRe = /end/i,
-        pub,
-        
-        afterbegin = 'afterbegin',
-        afterend = 'afterend',
-        beforebegin = 'beforebegin',
-        beforeend = 'beforeend',
-        ts = '<table>',
-        te = '</table>',
-        tbs = ts+'<tbody>',
-        tbe = '</tbody>'+te,
-        trs = tbs + '<tr>',
-        tre = '</tr>'+tbe;
+Copyright (c) 2011 Sencha Inc
 
-    
-    function doInsert(el, o, returnElement, pos, sibling, append){
-        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
-        return returnElement ? Ext.get(newNode, true) : newNode;
-    }
+Contact:  http://www.sencha.com/contact
 
-    
-    function createHtml(o){
-        var b = '',
-            attr,
-            val,
-            key,
-            cn;
+GNU General Public License Usage
+This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
 
-        if(typeof o == "string"){
-            b = o;
-        } else if (Ext.isArray(o)) {
-            for (var i=0; i < o.length; i++) {
-                if(o[i]) {
-                    b += createHtml(o[i]);
-                }
-            };
-        } else {
-            b += '<' + (o.tag = o.tag || 'div');
-            for (attr in o) {
-                val = o[attr];
-                if(!confRe.test(attr)){
-                    if (typeof val == "object") {
-                        b += ' ' + attr + '="';
-                        for (key in val) {
-                            b += key + ':' + val[key] + ';';
-                        };
-                        b += '"';
-                    }else{
-                        b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
-                    }
-                }
-            };
-            
-            if (emptyTags.test(o.tag)) {
-                b += '/>';
-            } else {
-                b += '>';
-                if ((cn = o.children || o.cn)) {
-                    b += createHtml(cn);
-                } else if(o.html){
-                    b += o.html;
-                }
-                b += '</' + o.tag + '>';
-            }
-        }
-        return b;
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
+
+*/
+
+
+(function() {
+    var global = this,
+        objectPrototype = Object.prototype,
+        toString = objectPrototype.toString,
+        enumerables = true,
+        enumerablesTest = { toString: 1 },
+        i;
+
+    if (typeof Ext === 'undefined') {
+        global.Ext = {};
     }
 
-    function ieTable(depth, s, h, e){
-        tempTableEl.innerHTML = [s, h, e].join('');
-        var i = -1,
-            el = tempTableEl,
-            ns;
-        while(++i < depth){
-            el = el.firstChild;
-        }
+    Ext.global = global;
 
-        if(ns = el.nextSibling){
-            var df = document.createDocumentFragment();
-            while(el){
-                ns = el.nextSibling;
-                df.appendChild(el);
-                el = ns;
-            }
-            el = df;
-        }
-        return el;
+    for (i in enumerablesTest) {
+        enumerables = null;
     }
 
-    
-    function insertIntoTable(tag, where, el, html) {
-        var node,
-            before;
+    if (enumerables) {
+        enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
+                       'toLocaleString', 'toString', 'constructor'];
+    }
 
-        tempTableEl = tempTableEl || document.createElement('div');
+    
+    Ext.enumerables = enumerables;
 
-        if(tag == 'td' && (where == afterbegin || where == beforeend) ||
-           !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
-            return;
+    
+    Ext.apply = function(object, config, defaults) {
+        if (defaults) {
+            Ext.apply(object, defaults);
         }
-        before = where == beforebegin ? el :
-                 where == afterend ? el.nextSibling :
-                 where == afterbegin ? el.firstChild : null;
 
-        if (where == beforebegin || where == afterend) {
-            el = el.parentNode;
-        }
+        if (object && config && typeof config === 'object') {
+            var i, j, k;
 
-        if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
-            node = ieTable(4, trs, html, tre);
-        } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
-                   (tag == 'tr' && (where == beforebegin || where == afterend))) {
-            node = ieTable(3, tbs, html, tbe);
-        } else {
-            node = ieTable(2, ts, html, te);
+            for (i in config) {
+                object[i] = config[i];
+            }
+
+            if (enumerables) {
+                for (j = enumerables.length; j--;) {
+                    k = enumerables[j];
+                    if (config.hasOwnProperty(k)) {
+                        object[k] = config[k];
+                    }
+                }
+            }
         }
-        el.insertBefore(node, before);
-        return node;
-    }
 
+        return object;
+    };
 
-    pub = {
+    Ext.buildSettings = Ext.apply({
+        baseCSSPrefix: 'x-',
+        scopeResetCSS: false
+    }, Ext.buildSettings || {});
+
+    Ext.apply(Ext, {
         
-        markup : function(o){
-            return createHtml(o);
-        },
+        emptyFn: function() {},
+
+        baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
 
         
-        applyStyles : function(el, styles){
-            if (styles) {
-                var matches;
+        applyIf: function(object, config) {
+            var property;
 
-                el = Ext.fly(el);
-                if (typeof styles == "function") {
-                    styles = styles.call();
-                }
-                if (typeof styles == "string") {
-                    while ((matches = cssRe.exec(styles))) {
-                        el.setStyle(matches[1], matches[2]);
+            if (object) {
+                for (property in config) {
+                    if (object[property] === undefined) {
+                        object[property] = config[property];
                     }
-                } else if (typeof styles == "object") {
-                    el.setStyle(styles);
                 }
             }
+
+            return object;
         },
 
         
-        insertHtml : function(where, el, html){
-            var hash = {},
-                hashVal,
-                setStart,
-                range,
-                frag,
-                rangeEl,
-                rs;
+        iterate: function(object, fn, scope) {
+            if (Ext.isEmpty(object)) {
+                return;
+            }
 
-            where = where.toLowerCase();
+            if (scope === undefined) {
+                scope = object;
+            }
+
+            if (Ext.isIterable(object)) {
+                Ext.Array.each.call(Ext.Array, object, fn, scope);
+            }
+            else {
+                Ext.Object.each.call(Ext.Object, object, fn, scope);
+            }
+        }
+    });
+
+    Ext.apply(Ext, {
+
+        
+        extend: function() {
             
-            hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
-            hash[afterend] = ['AfterEnd', 'nextSibling'];
+            var objectConstructor = objectPrototype.constructor,
+                inlineOverrides = function(o) {
+                for (var m in o) {
+                    if (!o.hasOwnProperty(m)) {
+                        continue;
+                    }
+                    this[m] = o[m];
+                }
+            };
 
-            if (el.insertAdjacentHTML) {
-                if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
-                    return rs;
+            return function(subclass, superclass, overrides) {
+                
+                if (Ext.isObject(superclass)) {
+                    overrides = superclass;
+                    superclass = subclass;
+                    subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
+                        superclass.apply(this, arguments);
+                    };
                 }
+
+
                 
-                hash[afterbegin] = ['AfterBegin', 'firstChild'];
-                hash[beforeend] = ['BeforeEnd', 'lastChild'];
-                if ((hashVal = hash[where])) {
-                    el.insertAdjacentHTML(hashVal[0], html);
-                    return el[hashVal[1]];
+                var F = function() {},
+                    subclassProto, superclassProto = superclass.prototype;
+
+                F.prototype = superclassProto;
+                subclassProto = subclass.prototype = new F();
+                subclassProto.constructor = subclass;
+                subclass.superclass = superclassProto;
+
+                if (superclassProto.constructor === objectConstructor) {
+                    superclassProto.constructor = superclass;
                 }
-            } else {
-                range = el.ownerDocument.createRange();
-                setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
-                if (hash[where]) {
-                    range[setStart](el);
-                    frag = range.createContextualFragment(html);
-                    el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
-                    return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
-                } else {
-                    rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
-                    if (el.firstChild) {
-                        range[setStart](el[rangeEl]);
-                        frag = range.createContextualFragment(html);
-                        if(where == afterbegin){
-                            el.insertBefore(frag, el.firstChild);
-                        }else{
-                            el.appendChild(frag);
-                        }
-                    } else {
-                        el.innerHTML = html;
+
+                subclass.override = function(overrides) {
+                    Ext.override(subclass, overrides);
+                };
+
+                subclassProto.override = inlineOverrides;
+                subclassProto.proto = subclassProto;
+
+                subclass.override(overrides);
+                subclass.extend = function(o) {
+                    return Ext.extend(subclass, o);
+                };
+
+                return subclass;
+            };
+        }(),
+
+        
+        override: function(cls, overrides) {
+            if (cls.prototype.$className) {
+                return cls.override(overrides);
+            }
+            else {
+                Ext.apply(cls.prototype, overrides);
+            }
+        }
+    });
+
+    
+    Ext.apply(Ext, {
+
+        
+        valueFrom: function(value, defaultValue, allowBlank){
+            return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
+        },
+
+        
+        typeOf: function(value) {
+            if (value === null) {
+                return 'null';
+            }
+
+            var type = typeof value;
+
+            if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
+                return type;
+            }
+
+            var typeToString = toString.call(value);
+
+            switch(typeToString) {
+                case '[object Array]':
+                    return 'array';
+                case '[object Date]':
+                    return 'date';
+                case '[object Boolean]':
+                    return 'boolean';
+                case '[object Number]':
+                    return 'number';
+                case '[object RegExp]':
+                    return 'regexp';
+            }
+
+            if (type === 'function') {
+                return 'function';
+            }
+
+            if (type === 'object') {
+                if (value.nodeType !== undefined) {
+                    if (value.nodeType === 3) {
+                        return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
+                    }
+                    else {
+                        return 'element';
                     }
-                    return el[rangeEl];
                 }
+
+                return 'object';
             }
-            throw 'Illegal insertion point -> "' + where + '"';
+
         },
 
         
-        insertBefore : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, beforebegin);
+        isEmpty: function(value, allowEmptyString) {
+            return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
         },
 
         
-        insertAfter : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, afterend, 'nextSibling');
+        isArray: ('isArray' in Array) ? Array.isArray : function(value) {
+            return toString.call(value) === '[object Array]';
         },
 
         
-        insertFirst : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
+        isDate: function(value) {
+            return toString.call(value) === '[object Date]';
         },
 
         
-        append : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, beforeend, '', true);
+        isObject: (toString.call(null) === '[object Object]') ?
+        function(value) {
+            
+            return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
+        } :
+        function(value) {
+            return toString.call(value) === '[object Object]';
         },
 
         
-        overwrite : function(el, o, returnElement){
-            el = Ext.getDom(el);
-            el.innerHTML = createHtml(o);
-            return returnElement ? Ext.get(el.firstChild) : el.firstChild;
+        isPrimitive: function(value) {
+            var type = typeof value;
+
+            return type === 'string' || type === 'number' || type === 'boolean';
         },
 
-        createHtml : createHtml
-    };
-    return pub;
-}();
+        
+        isFunction:
+        
+        
+        (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
+            return toString.call(value) === '[object Function]';
+        } : function(value) {
+            return typeof value === 'function';
+        },
 
-Ext.apply(Ext.DomHelper,
-function(){
-    var pub,
-        afterbegin = 'afterbegin',
-        afterend = 'afterend',
-        beforebegin = 'beforebegin',
-        beforeend = 'beforeend',
-        confRe = /tag|children|cn|html$/i;
+        
+        isNumber: function(value) {
+            return typeof value === 'number' && isFinite(value);
+        },
 
-    
-    function doInsert(el, o, returnElement, pos, sibling, append){
-        el = Ext.getDom(el);
-        var newNode;
-        if (pub.useDom) {
-            newNode = createDom(o, null);
-            if (append) {
-                el.appendChild(newNode);
-            } else {
-                (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
-            }
-        } else {
-            newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
+        
+        isNumeric: function(value) {
+            return !isNaN(parseFloat(value)) && isFinite(value);
+        },
+
+        
+        isString: function(value) {
+            return typeof value === 'string';
+        },
+
+        
+        isBoolean: function(value) {
+            return typeof value === 'boolean';
+        },
+
+        
+        isElement: function(value) {
+            return value ? value.nodeType === 1 : false;
+        },
+
+        
+        isTextNode: function(value) {
+            return value ? value.nodeName === "#text" : false;
+        },
+
+        
+        isDefined: function(value) {
+            return typeof value !== 'undefined';
+        },
+
+        
+        isIterable: function(value) {
+            return (value && typeof value !== 'string') ? value.length !== undefined : false;
         }
-        return returnElement ? Ext.get(newNode, true) : newNode;
-    }
+    });
 
-    
-    
-    function createDom(o, parentNode){
-        var el,
-            doc = document,
-            useSet,
-            attr,
-            val,
-            cn;
+    Ext.apply(Ext, {
 
-        if (Ext.isArray(o)) {                       
-            el = doc.createDocumentFragment(); 
-            for (var i = 0, l = o.length; i < l; i++) {
-                createDom(o[i], el);
+        
+        clone: function(item) {
+            if (item === null || item === undefined) {
+                return item;
             }
-        } else if (typeof o == 'string') {         
-            el = doc.createTextNode(o);
-        } else {
-            el = doc.createElement( o.tag || 'div' );
-            useSet = !!el.setAttribute; 
-            for (var attr in o) {
-                if(!confRe.test(attr)){
-                    val = o[attr];
-                    if(attr == 'cls'){
-                        el.className = val;
-                    }else{
-                        if(useSet){
-                            el.setAttribute(attr, val);
-                        }else{
-                            el[attr] = val;
-                        }
+
+            
+            
+            
+            if (item.nodeType && item.cloneNode) {
+                return item.cloneNode(true);
+            }
+
+            var type = toString.call(item);
+
+            
+            if (type === '[object Date]') {
+                return new Date(item.getTime());
+            }
+
+            var i, j, k, clone, key;
+
+            
+            if (type === '[object Array]') {
+                i = item.length;
+
+                clone = [];
+
+                while (i--) {
+                    clone[i] = Ext.clone(item[i]);
+                }
+            }
+            
+            else if (type === '[object Object]' && item.constructor === Object) {
+                clone = {};
+
+                for (key in item) {
+                    clone[key] = Ext.clone(item[key]);
+                }
+
+                if (enumerables) {
+                    for (j = enumerables.length; j--;) {
+                        k = enumerables[j];
+                        clone[k] = item[k];
                     }
                 }
             }
-            Ext.DomHelper.applyStyles(el, o.style);
 
-            if ((cn = o.children || o.cn)) {
-                createDom(cn, el);
-            } else if (o.html) {
-                el.innerHTML = o.html;
+            return clone || item;
+        },
+
+        
+        getUniqueGlobalNamespace: function() {
+            var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
+
+            if (uniqueGlobalNamespace === undefined) {
+                var i = 0;
+
+                do {
+                    uniqueGlobalNamespace = 'ExtBox' + (++i);
+                } while (Ext.global[uniqueGlobalNamespace] !== undefined);
+
+                Ext.global[uniqueGlobalNamespace] = Ext;
+                this.uniqueGlobalNamespace = uniqueGlobalNamespace;
             }
+
+            return uniqueGlobalNamespace;
+        },
+
+        
+        functionFactory: function() {
+            var args = Array.prototype.slice.call(arguments);
+
+            if (args.length > 0) {
+                args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
+                    args[args.length - 1];
+            }
+
+            return Function.prototype.constructor.apply(Function.prototype, args);
         }
-        if(parentNode){
-           parentNode.appendChild(el);
-        }
-        return el;
-    }
+    });
+
+    
+    Ext.type = Ext.typeOf;
+
+})();
+
+
+(function() {
+
+
+var version = '4.0.7', Version;
+    Ext.Version = Version = Ext.extend(Object, {
 
-    pub = {
         
-        createTemplate : function(o){
-            var html = Ext.DomHelper.createHtml(o);
-            return new Ext.Template(html);
+        constructor: function(version) {
+            var parts, releaseStartIndex;
+
+            if (version instanceof Version) {
+                return version;
+            }
+
+            this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
+
+            releaseStartIndex = this.version.search(/([^\d\.])/);
+
+            if (releaseStartIndex !== -1) {
+                this.release = this.version.substr(releaseStartIndex, version.length);
+                this.shortVersion = this.version.substr(0, releaseStartIndex);
+            }
+
+            this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
+
+            parts = this.version.split('.');
+
+            this.major = parseInt(parts.shift() || 0, 10);
+            this.minor = parseInt(parts.shift() || 0, 10);
+            this.patch = parseInt(parts.shift() || 0, 10);
+            this.build = parseInt(parts.shift() || 0, 10);
+
+            return this;
         },
 
         
-        useDom : false,
+        toString: function() {
+            return this.version;
+        },
 
         
-        insertBefore : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, beforebegin);
+        valueOf: function() {
+            return this.version;
         },
 
         
-        insertAfter : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, afterend, 'nextSibling');
+        getMajor: function() {
+            return this.major || 0;
         },
 
         
-        insertFirst : function(el, o, returnElement){
-            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
+        getMinor: function() {
+            return this.minor || 0;
         },
 
         
-        append: function(el, o, returnElement){
-            return doInsert(el, o, returnElement, beforeend, '', true);
+        getPatch: function() {
+            return this.patch || 0;
         },
 
         
-        createDom: createDom
-    };
-    return pub;
-}());
+        getBuild: function() {
+            return this.build || 0;
+        },
 
-Ext.Template = function(html){
-    var me = this,
-        a = arguments,
-        buf = [],
-        v;
-
-    if (Ext.isArray(html)) {
-        html = html.join("");
-    } else if (a.length > 1) {
-        for(var i = 0, len = a.length; i < len; i++){
-            v = a[i];
-            if(typeof v == 'object'){
-                Ext.apply(me, v);
-            } else {
-                buf.push(v);
-            }
-        };
-        html = buf.join('');
-    }
+        
+        getRelease: function() {
+            return this.release || '';
+        },
 
-    
-    me.html = html;
-    
-    if (me.compiled) {
-        me.compile();
-    }
-};
-Ext.Template.prototype = {
-    
-    re : /\{([\w-]+)\}/g,
-    
+        
+        isGreaterThan: function(target) {
+            return Version.compare(this.version, target) === 1;
+        },
 
-    
-    applyTemplate : function(values){
-        var me = this;
+        
+        isLessThan: function(target) {
+            return Version.compare(this.version, target) === -1;
+        },
 
-        return me.compiled ?
-                me.compiled(values) :
-                me.html.replace(me.re, function(m, name){
-                    return values[name] !== undefined ? values[name] : "";
-                });
-    },
+        
+        equals: function(target) {
+            return Version.compare(this.version, target) === 0;
+        },
 
-    
-    set : function(html, compile){
-        var me = this;
-        me.html = html;
-        me.compiled = null;
-        return compile ? me.compile() : me;
-    },
+        
+        match: function(target) {
+            target = String(target);
+            return this.version.substr(0, target.length) === target;
+        },
 
-    
-    compile : function(){
-        var me = this,
-            sep = Ext.isGecko ? "+" : ",";
+        
+        toArray: function() {
+            return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
+        },
 
-        function fn(m, name){
-            name = "values['" + name + "']";
-            return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
+        
+        getShortVersion: function() {
+            return this.shortVersion;
         }
+    });
 
-        eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
-             me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
-             (Ext.isGecko ?  "';};" : "'].join('');};"));
-        return me;
-    },
+    Ext.apply(Version, {
+        
+        releaseValueMap: {
+            'dev': -6,
+            'alpha': -5,
+            'a': -5,
+            'beta': -4,
+            'b': -4,
+            'rc': -3,
+            '#': -2,
+            'p': -1,
+            'pl': -1
+        },
 
-    
-    insertFirst: function(el, values, returnElement){
-        return this.doInsert('afterBegin', el, values, returnElement);
-    },
+        
+        getComponentValue: function(value) {
+            return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
+        },
 
-    
-    insertBefore: function(el, values, returnElement){
-        return this.doInsert('beforeBegin', el, values, returnElement);
-    },
+        
+        compare: function(current, target) {
+            var currentValue, targetValue, i;
 
-    
-    insertAfter : function(el, values, returnElement){
-        return this.doInsert('afterEnd', el, values, returnElement);
-    },
+            current = new Version(current).toArray();
+            target = new Version(target).toArray();
 
-    
-    append : function(el, values, returnElement){
-        return this.doInsert('beforeEnd', el, values, returnElement);
-    },
+            for (i = 0; i < Math.max(current.length, target.length); i++) {
+                currentValue = this.getComponentValue(current[i]);
+                targetValue = this.getComponentValue(target[i]);
 
-    doInsert : function(where, el, values, returnEl){
-        el = Ext.getDom(el);
-        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
-        return returnEl ? Ext.get(newNode, true) : newNode;
-    },
+                if (currentValue < targetValue) {
+                    return -1;
+                } else if (currentValue > targetValue) {
+                    return 1;
+                }
+            }
 
-    
-    overwrite : function(el, values, returnElement){
-        el = Ext.getDom(el);
-        el.innerHTML = this.applyTemplate(values);
-        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
-    }
-};
+            return 0;
+        }
+    });
 
-Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
+    Ext.apply(Ext, {
+        
+        versions: {},
 
+        
+        lastRegisteredVersion: null,
 
-Ext.Template.from = function(el, config){
-    el = Ext.getDom(el);
-    return new Ext.Template(el.value || el.innerHTML, config || '');
-};
+        
+        setVersion: function(packageName, version) {
+            Ext.versions[packageName] = new Version(version);
+            Ext.lastRegisteredVersion = Ext.versions[packageName];
 
-Ext.apply(Ext.Template.prototype, {
-    
-    disableFormats : false,
-    
+            return this;
+        },
 
-    
-    re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
-    argsRe : /^\s*['"](.*)["']\s*$/,
-    compileARe : /\\/g,
-    compileBRe : /(\r\n|\n)/g,
-    compileCRe : /'/g,
+        
+        getVersion: function(packageName) {
+            if (packageName === undefined) {
+                return Ext.lastRegisteredVersion;
+            }
 
-    /**
-     * Returns an HTML fragment of this template with the specified values applied.
-     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
-     * @return {String} The HTML fragment
-     * @hide repeat doc
-     */
-    applyTemplate : function(values){
-        var me = this,
-            useF = me.disableFormats !== true,
-            fm = Ext.util.Format,
-            tpl = me;
+            return Ext.versions[packageName];
+        },
 
-        if(me.compiled){
-            return me.compiled(values);
-        }
-        function fn(m, name, format, args){
-            if (format && useF) {
-                if (format.substr(0, 5) == "this.") {
-                    return tpl.call(format.substr(5), values[name], values);
-                } else {
-                    if (args) {
-                        // quoted values are required for strings in compiled templates,
-                        // but for non compiled we need to strip them
-                        // quoted reversed for jsmin
-                        var re = me.argsRe;
-                        args = args.split(',');
-                        for(var i = 0, len = args.length; i < len; i++){
-                            args[i] = args[i].replace(re, "$1");
-                        }
-                        args = [values[name]].concat(args);
-                    } else {
-                        args = [values[name]];
-                    }
-                    return fm[format].apply(fm, args);
-                }
-            } else {
-                return values[name] !== undefined ? values[name] : "";
+        
+        deprecate: function(packageName, since, closure, scope) {
+            if (Version.compare(Ext.getVersion(packageName), since) < 1) {
+                closure.call(scope);
             }
         }
-        return me.html.replace(me.re, fn);
-    },
+    }); 
+
+    Ext.setVersion('core', version);
+
+})();
+
+
+
+Ext.String = {
+    trimRegex: /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
+    escapeRe: /('|\\)/g,
+    formatRe: /\{(\d+)\}/g,
+    escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
 
     /**
-     * Compiles the template into an internal function, eliminating the RegEx overhead.
-     * @return {Ext.Template} this
-     * @hide repeat doc
+     * Convert certain characters (&, <, >, and ") to their HTML character equivalents for literal display in web pages.
+     * @param {String} value The string to encode
+     * @return {String} The encoded text
+     * @method
      */
-    compile : function(){
-        var me = this,
-            fm = Ext.util.Format,
-            useF = me.disableFormats !== true,
-            sep = Ext.isGecko ? "+" : ",",
-            body;
+    htmlEncode: (function() {
+        var entities = {
+            '&': '&amp;',
+            '>': '&gt;',
+            '<': '&lt;',
+            '"': '&quot;'
+        }, keys = [], p, regex;
+        
+        for (p in entities) {
+            keys.push(p);
+        }
+        
+        regex = new RegExp('(' + keys.join('|') + ')', 'g');
+        
+        return function(value) {
+            return (!value) ? value : String(value).replace(regex, function(match, capture) {
+                return entities[capture];    
+            });
+        };
+    })(),
 
-        function fn(m, name, format, args){
-            if(format && useF){
-                args = args ? ',' + args : "";
-                if(format.substr(0, 5) != "this."){
-                    format = "fm." + format + '(';
-                }else{
-                    format = 'this.call("'+ format.substr(5) + '", ';
-                    args = ", values";
-                }
-            }else{
-                args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
-            }
-            return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
+    /**
+     * Convert certain characters (&, <, >, and ") from their HTML character equivalents.
+     * @param {String} value The string to decode
+     * @return {String} The decoded text
+     * @method
+     */
+    htmlDecode: (function() {
+        var entities = {
+            '&amp;': '&',
+            '&gt;': '>',
+            '&lt;': '<',
+            '&quot;': '"'
+        }, keys = [], p, regex;
+        
+        for (p in entities) {
+            keys.push(p);
         }
+        
+        regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
+        
+        return function(value) {
+            return (!value) ? value : String(value).replace(regex, function(match, capture) {
+                if (capture in entities) {
+                    return entities[capture];
+                } else {
+                    return String.fromCharCode(parseInt(capture.substr(2), 10));
+                }
+            });
+        };
+    })(),
 
-        // branched to use + in gecko and [].join() in others
-        if(Ext.isGecko){
-            body = "this.compiled = function(values){ return '" +
-                   me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn) +
-                    "';};";
-        }else{
-            body = ["this.compiled = function(values){ return ['"];
-            body.push(me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn));
-            body.push("'].join('');};");
-            body = body.join('');
+    
+    urlAppend : function(url, string) {
+        if (!Ext.isEmpty(string)) {
+            return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
         }
-        eval(body);
-        return me;
+
+        return url;
     },
 
-    // private function used to call members
-    call : function(fnName, value, allValues){
-        return this[fnName](value, allValues);
-    }
-});
-Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
-/*
- * This is code is also distributed under MIT license for use
- * with jQuery and prototype JavaScript libraries.
- */
-/**
- * @class Ext.DomQuery
-Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
-<p>
-DomQuery supports most of the <a href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#selectors">CSS3 selectors spec</a>, along with some custom selectors and basic XPath.</p>
-
-<p>
-All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example "div.foo:nth-child(odd)[@foo=bar].bar:first" would be a perfectly valid selector. Node filters are processed in the order in which they appear, which allows you to optimize your queries for your document structure.
-</p>
-<h4>Element Selectors:</h4>
-<ul class="list">
-    <li> <b>*</b> any element</li>
-    <li> <b>E</b> an element with the tag E</li>
-    <li> <b>E F</b> All descendent elements of E that have the tag F</li>
-    <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
-    <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
-    <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
-</ul>
-<h4>Attribute Selectors:</h4>
-<p>The use of &#64; and quotes are optional. For example, div[&#64;foo='bar'] is also a valid attribute selector.</p>
-<ul class="list">
-    <li> <b>E[foo]</b> has an attribute "foo"</li>
-    <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
-    <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
-    <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
-    <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
-    <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
-    <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
-</ul>
-<h4>Pseudo Classes:</h4>
-<ul class="list">
-    <li> <b>E:first-child</b> E is the first child of its parent</li>
-    <li> <b>E:last-child</b> E is the last child of its parent</li>
-    <li> <b>E:nth-child(<i>n</i>)</b> E is the <i>n</i>th child of its parent (1 based as per the spec)</li>
-    <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
-    <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
-    <li> <b>E:only-child</b> E is the only child of its parent</li>
-    <li> <b>E:checked</b> E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) </li>
-    <li> <b>E:first</b> the first E in the resultset</li>
-    <li> <b>E:last</b> the last E in the resultset</li>
-    <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
-    <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
-    <li> <b>E:even</b> shortcut for :nth-child(even)</li>
-    <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
-    <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
-    <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
-    <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
-    <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
-    <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
-    <li> <b>E:any(S1|S2|S2)</b> an E element which matches any of the simple selectors S1, S2 or S3
-</ul>
-<h4>CSS Value Selectors:</h4>
-<ul class="list">
-    <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
-    <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
-    <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
-    <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
-    <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
-    <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
-</ul>
- * @singleton
- */
-Ext.DomQuery = function(){
-    var cache = {}, 
-       simpleCache = {}, 
-       valueCache = {},
-       nonSpace = /\S/,
-       trimRe = /^\s+|\s+$/g,
-       tplRe = /\{(\d+)\}/g,
-       modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
-       tagTokenRe = /^(#)?([\w-\*]+)/,
-       nthRe = /(\d*)n\+?(\d*)/, 
-       nthRe2 = /\D/,
-       
-       
-       
-       isIE = window.ActiveXObject ? true : false,
-       key = 30803;
-    
     
-    
-    eval("var batch = 30803;");        
+    trim: function(string) {
+        return string.replace(Ext.String.trimRegex, "");
+    },
 
     
+    capitalize: function(string) {
+        return string.charAt(0).toUpperCase() + string.substr(1);
+    },
+
     
-    function child(parent, index){
-        var i = 0,
-            n = parent.firstChild;
-        while(n){
-            if(n.nodeType == 1){
-               if(++i == index){
-                   return n;
-               }
+    ellipsis: function(value, len, word) {
+        if (value && value.length > len) {
+            if (word) {
+                var vs = value.substr(0, len - 2),
+                index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
+                if (index !== -1 && index >= (len - 15)) {
+                    return vs.substr(0, index) + "...";
+                }
             }
-            n = n.nextSibling;
+            return value.substr(0, len - 3) + "...";
         }
-        return null;
-    }
+        return value;
+    },
 
     
-    function next(n){  
-        while((n = n.nextSibling) && n.nodeType != 1);
-        return n;
-    }
+    escapeRegex: function(string) {
+        return string.replace(Ext.String.escapeRegexRe, "\\$1");
+    },
 
     
-    function prev(n){
-        while((n = n.previousSibling) && n.nodeType != 1);
-        return n;
-    }
+    escape: function(string) {
+        return string.replace(Ext.String.escapeRe, "\\$1");
+    },
 
     
-    
-    function children(parent){
-        var n = parent.firstChild,
-           nodeIndex = -1,
-           nextNode;
-       while(n){
-           nextNode = n.nextSibling;
-           
-           if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
-               parent.removeChild(n);
-           }else{
-               
-               n.nodeIndex = ++nodeIndex;
-           }
-           n = nextNode;
-       }
-       return this;
-    }
-
+    toggle: function(string, value, other) {
+        return string === value ? other : value;
+    },
 
     
-    
-    function byClassName(nodeSet, cls){
-        if(!cls){
-            return nodeSet;
-        }
-        var result = [], ri = -1;
-        for(var i = 0, ci; ci = nodeSet[i]; i++){
-            if((' '+ci.className+' ').indexOf(cls) != -1){
-                result[++ri] = ci;
-            }
+    leftPad: function(string, size, character) {
+        var result = String(string);
+        character = character || " ";
+        while (result.length < size) {
+            result = character + result;
         }
         return result;
-    };
+    },
 
-    function attrValue(n, attr){
-       
-        if(!n.tagName && typeof n.length != "undefined"){
-            n = n[0];
-        }
-        if(!n){
-            return null;
-        }
+    
+    format: function(format) {
+        var args = Ext.Array.toArray(arguments, 1);
+        return format.replace(Ext.String.formatRe, function(m, i) {
+            return args[i];
+        });
+    },
 
-        if(attr == "for"){
-            return n.htmlFor;
-        }
-        if(attr == "class" || attr == "className"){
-            return n.className;
+    
+    repeat: function(pattern, count, sep) {
+        for (var buf = [], i = count; i--; ) {
+            buf.push(pattern);
         }
-        return n.getAttribute(attr) || n[attr];
+        return buf.join(sep || '');
+    }
+};
 
-    };
 
 
+(function() {
+
+var isToFixedBroken = (0.9).toFixed() !== '1';
+
+Ext.Number = {
     
-    
-    
-    function getNodes(ns, mode, tagName){
-        var result = [], ri = -1, cs;
-        if(!ns){
-            return result;
-        }
-        tagName = tagName || "*";
-       
-        if(typeof ns.getElementsByTagName != "undefined"){
-            ns = [ns];
-        }
-       
-       
-       
-        if(!mode){
-            for(var i = 0, ni; ni = ns[i]; i++){
-                cs = ni.getElementsByTagName(tagName);
-                for(var j = 0, ci; ci = cs[j]; j++){
-                    result[++ri] = ci;
-                }
-            }
-       
-       
-        } else if(mode == "/" || mode == ">"){
-            var utag = tagName.toUpperCase();
-            for(var i = 0, ni, cn; ni = ns[i]; i++){
-                cn = ni.childNodes;
-                for(var j = 0, cj; cj = cn[j]; j++){
-                    if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
-                        result[++ri] = cj;
-                    }
-                }
-            }
-       
-       
-        }else if(mode == "+"){
-            var utag = tagName.toUpperCase();
-            for(var i = 0, n; n = ns[i]; i++){
-                while((n = n.nextSibling) && n.nodeType != 1);
-                if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
-                    result[++ri] = n;
-                }
-            }
-       
-       
-        }else if(mode == "~"){
-            var utag = tagName.toUpperCase();
-            for(var i = 0, n; n = ns[i]; i++){
-                while((n = n.nextSibling)){
-                    if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
-                        result[++ri] = n;
-                    }
-                }
-            }
-        }
-        return result;
-    }
+    constrain: function(number, min, max) {
+        number = parseFloat(number);
 
-    function concat(a, b){
-        if(b.slice){
-            return a.concat(b);
+        if (!isNaN(min)) {
+            number = Math.max(number, min);
         }
-        for(var i = 0, l = b.length; i < l; i++){
-            a[a.length] = b[i];
+        if (!isNaN(max)) {
+            number = Math.min(number, max);
         }
-        return a;
-    }
+        return number;
+    },
 
-    function byTag(cs, tagName){
-        if(cs.tagName || cs == document){
-            cs = [cs];
-        }
-        if(!tagName){
-            return cs;
+    
+    snap : function(value, increment, minValue, maxValue) {
+        var newValue = value,
+            m;
+
+        if (!(increment && value)) {
+            return value;
         }
-        var result = [], ri = -1;
-        tagName = tagName.toLowerCase();
-        for(var i = 0, ci; ci = cs[i]; i++){
-            if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
-                result[++ri] = ci;
+        m = value % increment;
+        if (m !== 0) {
+            newValue -= m;
+            if (m * 2 >= increment) {
+                newValue += increment;
+            } else if (m * 2 < -increment) {
+                newValue -= increment;
             }
         }
-        return result;
-    }
+        return Ext.Number.constrain(newValue, minValue,  maxValue);
+    },
 
-    function byId(cs, id){
-        if(cs.tagName || cs == document){
-            cs = [cs];
-        }
-        if(!id){
-            return cs;
+    
+    toFixed: function(value, precision) {
+        if (isToFixedBroken) {
+            precision = precision || 0;
+            var pow = Math.pow(10, precision);
+            return (Math.round(value * pow) / pow).toFixed(precision);
         }
-        var result = [], ri = -1;
-        for(var i = 0, ci; ci = cs[i]; i++){
-            if(ci && ci.id == id){
-                result[++ri] = ci;
-                return result;
-            }
+
+        return value.toFixed(precision);
+    },
+
+    
+    from: function(value, defaultValue) {
+        if (isFinite(value)) {
+            value = parseFloat(value);
         }
-        return result;
+
+        return !isNaN(value) ? value : defaultValue;
     }
+};
 
-    
-    
-    function byAttribute(cs, attr, value, op, custom){
-        var result = [], 
-            ri = -1, 
-            useGetStyle = custom == "{",           
-            fn = Ext.DomQuery.operators[op],       
-            a,
-            xml,
-            hasXml;
-            
-        for(var i = 0, ci; ci = cs[i]; i++){
-           
-            if(ci.nodeType != 1){
-                continue;
+})();
+
+
+Ext.num = function() {
+    return Ext.Number.from.apply(this, arguments);
+};
+
+(function() {
+
+    var arrayPrototype = Array.prototype,
+        slice = arrayPrototype.slice,
+        supportsSplice = function () {
+            var array = [],
+                lengthBefore,
+                j = 20;
+
+            if (!array.splice) {
+                return false;
             }
+
             
-            if(!hasXml){
-                xml = Ext.DomQuery.isXml(ci);
-                hasXml = true;
-            }
-           
             
-            if(!xml){
-                if(useGetStyle){
-                    a = Ext.DomQuery.getStyle(ci, attr);
-                } else if (attr == "class" || attr == "className"){
-                    a = ci.className;
-                } else if (attr == "for"){
-                    a = ci.htmlFor;
-                } else if (attr == "href"){
-                   
-                   
-                    a = ci.getAttribute("href", 2);
-                } else{
-                    a = ci.getAttribute(attr);
-                }
-            }else{
-                a = ci.getAttribute(attr);
+
+            while (j--) {
+                array.push("A");
             }
-            if((fn && fn(a, value)) || (!fn && a)){
-                result[++ri] = ci;
+
+            array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
+
+            lengthBefore = array.length; 
+            array.splice(13, 0, "XXX"); 
+
+            if (lengthBefore+1 != array.length) {
+                return false;
             }
+            
+
+            return true;
+        }(),
+        supportsForEach = 'forEach' in arrayPrototype,
+        supportsMap = 'map' in arrayPrototype,
+        supportsIndexOf = 'indexOf' in arrayPrototype,
+        supportsEvery = 'every' in arrayPrototype,
+        supportsSome = 'some' in arrayPrototype,
+        supportsFilter = 'filter' in arrayPrototype,
+        supportsSort = function() {
+            var a = [1,2,3,4,5].sort(function(){ return 0; });
+            return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
+        }(),
+        supportsSliceOnNodeList = true,
+        ExtArray;
+
+    try {
+        
+        if (typeof document !== 'undefined') {
+            slice.call(document.getElementsByTagName('body'));
         }
-        return result;
+    } catch (e) {
+        supportsSliceOnNodeList = false;
     }
 
-    function byPseudo(cs, name, value){
-        return Ext.DomQuery.pseudos[name](cs, value);
+    function fixArrayIndex (array, index) {
+        return (index < 0) ? Math.max(0, array.length + index)
+                           : Math.min(array.length, index);
     }
 
-    function nodupIEXml(cs){
-        var d = ++key, 
-            r;
-        cs[0].setAttribute("_nodup", d);
-        r = [cs[0]];
-        for(var i = 1, len = cs.length; i < len; i++){
-            var c = cs[i];
-            if(!c.getAttribute("_nodup") != d){
-                c.setAttribute("_nodup", d);
-                r[r.length] = c;
+    
+    function replaceSim (array, index, removeCount, insert) {
+        var add = insert ? insert.length : 0,
+            length = array.length,
+            pos = fixArrayIndex(array, index);
+
+        
+        if (pos === length) {
+            if (add) {
+                array.push.apply(array, insert);
             }
-        }
-        for(var i = 0, len = cs.length; i < len; i++){
-            cs[i].removeAttribute("_nodup");
-        }
-        return r;
-    }
+        } else {
+            var remove = Math.min(removeCount, length - pos),
+                tailOldPos = pos + remove,
+                tailNewPos = tailOldPos + add - remove,
+                tailCount = length - tailOldPos,
+                lengthAfterRemove = length - remove,
+                i;
 
-    function nodup(cs){
-        if(!cs){
-            return [];
-        }
-        var len = cs.length, c, i, r = cs, cj, ri = -1;
-        if(!len || typeof cs.nodeType != "undefined" || len == 1){
-            return cs;
-        }
-        if(isIE && typeof cs[0].selectSingleNode != "undefined"){
-            return nodupIEXml(cs);
-        }
-        var d = ++key;
-        cs[0]._nodup = d;
-        for(i = 1; c = cs[i]; i++){
-            if(c._nodup != d){
-                c._nodup = d;
-            }else{
-                r = [];
-                for(var j = 0; j < i; j++){
-                    r[++ri] = cs[j];
+            if (tailNewPos < tailOldPos) { 
+                for (i = 0; i < tailCount; ++i) {
+                    array[tailNewPos+i] = array[tailOldPos+i];
                 }
-                for(j = i+1; cj = cs[j]; j++){
-                    if(cj._nodup != d){
-                        cj._nodup = d;
-                        r[++ri] = cj;
-                    }
+            } else if (tailNewPos > tailOldPos) { 
+                for (i = tailCount; i--; ) {
+                    array[tailNewPos+i] = array[tailOldPos+i];
+                }
+            } 
+
+            if (add && pos === lengthAfterRemove) {
+                array.length = lengthAfterRemove; 
+                array.push.apply(array, insert);
+            } else {
+                array.length = lengthAfterRemove + add; 
+                for (i = 0; i < add; ++i) {
+                    array[pos+i] = insert[i];
                 }
-                return r;
             }
         }
-        return r;
+
+        return array;
     }
 
-    function quickDiffIEXml(c1, c2){
-        var d = ++key,
-            r = [];
-        for(var i = 0, len = c1.length; i < len; i++){
-            c1[i].setAttribute("_qdiff", d);
-        }        
-        for(var i = 0, len = c2.length; i < len; i++){
-            if(c2[i].getAttribute("_qdiff") != d){
-                r[r.length] = c2[i];
+    function replaceNative (array, index, removeCount, insert) {
+        if (insert && insert.length) {
+            if (index < array.length) {
+                array.splice.apply(array, [index, removeCount].concat(insert));
+            } else {
+                array.push.apply(array, insert);
             }
+        } else {
+            array.splice(index, removeCount);
         }
-        for(var i = 0, len = c1.length; i < len; i++){
-           c1[i].removeAttribute("_qdiff");
-        }
-        return r;
+        return array;
     }
 
-    function quickDiff(c1, c2){
-        var len1 = c1.length,
-               d = ++key,
-               r = [];
-        if(!len1){
-            return c2;
-        }
-        if(isIE && typeof c1[0].selectSingleNode != "undefined"){
-            return quickDiffIEXml(c1, c2);
-        }        
-        for(var i = 0; i < len1; i++){
-            c1[i]._qdiff = d;
-        }        
-        for(var i = 0, len = c2.length; i < len; i++){
-            if(c2[i]._qdiff != d){
-                r[r.length] = c2[i];
-            }
-        }
-        return r;
+    function eraseSim (array, index, removeCount) {
+        return replaceSim(array, index, removeCount);
     }
 
-    function quickId(ns, mode, root, id){
-        if(ns == root){
-           var d = root.ownerDocument || root;
-           return d.getElementById(id);
+    function eraseNative (array, index, removeCount) {
+        array.splice(index, removeCount);
+        return array;
+    }
+
+    function spliceSim (array, index, removeCount) {
+        var pos = fixArrayIndex(array, index),
+            removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
+
+        if (arguments.length < 4) {
+            replaceSim(array, pos, removeCount);
+        } else {
+            replaceSim(array, pos, removeCount, slice.call(arguments, 3));
         }
-        ns = getNodes(ns, mode, "*");
-        return byId(ns, id);
+
+        return removed;
     }
 
-    return {
-        getStyle : function(el, name){
-            return Ext.fly(el).getStyle(name);
-        },
+    function spliceNative (array) {
+        return array.splice.apply(array, slice.call(arguments, 1));
+    }
+
+    var erase = supportsSplice ? eraseNative : eraseSim,
+        replace = supportsSplice ? replaceNative : replaceSim,
+        splice = supportsSplice ? spliceNative : spliceSim;
+
+    
+
+    ExtArray = Ext.Array = {
         
-        compile : function(path, type){
-            type = type || "select";
+        each: function(array, fn, scope, reverse) {
+            array = ExtArray.from(array);
 
-           
-            var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
-                       mode,           
-                       lastPath,
-               matchers = Ext.DomQuery.matchers,
-               matchersLn = matchers.length,
-               modeMatch,
-               
-               lmode = path.match(modeRe);
-            
-            if(lmode && lmode[1]){
-                fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
-                path = path.replace(lmode[1], "");
-            }
-           
-            
-            while(path.substr(0, 1)=="/"){
-                path = path.substr(1);
-            }
+            var i,
+                ln = array.length;
 
-            while(path && lastPath != path){
-                lastPath = path;
-                var tokenMatch = path.match(tagTokenRe);
-                if(type == "select"){
-                    if(tokenMatch){
-                       
-                        if(tokenMatch[1] == "#"){
-                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';                        
-                        }else{
-                            fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
-                        }
-                        path = path.replace(tokenMatch[0], "");
-                    }else if(path.substr(0, 1) != '@'){
-                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
-                    }
-               
-                }else{
-                    if(tokenMatch){
-                        if(tokenMatch[1] == "#"){
-                            fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
-                        }else{
-                            fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
-                        }
-                        path = path.replace(tokenMatch[0], "");
+            if (reverse !== true) {
+                for (i = 0; i < ln; i++) {
+                    if (fn.call(scope || array[i], array[i], i, array) === false) {
+                        return i;
                     }
                 }
-                while(!(modeMatch = path.match(modeRe))){
-                    var matched = false;
-                    for(var j = 0; j < matchersLn; j++){
-                        var t = matchers[j];
-                        var m = path.match(t.re);
-                        if(m){
-                            fn[fn.length] = t.select.replace(tplRe, function(x, i){
-                               return m[i];
-                           });
-                            path = path.replace(m[0], "");
-                            matched = true;
-                            break;
-                        }
-                    }
-                    
-                    if(!matched){
-                        throw 'Error parsing selector, parsing failed at "' + path + '"';
+            }
+            else {
+                for (i = ln - 1; i > -1; i--) {
+                    if (fn.call(scope || array[i], array[i], i, array) === false) {
+                        return i;
                     }
                 }
-                if(modeMatch[1]){
-                    fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
-                    path = path.replace(modeMatch[1], "");
-                }
             }
-           
-            fn[fn.length] = "return nodup(n);\n}";
-           
-           
-            eval(fn.join(""));
-            return f;
+
+            return true;
         },
 
         
-       jsSelect: function(path, root, type){
-           
-           root = root || document;
-           
-            if(typeof root == "string"){
-                root = document.getElementById(root);
-            }
-            var paths = path.split(","),
-               results = [];
-               
-           
-            for(var i = 0, len = paths.length; i < len; i++){          
-                var subPath = paths[i].replace(trimRe, "");
-               
-                if(!cache[subPath]){
-                    cache[subPath] = Ext.DomQuery.compile(subPath);
-                    if(!cache[subPath]){
-                        throw subPath + " is not a valid selector";
-                    }
-                }
-                var result = cache[subPath](root);
-                if(result && result != document){
-                    results = results.concat(result);
-                }
+        forEach: function(array, fn, scope) {
+            if (supportsForEach) {
+                return array.forEach(fn, scope);
             }
-           
-           
-           
-            if(paths.length > 1){
-                return nodup(results);
+
+            var i = 0,
+                ln = array.length;
+
+            for (; i < ln; i++) {
+                fn.call(scope, array[i], i, array);
             }
-            return results;
         },
-       isXml: function(el) {
-           var docEl = (el ? el.ownerDocument || el : 0).documentElement;
-           return docEl ? docEl.nodeName !== "HTML" : false;
-       },
-        select : document.querySelectorAll ? function(path, root, type) {
-           root = root || document;
-           if (!Ext.DomQuery.isXml(root)) {
-               try {
-                   var cs = root.querySelectorAll(path);
-                   return Ext.toArray(cs);
-               }
-               catch (ex) {}           
-           }       
-           return Ext.DomQuery.jsSelect.call(this, path, root, type);
-       } : function(path, root, type) {
-           return Ext.DomQuery.jsSelect.call(this, path, root, type);
-       },
 
         
-        selectNode : function(path, root){
-            return Ext.DomQuery.select(path, root)[0];
+        indexOf: function(array, item, from) {
+            if (supportsIndexOf) {
+                return array.indexOf(item, from);
+            }
+
+            var i, length = array.length;
+
+            for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
+                if (array[i] === item) {
+                    return i;
+                }
+            }
+
+            return -1;
         },
 
         
-        selectValue : function(path, root, defaultValue){
-            path = path.replace(trimRe, "");
-            if(!valueCache[path]){
-                valueCache[path] = Ext.DomQuery.compile(path, "select");
+        contains: function(array, item) {
+            if (supportsIndexOf) {
+                return array.indexOf(item) !== -1;
             }
-            var n = valueCache[path](root), v;
-            n = n[0] ? n[0] : n;
-                   
-           
-           
-           
-           
-            if (typeof n.normalize == 'function') n.normalize();
-            
-            v = (n && n.firstChild ? n.firstChild.nodeValue : null);
-            return ((v === null||v === undefined||v==='') ? defaultValue : v);
+
+            var i, ln;
+
+            for (i = 0, ln = array.length; i < ln; i++) {
+                if (array[i] === item) {
+                    return true;
+                }
+            }
+
+            return false;
         },
 
         
-        selectNumber : function(path, root, defaultValue){
-            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
-            return parseFloat(v);
+        toArray: function(iterable, start, end){
+            if (!iterable || !iterable.length) {
+                return [];
+            }
+
+            if (typeof iterable === 'string') {
+                iterable = iterable.split('');
+            }
+
+            if (supportsSliceOnNodeList) {
+                return slice.call(iterable, start || 0, end || iterable.length);
+            }
+
+            var array = [],
+                i;
+
+            start = start || 0;
+            end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
+
+            for (i = start; i < end; i++) {
+                array.push(iterable[i]);
+            }
+
+            return array;
         },
 
         
-        is : function(el, ss){
-            if(typeof el == "string"){
-                el = document.getElementById(el);
+        pluck: function(array, propertyName) {
+            var ret = [],
+                i, ln, item;
+
+            for (i = 0, ln = array.length; i < ln; i++) {
+                item = array[i];
+
+                ret.push(item[propertyName]);
             }
-            var isArray = Ext.isArray(el),
-               result = Ext.DomQuery.filter(isArray ? el : [el], ss);
-            return isArray ? (result.length == el.length) : (result.length > 0);
+
+            return ret;
         },
 
         
-        filter : function(els, ss, nonMatches){
-            ss = ss.replace(trimRe, "");
-            if(!simpleCache[ss]){
-                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
+        map: function(array, fn, scope) {
+            if (supportsMap) {
+                return array.map(fn, scope);
             }
-            var result = simpleCache[ss](els);
-            return nonMatches ? quickDiff(result, els) : result;
+
+            var results = [],
+                i = 0,
+                len = array.length;
+
+            for (; i < len; i++) {
+                results[i] = fn.call(scope, array[i], i, array);
+            }
+
+            return results;
         },
 
         
-        matchers : [{
-                re: /^\.([\w-]+)/,
-                select: 'n = byClassName(n, " {1} ");'
-            }, {
-                re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
-                select: 'n = byPseudo(n, "{1}", "{2}");'
-            },{
-                re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
-                select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
-            }, {
-                re: /^#([\w-]+)/,
-                select: 'n = byId(n, "{1}");'
-            },{
-                re: /^@([\w-]+)/,
-                select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
+        every: function(array, fn, scope) {
+            if (supportsEvery) {
+                return array.every(fn, scope);
             }
-        ],
+
+            var i = 0,
+                ln = array.length;
+
+            for (; i < ln; ++i) {
+                if (!fn.call(scope, array[i], i, array)) {
+                    return false;
+                }
+            }
+
+            return true;
+        },
 
         
-        operators : {
-            "=" : function(a, v){
-                return a == v;
-            },
-            "!=" : function(a, v){
-                return a != v;
-            },
-            "^=" : function(a, v){
-                return a && a.substr(0, v.length) == v;
-            },
-            "$=" : function(a, v){
-                return a && a.substr(a.length-v.length) == v;
-            },
-            "*=" : function(a, v){
-                return a && a.indexOf(v) !== -1;
-            },
-            "%=" : function(a, v){
-                return (a % v) == 0;
-            },
-            "|=" : function(a, v){
-                return a && (a == v || a.substr(0, v.length+1) == v+'-');
-            },
-            "~=" : function(a, v){
-                return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
+        some: function(array, fn, scope) {
+            if (supportsSome) {
+                return array.some(fn, scope);
+            }
+
+            var i = 0,
+                ln = array.length;
+
+            for (; i < ln; ++i) {
+                if (fn.call(scope, array[i], i, array)) {
+                    return true;
+                }
             }
+
+            return false;
         },
 
         
-        pseudos : {
-            "first-child" : function(c){
-                var r = [], ri = -1, n;
-                for(var i = 0, ci; ci = n = c[i]; i++){
-                    while((n = n.previousSibling) && n.nodeType != 1);
-                    if(!n){
-                        r[++ri] = ci;
-                    }
+        clean: function(array) {
+            var results = [],
+                i = 0,
+                ln = array.length,
+                item;
+
+            for (; i < ln; i++) {
+                item = array[i];
+
+                if (!Ext.isEmpty(item)) {
+                    results.push(item);
                 }
-                return r;
-            },
+            }
 
-            "last-child" : function(c){
-                var r = [], ri = -1, n;
-                for(var i = 0, ci; ci = n = c[i]; i++){
-                    while((n = n.nextSibling) && n.nodeType != 1);
-                    if(!n){
-                        r[++ri] = ci;
-                    }
+            return results;
+        },
+
+        
+        unique: function(array) {
+            var clone = [],
+                i = 0,
+                ln = array.length,
+                item;
+
+            for (; i < ln; i++) {
+                item = array[i];
+
+                if (ExtArray.indexOf(clone, item) === -1) {
+                    clone.push(item);
                 }
-                return r;
-            },
+            }
 
-            "nth-child" : function(c, a) {
-                var r = [], ri = -1,
-                       m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
-                       f = (m[1] || 1) - 0, l = m[2] - 0;
-                for(var i = 0, n; n = c[i]; i++){
-                    var pn = n.parentNode;
-                    if (batch != pn._batch) {
-                        var j = 0;
-                        for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
-                            if(cn.nodeType == 1){
-                               cn.nodeIndex = ++j;
-                            }
-                        }
-                        pn._batch = batch;
-                    }
-                    if (f == 1) {
-                        if (l == 0 || n.nodeIndex == l){
-                            r[++ri] = n;
-                        }
-                    } else if ((n.nodeIndex + l) % f == 0){
-                        r[++ri] = n;
-                    }
+            return clone;
+        },
+
+        
+        filter: function(array, fn, scope) {
+            if (supportsFilter) {
+                return array.filter(fn, scope);
+            }
+
+            var results = [],
+                i = 0,
+                ln = array.length;
+
+            for (; i < ln; i++) {
+                if (fn.call(scope, array[i], i, array)) {
+                    results.push(array[i]);
                 }
+            }
 
-                return r;
-            },
+            return results;
+        },
 
-            "only-child" : function(c){
-                var r = [], ri = -1;;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    if(!prev(ci) && !next(ci)){
-                        r[++ri] = ci;
-                    }
+        
+        from: function(value, newReference) {
+            if (value === undefined || value === null) {
+                return [];
+            }
+
+            if (Ext.isArray(value)) {
+                return (newReference) ? slice.call(value) : value;
+            }
+
+            if (value && value.length !== undefined && typeof value !== 'string') {
+                return Ext.toArray(value);
+            }
+
+            return [value];
+        },
+
+        
+        remove: function(array, item) {
+            var index = ExtArray.indexOf(array, item);
+
+            if (index !== -1) {
+                erase(array, index, 1);
+            }
+
+            return array;
+        },
+
+        
+        include: function(array, item) {
+            if (!ExtArray.contains(array, item)) {
+                array.push(item);
+            }
+        },
+
+        
+        clone: function(array) {
+            return slice.call(array);
+        },
+
+        
+        merge: function() {
+            var args = slice.call(arguments),
+                array = [],
+                i, ln;
+
+            for (i = 0, ln = args.length; i < ln; i++) {
+                array = array.concat(args[i]);
+            }
+
+            return ExtArray.unique(array);
+        },
+
+        
+        intersect: function() {
+            var intersect = [],
+                arrays = slice.call(arguments),
+                i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
+
+            if (!arrays.length) {
+                return intersect;
+            }
+
+            
+            for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
+                if (!minArray || array.length < minArray.length) {
+                    minArray = array;
+                    x = i;
                 }
-                return r;
-            },
+            }
 
-            "empty" : function(c){
-                var r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    var cns = ci.childNodes, j = 0, cn, empty = true;
-                    while(cn = cns[j]){
-                        ++j;
-                        if(cn.nodeType == 1 || cn.nodeType == 3){
-                            empty = false;
+            minArray = ExtArray.unique(minArray);
+            erase(arrays, x, 1);
+
+            
+            
+            
+            for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
+                var count = 0;
+
+                for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
+                    for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
+                        if (x === y) {
+                            count++;
                             break;
                         }
                     }
-                    if(empty){
-                        r[++ri] = ci;
-                    }
                 }
-                return r;
-            },
 
-            "contains" : function(c, v){
-                var r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
-                        r[++ri] = ci;
-                    }
+                if (count === arraysLn) {
+                    intersect.push(x);
                 }
-                return r;
-            },
+            }
 
-            "nodeValue" : function(c, v){
-                var r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    if(ci.firstChild && ci.firstChild.nodeValue == v){
-                        r[++ri] = ci;
+            return intersect;
+        },
+
+        
+        difference: function(arrayA, arrayB) {
+            var clone = slice.call(arrayA),
+                ln = clone.length,
+                i, j, lnB;
+
+            for (i = 0,lnB = arrayB.length; i < lnB; i++) {
+                for (j = 0; j < ln; j++) {
+                    if (clone[j] === arrayB[i]) {
+                        erase(clone, j, 1);
+                        j--;
+                        ln--;
                     }
                 }
-                return r;
-            },
+            }
 
-            "checked" : function(c){
-                var r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    if(ci.checked == true){
-                        r[++ri] = ci;
-                    }
+            return clone;
+        },
+
+        
+        
+        slice: ([1,2].slice(1, undefined).length ?
+            function (array, begin, end) {
+                return slice.call(array, begin, end);
+            } :
+            
+            function (array, begin, end) {
+                
+                
+                if (typeof begin === 'undefined') {
+                    return slice.call(array);
                 }
-                return r;
-            },
+                if (typeof end === 'undefined') {
+                    return slice.call(array, begin);
+                }
+                return slice.call(array, begin, end);
+            }
+        ),
 
-            "not" : function(c, ss){
-                return Ext.DomQuery.filter(c, ss, true);
-            },
+        
+        sort: function(array, sortFn) {
+            if (supportsSort) {
+                if (sortFn) {
+                    return array.sort(sortFn);
+                } else {
+                    return array.sort();
+                }
+            }
 
-            "any" : function(c, selectors){
-                var ss = selectors.split('|'),
-                       r = [], ri = -1, s;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    for(var j = 0; s = ss[j]; j++){
-                        if(Ext.DomQuery.is(ci, s)){
-                            r[++ri] = ci;
-                            break;
+            var length = array.length,
+                i = 0,
+                comparison,
+                j, min, tmp;
+
+            for (; i < length; i++) {
+                min = i;
+                for (j = i + 1; j < length; j++) {
+                    if (sortFn) {
+                        comparison = sortFn(array[j], array[min]);
+                        if (comparison < 0) {
+                            min = j;
                         }
+                    } else if (array[j] < array[min]) {
+                        min = j;
                     }
                 }
-                return r;
-            },
-
-            "odd" : function(c){
-                return this["nth-child"](c, "odd");
-            },
+                if (min !== i) {
+                    tmp = array[i];
+                    array[i] = array[min];
+                    array[min] = tmp;
+                }
+            }
 
-            "even" : function(c){
-                return this["nth-child"](c, "even");
-            },
+            return array;
+        },
 
-            "nth" : function(c, a){
-                return c[a-1] || [];
-            },
+        
+        flatten: function(array) {
+            var worker = [];
 
-            "first" : function(c){
-                return c[0] || [];
-            },
+            function rFlatten(a) {
+                var i, ln, v;
 
-            "last" : function(c){
-                return c[c.length-1] || [];
-            },
+                for (i = 0, ln = a.length; i < ln; i++) {
+                    v = a[i];
 
-            "has" : function(c, ss){
-                var s = Ext.DomQuery.select,
-                       r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    if(s(ss, ci).length > 0){
-                        r[++ri] = ci;
+                    if (Ext.isArray(v)) {
+                        rFlatten(v);
+                    } else {
+                        worker.push(v);
                     }
                 }
-                return r;
-            },
 
-            "next" : function(c, ss){
-                var is = Ext.DomQuery.is,
-                       r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    var n = next(ci);
-                    if(n && is(n, ss)){
-                        r[++ri] = ci;
+                return worker;
+            }
+
+            return rFlatten(array);
+        },
+
+        
+        min: function(array, comparisonFn) {
+            var min = array[0],
+                i, ln, item;
+
+            for (i = 0, ln = array.length; i < ln; i++) {
+                item = array[i];
+
+                if (comparisonFn) {
+                    if (comparisonFn(min, item) === 1) {
+                        min = item;
                     }
                 }
-                return r;
-            },
+                else {
+                    if (item < min) {
+                        min = item;
+                    }
+                }
+            }
 
-            "prev" : function(c, ss){
-                var is = Ext.DomQuery.is,
-                       r = [], ri = -1;
-                for(var i = 0, ci; ci = c[i]; i++){
-                    var n = prev(ci);
-                    if(n && is(n, ss)){
-                        r[++ri] = ci;
+            return min;
+        },
+
+        
+        max: function(array, comparisonFn) {
+            var max = array[0],
+                i, ln, item;
+
+            for (i = 0, ln = array.length; i < ln; i++) {
+                item = array[i];
+
+                if (comparisonFn) {
+                    if (comparisonFn(max, item) === -1) {
+                        max = item;
+                    }
+                }
+                else {
+                    if (item > max) {
+                        max = item;
                     }
                 }
-                return r;
             }
-        }
-    };
-}();
 
+            return max;
+        },
 
-Ext.query = Ext.DomQuery.select;
+        
+        mean: function(array) {
+            return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
+        },
 
-Ext.util.DelayedTask = function(fn, scope, args){
-    var me = this,
-       id,     
-       call = function(){
-               clearInterval(id);
-               id = null;
-               fn.apply(scope, args || []);
-           };
-           
-    
-    me.delay = function(delay, newFn, newScope, newArgs){
-        me.cancel();
-        fn = newFn || fn;
-        scope = newScope || scope;
-        args = newArgs || args;
-        id = setInterval(call, delay);
+        
+        sum: function(array) {
+            var sum = 0,
+                i, ln, item;
+
+            for (i = 0,ln = array.length; i < ln; i++) {
+                item = array[i];
+
+                sum += item;
+            }
+
+            return sum;
+        },
+
+
+        
+        erase: erase,
+
+        
+        insert: function (array, index, items) {
+            return replace(array, index, 0, items);
+        },
+
+        
+        replace: replace,
+
+        
+        splice: splice
     };
 
     
-    me.cancel = function(){
-        if(id){
-            clearInterval(id);
-            id = null;
-        }
-    };
-};(function(){
+    Ext.each = ExtArray.each;
 
-var EXTUTIL = Ext.util,
-    EACH = Ext.each,
-    TRUE = true,
-    FALSE = false;
+    
+    ExtArray.union = ExtArray.merge;
 
-EXTUTIL.Observable = function(){
     
-    var me = this, e = me.events;
-    if(me.listeners){
-        me.on(me.listeners);
-        delete me.listeners;
-    }
-    me.events = e || {};
-};
+    Ext.min = ExtArray.min;
 
-EXTUTIL.Observable.prototype = {
     
-    filterOptRe : /^(?:scope|delay|buffer|single)$/,
+    Ext.max = ExtArray.max;
 
     
-    fireEvent : function(){
-        var a = Array.prototype.slice.call(arguments, 0),
-            ename = a[0].toLowerCase(),
-            me = this,
-            ret = TRUE,
-            ce = me.events[ename],
-            cc,
-            q,
-            c;
-        if (me.eventsSuspended === TRUE) {
-            if (q = me.eventQueue) {
-                q.push(a);
+    Ext.sum = ExtArray.sum;
+
+    
+    Ext.mean = ExtArray.mean;
+
+    
+    Ext.flatten = ExtArray.flatten;
+
+    
+    Ext.clean = ExtArray.clean;
+
+    
+    Ext.unique = ExtArray.unique;
+
+    
+    Ext.pluck = ExtArray.pluck;
+
+    
+    Ext.toArray = function() {
+        return ExtArray.toArray.apply(ExtArray, arguments);
+    };
+})();
+
+
+Ext.Function = {
+
+    
+    flexSetter: function(fn) {
+        return function(a, b) {
+            var k, i;
+
+            if (a === null) {
+                return this;
             }
-        }
-        else if(typeof ce == 'object') {
-            if (ce.bubble){
-                if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
-                    return FALSE;
+
+            if (typeof a !== 'string') {
+                for (k in a) {
+                    if (a.hasOwnProperty(k)) {
+                        fn.call(this, k, a[k]);
+                    }
                 }
-                c = me.getBubbleTarget && me.getBubbleTarget();
-                if(c && c.enableBubble) {
-                    cc = c.events[ename];
-                    if(!cc || typeof cc != 'object' || !cc.bubble) {
-                        c.enableBubble(ename);
+
+                if (Ext.enumerables) {
+                    for (i = Ext.enumerables.length; i--;) {
+                        k = Ext.enumerables[i];
+                        if (a.hasOwnProperty(k)) {
+                            fn.call(this, k, a[k]);
+                        }
                     }
-                    return c.fireEvent.apply(c, a);
                 }
+            } else {
+                fn.call(this, a, b);
             }
-            else {
-                a.shift();
-                ret = ce.fire.apply(ce, a);
-            }
-        }
-        return ret;
+
+            return this;
+        };
     },
 
     
-    addListener : function(eventName, fn, scope, o){
-        var me = this,
-            e,
-            oe,
-            ce;
-            
-        if (typeof eventName == 'object') {
-            o = eventName;
-            for (e in o) {
-                oe = o[e];
-                if (!me.filterOptRe.test(e)) {
-                    me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
-                }
-            }
-        } else {
-            eventName = eventName.toLowerCase();
-            ce = me.events[eventName] || TRUE;
-            if (typeof ce == 'boolean') {
-                me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
+    bind: function(fn, scope, args, appendArgs) {
+        if (arguments.length === 2) {
+            return function() {
+                return fn.apply(scope, arguments);
             }
-            ce.addListener(fn, scope, typeof o == 'object' ? o : {});
         }
+
+        var method = fn,
+            slice = Array.prototype.slice;
+
+        return function() {
+            var callArgs = args || arguments;
+
+            if (appendArgs === true) {
+                callArgs = slice.call(arguments, 0);
+                callArgs = callArgs.concat(args);
+            }
+            else if (typeof appendArgs == 'number') {
+                callArgs = slice.call(arguments, 0); 
+                Ext.Array.insert(callArgs, appendArgs, args);
+            }
+
+            return method.apply(scope || window, callArgs);
+        };
     },
 
     
-    removeListener : function(eventName, fn, scope){
-        var ce = this.events[eventName.toLowerCase()];
-        if (typeof ce == 'object') {
-            ce.removeListener(fn, scope);
+    pass: function(fn, args, scope) {
+        if (args) {
+            args = Ext.Array.from(args);
         }
+
+        return function() {
+            return fn.apply(scope, args.concat(Ext.Array.toArray(arguments)));
+        };
     },
 
     
-    purgeListeners : function(){
-        var events = this.events,
-            evt,
-            key;
-        for(key in events){
-            evt = events[key];
-            if(typeof evt == 'object'){
-                evt.clearListeners();
-            }
+    alias: function(object, methodName) {
+        return function() {
+            return object[methodName].apply(object, arguments);
+        };
+    },
+
+    
+    createInterceptor: function(origFn, newFn, scope, returnValue) {
+        var method = origFn;
+        if (!Ext.isFunction(newFn)) {
+            return origFn;
+        }
+        else {
+            return function() {
+                var me = this,
+                    args = arguments;
+                newFn.target = me;
+                newFn.method = origFn;
+                return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
+            };
         }
     },
 
     
-    addEvents : function(o){
-        var me = this;
-        me.events = me.events || {};
-        if (typeof o == 'string') {
-            var a = arguments,
-                i = a.length;
-            while(i--) {
-                me.events[a[i]] = me.events[a[i]] || TRUE;
-            }
-        } else {
-            Ext.applyIf(me.events, o);
+    createDelayed: function(fn, delay, scope, args, appendArgs) {
+        if (scope || args) {
+            fn = Ext.Function.bind(fn, scope, args, appendArgs);
         }
+        return function() {
+            var me = this;
+            setTimeout(function() {
+                fn.apply(me, arguments);
+            }, delay);
+        };
     },
 
     
-    hasListener : function(eventName){
-        var e = this.events[eventName.toLowerCase()];
-        return typeof e == 'object' && e.listeners.length > 0;
+    defer: function(fn, millis, obj, args, appendArgs) {
+        fn = Ext.Function.bind(fn, obj, args, appendArgs);
+        if (millis > 0) {
+            return setTimeout(fn, millis);
+        }
+        fn();
+        return 0;
     },
 
     
-    suspendEvents : function(queueSuspended){
-        this.eventsSuspended = TRUE;
-        if(queueSuspended && !this.eventQueue){
-            this.eventQueue = [];
+    createSequence: function(origFn, newFn, scope) {
+        if (!Ext.isFunction(newFn)) {
+            return origFn;
+        }
+        else {
+            return function() {
+                var retval = origFn.apply(this || window, arguments);
+                newFn.apply(scope || this || window, arguments);
+                return retval;
+            };
         }
     },
 
     
-    resumeEvents : function(){
-        var me = this,
-            queued = me.eventQueue || [];
-        me.eventsSuspended = FALSE;
-        delete me.eventQueue;
-        EACH(queued, function(e) {
-            me.fireEvent.apply(me, e);
-        });
-    }
-};
+    createBuffered: function(fn, buffer, scope, args) {
+        return function(){
+            var timerId;
+            return function() {
+                var me = this;
+                if (timerId) {
+                    clearTimeout(timerId);
+                    timerId = null;
+                }
+                timerId = setTimeout(function(){
+                    fn.apply(scope || me, args || arguments);
+                }, buffer);
+            };
+        }();
+    },
 
-var OBSERVABLE = EXTUTIL.Observable.prototype;
+    
+    createThrottled: function(fn, interval, scope) {
+        var lastCallTime, elapsed, lastArgs, timer, execute = function() {
+            fn.apply(scope || this, lastArgs);
+            lastCallTime = new Date().getTime();
+        };
 
-OBSERVABLE.on = OBSERVABLE.addListener;
+        return function() {
+            elapsed = new Date().getTime() - lastCallTime;
+            lastArgs = arguments;
 
-OBSERVABLE.un = OBSERVABLE.removeListener;
+            clearTimeout(timer);
+            if (!lastCallTime || (elapsed >= interval)) {
+                execute();
+            } else {
+                timer = setTimeout(execute, interval - elapsed);
+            }
+        };
+    },
 
+    
+    interceptBefore: function(object, methodName, fn) {
+        var method = object[methodName] || Ext.emptyFn;
 
-EXTUTIL.Observable.releaseCapture = function(o){
-    o.fireEvent = OBSERVABLE.fireEvent;
-};
+        return object[methodName] = function() {
+            var ret = fn.apply(this, arguments);
+            method.apply(this, arguments);
 
-function createTargeted(h, o, scope){
-    return function(){
-        if(o.target == arguments[0]){
-            h.apply(scope, Array.prototype.slice.call(arguments, 0));
-        }
-    };
-};
+            return ret;
+        };
+    },
 
-function createBuffered(h, o, l, scope){
-    l.task = new EXTUTIL.DelayedTask();
-    return function(){
-        l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
-    };
-};
+    
+    interceptAfter: function(object, methodName, fn) {
+        var method = object[methodName] || Ext.emptyFn;
 
-function createSingle(h, e, fn, scope){
-    return function(){
-        e.removeListener(fn, scope);
-        return h.apply(scope, arguments);
-    };
+        return object[methodName] = function() {
+            method.apply(this, arguments);
+            return fn.apply(this, arguments);
+        };
+    }
 };
 
-function createDelayed(h, o, l, scope){
-    return function(){
-        var task = new EXTUTIL.DelayedTask();
-        if(!l.tasks) {
-            l.tasks = [];
-        }
-        l.tasks.push(task);
-        task.delay(o.delay || 10, h, scope, Array.prototype.slice.call(arguments, 0));
-    };
-};
 
-EXTUTIL.Event = function(obj, name){
-    this.name = name;
-    this.obj = obj;
-    this.listeners = [];
-};
+Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
 
-EXTUTIL.Event.prototype = {
-    addListener : function(fn, scope, options){
-        var me = this,
-            l;
-        scope = scope || me.obj;
-        if(!me.isListening(fn, scope)){
-            l = me.createListener(fn, scope, options);
-            if(me.firing){ 
-                me.listeners = me.listeners.slice(0);
-            }
-            me.listeners.push(l);
-        }
-    },
 
-    createListener: function(fn, scope, o){
-        o = o || {};
-        scope = scope || this.obj;
-        var l = {
-            fn: fn,
-            scope: scope,
-            options: o
-        }, h = fn;
-        if(o.target){
-            h = createTargeted(h, o, scope);
-        }
-        if(o.delay){
-            h = createDelayed(h, o, l, scope);
-        }
-        if(o.single){
-            h = createSingle(h, this, fn, scope);
-        }
-        if(o.buffer){
-            h = createBuffered(h, o, l, scope);
-        }
-        l.fireFn = h;
-        return l;
-    },
+Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
 
-    findListener : function(fn, scope){
-        var list = this.listeners,
-            i = list.length,
-            l;
 
-        scope = scope || this.obj;
-        while(i--){
-            l = list[i];
-            if(l){
-                if(l.fn == fn && l.scope == scope){
-                    return i;
-                }
-            }
-        }
-        return -1;
-    },
+Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
 
-    isListening : function(fn, scope){
-        return this.findListener(fn, scope) != -1;
-    },
 
-    removeListener : function(fn, scope){
-        var index,
-            l,
-            k,
-            me = this,
-            ret = FALSE;
-        if((index = me.findListener(fn, scope)) != -1){
-            if (me.firing) {
-                me.listeners = me.listeners.slice(0);
-            }
-            l = me.listeners[index];
-            if(l.task) {
-                l.task.cancel();
-                delete l.task;
+
+(function() {
+
+var ExtObject = Ext.Object = {
+
+    
+    toQueryObjects: function(name, value, recursive) {
+        var self = ExtObject.toQueryObjects,
+            objects = [],
+            i, ln;
+
+        if (Ext.isArray(value)) {
+            for (i = 0, ln = value.length; i < ln; i++) {
+                if (recursive) {
+                    objects = objects.concat(self(name + '[' + i + ']', value[i], true));
+                }
+                else {
+                    objects.push({
+                        name: name,
+                        value: value[i]
+                    });
+                }
             }
-            k = l.tasks && l.tasks.length;
-            if(k) {
-                while(k--) {
-                    l.tasks[k].cancel();
+        }
+        else if (Ext.isObject(value)) {
+            for (i in value) {
+                if (value.hasOwnProperty(i)) {
+                    if (recursive) {
+                        objects = objects.concat(self(name + '[' + i + ']', value[i], true));
+                    }
+                    else {
+                        objects.push({
+                            name: name,
+                            value: value[i]
+                        });
+                    }
                 }
-                delete l.tasks;
             }
-            me.listeners.splice(index, 1);
-            ret = TRUE;
         }
-        return ret;
+        else {
+            objects.push({
+                name: name,
+                value: value
+            });
+        }
+
+        return objects;
     },
 
     
-    clearListeners : function(){
-        var me = this,
-            l = me.listeners,
-            i = l.length;
-        while(i--) {
-            me.removeListener(l[i].fn, l[i].scope);
+    toQueryString: function(object, recursive) {
+        var paramObjects = [],
+            params = [],
+            i, j, ln, paramObject, value;
+
+        for (i in object) {
+            if (object.hasOwnProperty(i)) {
+                paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
+            }
         }
-    },
 
-    fire : function(){
-        var me = this,
-            listeners = me.listeners,
-            len = listeners.length,
-            i = 0,
-            l;
+        for (j = 0, ln = paramObjects.length; j < ln; j++) {
+            paramObject = paramObjects[j];
+            value = paramObject.value;
 
-        if(len > 0){
-            me.firing = TRUE;
-            var args = Array.prototype.slice.call(arguments, 0);
-            for (; i < len; i++) {
-                l = listeners[i];
-                if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
-                    return (me.firing = FALSE);
-                }
+            if (Ext.isEmpty(value)) {
+                value = '';
             }
+            else if (Ext.isDate(value)) {
+                value = Ext.Date.toString(value);
+            }
+
+            params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
         }
-        me.firing = FALSE;
-        return TRUE;
-    }
 
-};
-})();
+        return params.join('&');
+    },
 
-Ext.apply(Ext.util.Observable.prototype, function(){
-    
-    
     
-    function getMethodEvent(method){
-        var e = (this.methodEvents = this.methodEvents ||
-        {})[method], returnValue, v, cancel, obj = this;
+    fromQueryString: function(queryString, recursive) {
+        var parts = queryString.replace(/^\?/, '').split('&'),
+            object = {},
+            temp, components, name, value, i, ln,
+            part, j, subLn, matchedKeys, matchedName,
+            keys, key, nextKey;
 
-        if (!e) {
-            this.methodEvents[method] = e = {};
-            e.originalFn = this[method];
-            e.methodName = method;
-            e.before = [];
-            e.after = [];
+        for (i = 0, ln = parts.length; i < ln; i++) {
+            part = parts[i];
 
-            var makeCall = function(fn, scope, args){
-                if((v = fn.apply(scope || obj, args)) !== undefined){
-                    if (typeof v == 'object') {
-                        if(v.returnValue !== undefined){
-                            returnValue = v.returnValue;
-                        }else{
-                            returnValue = v;
+            if (part.length > 0) {
+                components = part.split('=');
+                name = decodeURIComponent(components[0]);
+                value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
+
+                if (!recursive) {
+                    if (object.hasOwnProperty(name)) {
+                        if (!Ext.isArray(object[name])) {
+                            object[name] = [object[name]];
                         }
-                        cancel = !!v.cancel;
+
+                        object[name].push(value);
+                    }
+                    else {
+                        object[name] = value;
                     }
-                    else
-                        if (v === false) {
-                            cancel = true;
-                        }
-                        else {
-                            returnValue = v;
-                        }
                 }
-            };
+                else {
+                    matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
+                    matchedName = name.match(/^([^\[]+)/);
 
-            this[method] = function(){
-                var args = Array.prototype.slice.call(arguments, 0),
-                    b;
-                returnValue = v = undefined;
-                cancel = false;
 
-                for(var i = 0, len = e.before.length; i < len; i++){
-                    b = e.before[i];
-                    makeCall(b.fn, b.scope, args);
-                    if (cancel) {
-                        return returnValue;
-                    }
-                }
+                    name = matchedName[0];
+                    keys = [];
 
-                if((v = e.originalFn.apply(obj, args)) !== undefined){
-                    returnValue = v;
-                }
+                    if (matchedKeys === null) {
+                        object[name] = value;
+                        continue;
+                    }
 
-                for(var i = 0, len = e.after.length; i < len; i++){
-                    b = e.after[i];
-                    makeCall(b.fn, b.scope, args);
-                    if (cancel) {
-                        return returnValue;
+                    for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
+                        key = matchedKeys[j];
+                        key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
+                        keys.push(key);
                     }
-                }
-                return returnValue;
-            };
-        }
-        return e;
-    }
 
-    return {
-        
-        
-        
-        beforeMethod : function(method, fn, scope){
-            getMethodEvent.call(this, method).before.push({
-                fn: fn,
-                scope: scope
-            });
-        },
+                    keys.unshift(name);
 
-        
-        afterMethod : function(method, fn, scope){
-            getMethodEvent.call(this, method).after.push({
-                fn: fn,
-                scope: scope
-            });
-        },
+                    temp = object;
 
-        removeMethodListener: function(method, fn, scope){
-            var e = this.getMethodEvent(method);
-            for(var i = 0, len = e.before.length; i < len; i++){
-                if(e.before[i].fn == fn && e.before[i].scope == scope){
-                    e.before.splice(i, 1);
-                    return;
-                }
-            }
-            for(var i = 0, len = e.after.length; i < len; i++){
-                if(e.after[i].fn == fn && e.after[i].scope == scope){
-                    e.after.splice(i, 1);
-                    return;
-                }
-            }
-        },
+                    for (j = 0, subLn = keys.length; j < subLn; j++) {
+                        key = keys[j];
 
-        
-        relayEvents : function(o, events){
-            var me = this;
-            function createHandler(ename){
-                return function(){
-                    return me.fireEvent.apply(me, [ename].concat(Array.prototype.slice.call(arguments, 0)));
-                };
-            }
-            for(var i = 0, len = events.length; i < len; i++){
-                var ename = events[i];
-                me.events[ename] = me.events[ename] || true;
-                o.on(ename, createHandler(ename), me);
-            }
-        },
+                        if (j === subLn - 1) {
+                            if (Ext.isArray(temp) && key === '') {
+                                temp.push(value);
+                            }
+                            else {
+                                temp[key] = value;
+                            }
+                        }
+                        else {
+                            if (temp[key] === undefined || typeof temp[key] === 'string') {
+                                nextKey = keys[j+1];
 
-        
-        enableBubble : function(events){
-            var me = this;
-            if(!Ext.isEmpty(events)){
-                events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
-                for(var i = 0, len = events.length; i < len; i++){
-                    var ename = events[i];
-                    ename = ename.toLowerCase();
-                    var ce = me.events[ename] || true;
-                    if (typeof ce == 'boolean') {
-                        ce = new Ext.util.Event(me, ename);
-                        me.events[ename] = ce;
+                                temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
+                            }
+
+                            temp = temp[key];
+                        }
                     }
-                    ce.bubble = true;
                 }
             }
         }
-    };
-}());
-
-
 
-Ext.util.Observable.capture = function(o, fn, scope){
-    o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
-};
-
-
-
-Ext.util.Observable.observeClass = function(c, listeners){
-    if(c){
-      if(!c.fireEvent){
-          Ext.apply(c, new Ext.util.Observable());
-          Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
-      }
-      if(typeof listeners == 'object'){
-          c.on(listeners);
-      }
-      return c;
-   }
-};
-
-
-Ext.EventManager = function(){
-    var docReadyEvent,
-        docReadyProcId,
-        docReadyState = false,
-        DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
-        E = Ext.lib.Event,
-        D = Ext.lib.Dom,
-        DOC = document,
-        WINDOW = window,
-        DOMCONTENTLOADED = "DOMContentLoaded",
-        COMPLETE = 'complete',
-        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
-        
-        specialElCache = [];
+        return object;
+    },
 
-     function getId(el){
-        var id = false,
-            i = 0,
-            len = specialElCache.length,
-            id = false,
-            skip = false,
-            o;
-        if(el){
-            if(el.getElementById || el.navigator){
-                
-                for(; i < len; ++i){
-                    o = specialElCache[i];
-                    if(o.el === el){
-                        id = o.id;
-                        break;
-                    }
-                }
-                if(!id){
-                    
-                    id = Ext.id(el);
-                    specialElCache.push({
-                        id: id,
-                        el: el
-                    });
-                    skip = true;
-                }
-            }else{
-                id = Ext.id(el);
-            }
-            if(!Ext.elCache[id]){
-                Ext.Element.addToCache(new Ext.Element(el), id);
-                if(skip){
-                    Ext.elCache[id].skipGC = true;
+    
+    each: function(object, fn, scope) {
+        for (var property in object) {
+            if (object.hasOwnProperty(property)) {
+                if (fn.call(scope || object, property, object[property], object) === false) {
+                    return;
                 }
             }
         }
-        return id;
-     };
+    },
 
     
-    function addListener(el, ename, fn, task, wrap, scope){
-        el = Ext.getDom(el);
-        var id = getId(el),
-            es = Ext.elCache[id].events,
-            wfn;
+    merge: function(source, key, value) {
+        if (typeof key === 'string') {
+            if (value && value.constructor === Object) {
+                if (source[key] && source[key].constructor === Object) {
+                    ExtObject.merge(source[key], value);
+                }
+                else {
+                    source[key] = Ext.clone(value);
+                }
+            }
+            else {
+                source[key] = value;
+            }
 
-        wfn = E.on(el, ename, wrap);
-        es[ename] = es[ename] || [];
+            return source;
+        }
 
-        
-        es[ename].push([fn, wrap, scope, wfn, task]);
+        var i = 1,
+            ln = arguments.length,
+            object, property;
 
-        
-        
+        for (; i < ln; i++) {
+            object = arguments[i];
 
-        
-        if(el.addEventListener && ename == "mousewheel"){
-            var args = ["DOMMouseScroll", wrap, false];
-            el.addEventListener.apply(el, args);
-            Ext.EventManager.addListener(WINDOW, 'unload', function(){
-                el.removeEventListener.apply(el, args);
-            });
+            for (property in object) {
+                if (object.hasOwnProperty(property)) {
+                    ExtObject.merge(source, property, object[property]);
+                }
+            }
         }
 
-        
-        if(el == DOC && ename == "mousedown"){
-            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
-        }
-    };
+        return source;
+    },
 
-    function doScrollChk(){
-        
-        if(window != top){
-            return false;
+    
+    getKey: function(object, value) {
+        for (var property in object) {
+            if (object.hasOwnProperty(property) && object[property] === value) {
+                return property;
+            }
         }
 
-        try{
-            DOC.documentElement.doScroll('left');
-        }catch(e){
-             return false;
-        }
+        return null;
+    },
 
-        fireDocReady();
-        return true;
-    }
     
-    function checkReadyState(e){
+    getValues: function(object) {
+        var values = [],
+            property;
 
-        if(Ext.isIE && doScrollChk()){
-            return true;
-        }
-        if(DOC.readyState == COMPLETE){
-            fireDocReady();
-            return true;
+        for (property in object) {
+            if (object.hasOwnProperty(property)) {
+                values.push(object[property]);
+            }
         }
-        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
-        return false;
-    }
 
-    var styles;
-    function checkStyleSheets(e){
-        styles || (styles = Ext.query('style, link[rel=stylesheet]'));
-        if(styles.length == DOC.styleSheets.length){
-            fireDocReady();
-            return true;
+        return values;
+    },
+
+    
+    getKeys: ('keys' in Object.prototype) ? Object.keys : function(object) {
+        var keys = [],
+            property;
+
+        for (property in object) {
+            if (object.hasOwnProperty(property)) {
+                keys.push(property);
+            }
         }
-        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
-        return false;
-    }
 
-    function OperaDOMContentLoaded(e){
-        DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
-        checkStyleSheets();
-    }
+        return keys;
+    },
 
-    function fireDocReady(e){
-        if(!docReadyState){
-            docReadyState = true; 
+    
+    getSize: function(object) {
+        var size = 0,
+            property;
 
-            if(docReadyProcId){
-                clearTimeout(docReadyProcId);
-            }
-            if(DETECT_NATIVE) {
-                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
-            }
-            if(Ext.isIE && checkReadyState.bindIE){  
-                DOC.detachEvent('onreadystatechange', checkReadyState);
+        for (property in object) {
+            if (object.hasOwnProperty(property)) {
+                size++;
             }
-            E.un(WINDOW, "load", arguments.callee);
-        }
-        if(docReadyEvent && !Ext.isReady){
-            Ext.isReady = true;
-            docReadyEvent.fire();
-            docReadyEvent.listeners = [];
         }
 
-    };
+        return size;
+    }
+};
 
-    function initDocReady(){
-        docReadyEvent || (docReadyEvent = new Ext.util.Event());
-        if (DETECT_NATIVE) {
-            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
-        }
-        
-        if (Ext.isIE){
-            
-            
-            if(!checkReadyState()){
-                checkReadyState.bindIE = true;
-                DOC.attachEvent('onreadystatechange', checkReadyState);
-            }
 
-        }else if(Ext.isOpera ){
-            
 
-            
-            (DOC.readyState == COMPLETE && checkStyleSheets()) ||
-                DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
+Ext.merge = Ext.Object.merge;
 
-        }else if (Ext.isWebKit){
-            
-            checkReadyState();
-        }
-        
-        E.on(WINDOW, "load", fireDocReady);
-    };
 
-    function createTargeted(h, o){
-        return function(){
-            var args = Ext.toArray(arguments);
-            if(o.target == Ext.EventObject.setEvent(args[0]).target){
-                h.apply(this, args);
-            }
-        };
-    };
+Ext.urlEncode = function() {
+    var args = Ext.Array.from(arguments),
+        prefix = '';
 
-    function createBuffered(h, o, task){
-        return function(e){
-            
-            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
-        };
-    };
+    
+    if ((typeof args[1] === 'string')) {
+        prefix = args[1] + '&';
+        args[1] = false;
+    }
 
-    function createSingle(h, el, ename, fn, scope){
-        return function(e){
-            Ext.EventManager.removeListener(el, ename, fn, scope);
-            h(e);
-        };
-    };
+    return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
+};
 
-    function createDelayed(h, o, fn){
-        return function(e){
-            var task = new Ext.util.DelayedTask(h);
-            if(!fn.tasks) {
-                fn.tasks = [];
-            }
-            fn.tasks.push(task);
-            task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
-        };
-    };
 
-    function listen(element, ename, opt, fn, scope){
-        var o = (!opt || typeof opt == "boolean") ? {} : opt,
-            el = Ext.getDom(element), task;
+Ext.urlDecode = function() {
+    return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
+};
 
-        fn = fn || o.fn;
-        scope = scope || o.scope;
+})();
 
-        if(!el){
-            throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
-        }
-        function h(e){
-            
-            if(!Ext){
-                return;
-            }
-            e = Ext.EventObject.setEvent(e);
-            var t;
-            if (o.delegate) {
-                if(!(t = e.getTarget(o.delegate, el))){
-                    return;
-                }
-            } else {
-                t = e.target;
-            }
-            if (o.stopEvent) {
-                e.stopEvent();
-            }
-            if (o.preventDefault) {
-               e.preventDefault();
-            }
-            if (o.stopPropagation) {
-                e.stopPropagation();
-            }
-            if (o.normalized) {
-                e = e.browserEvent;
-            }
 
-            fn.call(scope || el, e, t, o);
-        };
-        if(o.target){
-            h = createTargeted(h, o);
-        }
-        if(o.delay){
-            h = createDelayed(h, o, fn);
-        }
-        if(o.single){
-            h = createSingle(h, el, ename, fn, scope);
-        }
-        if(o.buffer){
-            task = new Ext.util.DelayedTask(h);
-            h = createBuffered(h, o, task);
-        }
 
-        addListener(el, ename, fn, task, h, scope);
-        return h;
-    };
 
-    var pub = {
-        
-        addListener : function(element, eventName, fn, scope, options){
-            if(typeof eventName == 'object'){
-                var o = eventName, e, val;
-                for(e in o){
-                    val = o[e];
-                    if(!propRe.test(e)){
-                        if(Ext.isFunction(val)){
-                            
-                            listen(element, e, o, val, o.scope);
-                        }else{
-                            
-                            listen(element, e, val);
-                        }
-                    }
-                }
-            } else {
-                listen(element, eventName, options, fn, scope);
-            }
-        },
 
-        
-        removeListener : function(el, eventName, fn, scope){
-            el = Ext.getDom(el);
-            var id = getId(el),
-                f = el && (Ext.elCache[id].events)[eventName] || [],
-                wrap, i, l, k, len, fnc;
+(function() {
 
-            for (i = 0, len = f.length; i < len; i++) {
 
-                
-                if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
-                    if(fnc[4]) {
-                        fnc[4].cancel();
-                    }
-                    k = fn.tasks && fn.tasks.length;
-                    if(k) {
-                        while(k--) {
-                            fn.tasks[k].cancel();
-                        }
-                        delete fn.tasks;
-                    }
-                    wrap = fnc[1];
-                    E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
 
-                    
-                    if(wrap && el.addEventListener && eventName == "mousewheel"){
-                        el.removeEventListener("DOMMouseScroll", wrap, false);
-                    }
 
-                    
-                    if(wrap && el == DOC && eventName == "mousedown"){
-                        Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
-                    }
+function xf(format) {
+    var args = Array.prototype.slice.call(arguments, 1);
+    return format.replace(/\{(\d+)\}/g, function(m, i) {
+        return args[i];
+    });
+}
 
-                    f.splice(i, 1);
-                    if (f.length === 0) {
-                        delete Ext.elCache[id].events[eventName];
-                    }
-                    for (k in Ext.elCache[id].events) {
-                        return false;
-                    }
-                    Ext.elCache[id].events = {};
-                    return false;
-                }
-            }
-        },
+Ext.Date = {
+    
+    now: Date.now || function() {
+        return +new Date();
+    },
 
-        
-        removeAll : function(el){
-            el = Ext.getDom(el);
-            var id = getId(el),
-                ec = Ext.elCache[id] || {},
-                es = ec.events || {},
-                f, i, len, ename, fn, k, wrap;
-
-            for(ename in es){
-                if(es.hasOwnProperty(ename)){
-                    f = es[ename];
-                    
-                    for (i = 0, len = f.length; i < len; i++) {
-                        fn = f[i];
-                        if(fn[4]) {
-                            fn[4].cancel();
-                        }
-                        if(fn[0].tasks && (k = fn[0].tasks.length)) {
-                            while(k--) {
-                                fn[0].tasks[k].cancel();
-                            }
-                            delete fn.tasks;
-                        }
-                        wrap =  fn[1];
-                        E.un(el, ename, E.extAdapter ? fn[3] : wrap);
+    
+    toString: function(date) {
+        var pad = Ext.String.leftPad;
 
-                        
-                        if(el.addEventListener && wrap && ename == "mousewheel"){
-                            el.removeEventListener("DOMMouseScroll", wrap, false);
-                        }
+        return date.getFullYear() + "-"
+            + pad(date.getMonth() + 1, 2, '0') + "-"
+            + pad(date.getDate(), 2, '0') + "T"
+            + pad(date.getHours(), 2, '0') + ":"
+            + pad(date.getMinutes(), 2, '0') + ":"
+            + pad(date.getSeconds(), 2, '0');
+    },
 
-                        
-                        if(wrap && el == DOC &&  ename == "mousedown"){
-                            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
-                        }
-                    }
-                }
-            }
-            if (Ext.elCache[id]) {
-                Ext.elCache[id].events = {};
-            }
-        },
+    
+    getElapsed: function(dateA, dateB) {
+        return Math.abs(dateA - (dateB || new Date()));
+    },
 
-        getListeners : function(el, eventName) {
-            el = Ext.getDom(el);
-            var id = getId(el),
-                ec = Ext.elCache[id] || {},
-                es = ec.events || {},
-                results = [];
-            if (es && es[eventName]) {
-                return es[eventName];
-            } else {
-                return null;
-            }
-        },
+    
+    useStrict: false,
 
-        purgeElement : function(el, recurse, eventName) {
-            el = Ext.getDom(el);
-            var id = getId(el),
-                ec = Ext.elCache[id] || {},
-                es = ec.events || {},
-                i, f, len;
-            if (eventName) {
-                if (es && es.hasOwnProperty(eventName)) {
-                    f = es[eventName];
-                    for (i = 0, len = f.length; i < len; i++) {
-                        Ext.EventManager.removeListener(el, eventName, f[i][0]);
-                    }
-                }
-            } else {
-                Ext.EventManager.removeAll(el);
-            }
-            if (recurse && el && el.childNodes) {
-                for (i = 0, len = el.childNodes.length; i < len; i++) {
-                    Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
-                }
-            }
-        },
+    
+    formatCodeToRegex: function(character, currentGroup) {
+        
+        var p = utilDate.parseCodes[character];
 
-        _unload : function() {
-            var el;
-            for (el in Ext.elCache) {
-                Ext.EventManager.removeAll(el);
-            }
-            delete Ext.elCache;
-            delete Ext.Element._flyweights;
+        if (p) {
+          p = typeof p == 'function'? p() : p;
+          utilDate.parseCodes[character] = p; 
+        }
 
+        return p ? Ext.applyIf({
+          c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
+        }, p) : {
+            g: 0,
+            c: null,
+            s: Ext.String.escapeRegex(character) 
+        };
+    },
+
+    
+    parseFunctions: {
+        "MS": function(input, strict) {
             
-            var c,
-                conn,
-                tid,
-                ajax = Ext.lib.Ajax;
-            (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
-            for (tid in conn) {
-                c = conn[tid];
-                if (c) {
-                    ajax.abort({conn: c, tId: tid});
-                }
-            }
-        },
-        
-        onDocumentReady : function(fn, scope, options){
-            if(Ext.isReady){ 
-                docReadyEvent || (docReadyEvent = new Ext.util.Event());
-                docReadyEvent.addListener(fn, scope, options);
-                docReadyEvent.fire();
-                docReadyEvent.listeners = [];
-            }else{
-                if(!docReadyEvent){
-                    initDocReady();
-                }
-                options = options || {};
-                options.delay = options.delay || 1;
-                docReadyEvent.addListener(fn, scope, options);
-            }
-        },
+            
+            var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
+            var r = (input || '').match(re);
+            return r? new Date(((r[1] || '') + r[2]) * 1) : null;
+        }
+    },
+    parseRegexes: [],
 
-        
-        fireDocReady  : fireDocReady
-    };
-     
-    pub.on = pub.addListener;
     
-    pub.un = pub.removeListener;
+    formatFunctions: {
+        "MS": function() {
+            
+            return '\\/Date(' + this.getTime() + ')\\/';
+        }
+    },
 
-    pub.stoppedMouseDownEvent = new Ext.util.Event();
-    return pub;
-}();
+    y2kYear : 50,
 
-Ext.onReady = Ext.EventManager.onDocumentReady;
+    
+    MILLI : "ms",
 
+    
+    SECOND : "s",
 
+    
+    MINUTE : "mi",
 
-(function(){
+    
+    HOUR : "h",
 
-    var initExtCss = function(){
-        
-        var bd = document.body || document.getElementsByTagName('body')[0];
-        if(!bd){ return false; }
-        var cls = [' ',
-                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
-                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
-                : Ext.isOpera ? "ext-opera"
-                : Ext.isWebKit ? "ext-webkit" : ""];
+    
+    DAY : "d",
 
-        if(Ext.isSafari){
-            cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
-        }else if(Ext.isChrome){
-            cls.push("ext-chrome");
-        }
+    
+    MONTH : "mo",
 
-        if(Ext.isMac){
-            cls.push("ext-mac");
-        }
-        if(Ext.isLinux){
-            cls.push("ext-linux");
-        }
+    
+    YEAR : "y",
 
-        if(Ext.isStrict || Ext.isBorderBox){ 
-            var p = bd.parentNode;
-            if(p){
-                p.className += Ext.isStrict ? ' ext-strict' : ' ext-border-box';
-            }
-        }
-        bd.className += cls.join(' ');
-        return true;
-    }
+    
+    defaults: {},
 
-    if(!initExtCss()){
-        Ext.onReady(initExtCss);
-    }
-})();
+    
+    dayNames : [
+        "Sunday",
+        "Monday",
+        "Tuesday",
+        "Wednesday",
+        "Thursday",
+        "Friday",
+        "Saturday"
+    ],
 
+    
+    monthNames : [
+        "January",
+        "February",
+        "March",
+        "April",
+        "May",
+        "June",
+        "July",
+        "August",
+        "September",
+        "October",
+        "November",
+        "December"
+    ],
+
+    
+    monthNumbers : {
+        Jan:0,
+        Feb:1,
+        Mar:2,
+        Apr:3,
+        May:4,
+        Jun:5,
+        Jul:6,
+        Aug:7,
+        Sep:8,
+        Oct:9,
+        Nov:10,
+        Dec:11
+    },
+    
+    defaultFormat : "m/d/Y",
+    
+    getShortMonthName : function(month) {
+        return utilDate.monthNames[month].substring(0, 3);
+    },
 
+    
+    getShortDayName : function(day) {
+        return utilDate.dayNames[day].substring(0, 3);
+    },
 
-Ext.EventObject = function(){
-    var E = Ext.lib.Event,
-        clickRe = /(dbl)?click/,
-        
-        safariKeys = {
-            3 : 13, 
-            63234 : 37, 
-            63235 : 39, 
-            63232 : 38, 
-            63233 : 40, 
-            63276 : 33, 
-            63277 : 34, 
-            63272 : 46, 
-            63273 : 36, 
-            63275 : 35  
-        },
+    
+    getMonthNumber : function(name) {
         
-        btnMap = Ext.isIE ? {1:0,4:1,2:2} :
-                (Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
+        return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
+    },
 
-    Ext.EventObjectImpl = function(e){
-        if(e){
-            this.setEvent(e.browserEvent || e);
-        }
-    };
+    
+    formatContainsHourInfo : (function(){
+        var stripEscapeRe = /(\\.)/g,
+            hourInfoRe = /([gGhHisucUOPZ]|MS)/;
+        return function(format){
+            return hourInfoRe.test(format.replace(stripEscapeRe, ''));
+        };
+    })(),
 
-    Ext.EventObjectImpl.prototype = {
-           
-        setEvent : function(e){
-            var me = this;
-            if(e == me || (e && e.browserEvent)){ 
-                return e;
-            }
-            me.browserEvent = e;
-            if(e){
-                
-                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
-                if(clickRe.test(e.type) && me.button == -1){
-                    me.button = 0;
-                }
-                me.type = e.type;
-                me.shiftKey = e.shiftKey;
-                
-                me.ctrlKey = e.ctrlKey || e.metaKey || false;
-                me.altKey = e.altKey;
-                
-                me.keyCode = e.keyCode;
-                me.charCode = e.charCode;
-                
-                me.target = E.getTarget(e);
-                
-                me.xy = E.getXY(e);
-            }else{
-                me.button = -1;
-                me.shiftKey = false;
-                me.ctrlKey = false;
-                me.altKey = false;
-                me.keyCode = 0;
-                me.charCode = 0;
-                me.target = null;
-                me.xy = [0, 0];
-            }
-            return me;
-        },
+    
+    formatContainsDateInfo : (function(){
+        var stripEscapeRe = /(\\.)/g,
+            dateInfoRe = /([djzmnYycU]|MS)/;
 
-        
-        stopEvent : function(){
-            var me = this;
-            if(me.browserEvent){
-                if(me.browserEvent.type == 'mousedown'){
-                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
-                }
-                E.stopEvent(me.browserEvent);
-            }
-        },
+        return function(format){
+            return dateInfoRe.test(format.replace(stripEscapeRe, ''));
+        };
+    })(),
 
-        
-        preventDefault : function(){
-            if(this.browserEvent){
-                E.preventDefault(this.browserEvent);
-            }
-        },
+    
+    formatCodes : {
+        d: "Ext.String.leftPad(this.getDate(), 2, '0')",
+        D: "Ext.Date.getShortDayName(this.getDay())", 
+        j: "this.getDate()",
+        l: "Ext.Date.dayNames[this.getDay()]",
+        N: "(this.getDay() ? this.getDay() : 7)",
+        S: "Ext.Date.getSuffix(this)",
+        w: "this.getDay()",
+        z: "Ext.Date.getDayOfYear(this)",
+        W: "Ext.String.leftPad(Ext.Date.getWeekOfYear(this), 2, '0')",
+        F: "Ext.Date.monthNames[this.getMonth()]",
+        m: "Ext.String.leftPad(this.getMonth() + 1, 2, '0')",
+        M: "Ext.Date.getShortMonthName(this.getMonth())", 
+        n: "(this.getMonth() + 1)",
+        t: "Ext.Date.getDaysInMonth(this)",
+        L: "(Ext.Date.isLeapYear(this) ? 1 : 0)",
+        o: "(this.getFullYear() + (Ext.Date.getWeekOfYear(this) == 1 && this.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(this) >= 52 && this.getMonth() < 11 ? -1 : 0)))",
+        Y: "Ext.String.leftPad(this.getFullYear(), 4, '0')",
+        y: "('' + this.getFullYear()).substring(2, 4)",
+        a: "(this.getHours() < 12 ? 'am' : 'pm')",
+        A: "(this.getHours() < 12 ? 'AM' : 'PM')",
+        g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
+        G: "this.getHours()",
+        h: "Ext.String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
+        H: "Ext.String.leftPad(this.getHours(), 2, '0')",
+        i: "Ext.String.leftPad(this.getMinutes(), 2, '0')",
+        s: "Ext.String.leftPad(this.getSeconds(), 2, '0')",
+        u: "Ext.String.leftPad(this.getMilliseconds(), 3, '0')",
+        O: "Ext.Date.getGMTOffset(this)",
+        P: "Ext.Date.getGMTOffset(this, true)",
+        T: "Ext.Date.getTimezone(this)",
+        Z: "(this.getTimezoneOffset() * -60)",
 
-        
-        stopPropagation : function(){
-            var me = this;
-            if(me.browserEvent){
-                if(me.browserEvent.type == 'mousedown'){
-                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
-                }
-                E.stopPropagation(me.browserEvent);
+        c: function() { 
+            for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
+                var e = c.charAt(i);
+                code.push(e == "T" ? "'T'" : utilDate.getFormatCode(e)); 
             }
+            return code.join(" + ");
         },
-
         
-        getCharCode : function(){
-            return this.charCode || this.keyCode;
-        },
 
-        
-        getKey : function(){
-            return this.normalizeKey(this.keyCode || this.charCode)
-        },
+        U: "Math.round(this.getTime() / 1000)"
+    },
 
+    
+    isValid : function(y, m, d, h, i, s, ms) {
         
-        normalizeKey: function(k){
-            return Ext.isSafari ? (safariKeys[k] || k) : k;
-        },
+        h = h || 0;
+        i = i || 0;
+        s = s || 0;
+        ms = ms || 0;
 
         
-        getPageX : function(){
-            return this.xy[0];
-        },
+        var dt = utilDate.add(new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms), utilDate.YEAR, y < 100 ? y - 100 : 0);
 
-        
-        getPageY : function(){
-            return this.xy[1];
-        },
+        return y == dt.getFullYear() &&
+            m == dt.getMonth() + 1 &&
+            d == dt.getDate() &&
+            h == dt.getHours() &&
+            i == dt.getMinutes() &&
+            s == dt.getSeconds() &&
+            ms == dt.getMilliseconds();
+    },
 
-        
-        getXY : function(){
-            return this.xy;
-        },
+    
+    parse : function(input, format, strict) {
+        var p = utilDate.parseFunctions;
+        if (p[format] == null) {
+            utilDate.createParser(format);
+        }
+        return p[format](input, Ext.isDefined(strict) ? strict : utilDate.useStrict);
+    },
 
-        
-        getTarget : function(selector, maxDepth, returnEl){
-            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
-        },
+    
+    parseDate: function(input, format, strict){
+        return utilDate.parse(input, format, strict);
+    },
 
-        
-        getRelatedTarget : function(){
-            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
-        },
 
-        
-        getWheelDelta : function(){
-            var e = this.browserEvent;
-            var delta = 0;
-            if(e.wheelDelta){ 
-                delta = e.wheelDelta/120;
-            }else if(e.detail){ 
-                delta = -e.detail/3;
-            }
-            return delta;
-        },
+    
+    getFormatCode : function(character) {
+        var f = utilDate.formatCodes[character];
 
-        
-        within : function(el, related, allowEl){
-            if(el){
-                var t = this[related ? "getRelatedTarget" : "getTarget"]();
-                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
-            }
-            return false;
+        if (f) {
+          f = typeof f == 'function'? f() : f;
+          utilDate.formatCodes[character] = f; 
         }
-     };
-
-    return new Ext.EventObjectImpl();
-}();
 
-Ext.apply(Ext.EventManager, function(){
-   var resizeEvent,
-       resizeTask,
-       textEvent,
-       textSize,
-       D = Ext.lib.Dom,
-       propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
-       curWidth = 0,
-       curHeight = 0,
-       
-       
-       
-       useKeydown = Ext.isWebKit ?
-                   Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :
-                   !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);
+        
+        return f || ("'" + Ext.String.escape(character) + "'");
+    },
 
-   return {
-       
-       doResizeEvent: function(){
-           var h = D.getViewHeight(),
-               w = D.getViewWidth();
+    
+    createFormat : function(format) {
+        var code = [],
+            special = false,
+            ch = '';
 
-            
-            if(curHeight != h || curWidth != w){
-               resizeEvent.fire(curWidth = w, curHeight = h);
+        for (var i = 0; i < format.length; ++i) {
+            ch = format.charAt(i);
+            if (!special && ch == "\\") {
+                special = true;
+            } else if (special) {
+                special = false;
+                code.push("'" + Ext.String.escape(ch) + "'");
+            } else {
+                code.push(utilDate.getFormatCode(ch));
             }
-       },
+        }
+        utilDate.formatFunctions[format] = Ext.functionFactory("return " + code.join('+'));
+    },
 
-       
-       onWindowResize : function(fn, scope, options){
-           if(!resizeEvent){
-               resizeEvent = new Ext.util.Event();
-               resizeTask = new Ext.util.DelayedTask(this.doResizeEvent);
-               Ext.EventManager.on(window, "resize", this.fireWindowResize, this);
-           }
-           resizeEvent.addListener(fn, scope, options);
-       },
+    
+    createParser : (function() {
+        var code = [
+            "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
+                "def = Ext.Date.defaults,",
+                "results = String(input).match(Ext.Date.parseRegexes[{0}]);", 
 
-       
-       fireWindowResize : function(){
-           if(resizeEvent){
-               resizeTask.delay(100);
-           }
-       },
+            "if(results){",
+                "{1}",
 
-       
-       onTextResize : function(fn, scope, options){
-           if(!textEvent){
-               textEvent = new Ext.util.Event();
-               var textEl = new Ext.Element(document.createElement('div'));
-               textEl.dom.className = 'x-text-resize';
-               textEl.dom.innerHTML = 'X';
-               textEl.appendTo(document.body);
-               textSize = textEl.dom.offsetHeight;
-               setInterval(function(){
-                   if(textEl.dom.offsetHeight != textSize){
-                       textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
-                   }
-               }, this.textResizeInterval);
-           }
-           textEvent.addListener(fn, scope, options);
-       },
+                "if(u != null){", 
+                    "v = new Date(u * 1000);", 
+                "}else{",
+                    
+                    
+                    
+                    "dt = Ext.Date.clearTime(new Date);",
 
-       
-       removeResizeListener : function(fn, scope){
-           if(resizeEvent){
-               resizeEvent.removeListener(fn, scope);
-           }
-       },
+                    
+                    "y = Ext.Number.from(y, Ext.Number.from(def.y, dt.getFullYear()));",
+                    "m = Ext.Number.from(m, Ext.Number.from(def.m - 1, dt.getMonth()));",
+                    "d = Ext.Number.from(d, Ext.Number.from(def.d, dt.getDate()));",
 
-       
-       fireResize : function(){
-           if(resizeEvent){
-               resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
-           }
-       },
+                    
+                    "h  = Ext.Number.from(h, Ext.Number.from(def.h, dt.getHours()));",
+                    "i  = Ext.Number.from(i, Ext.Number.from(def.i, dt.getMinutes()));",
+                    "s  = Ext.Number.from(s, Ext.Number.from(def.s, dt.getSeconds()));",
+                    "ms = Ext.Number.from(ms, Ext.Number.from(def.ms, dt.getMilliseconds()));",
 
-        
-       textResizeInterval : 50,
+                    "if(z >= 0 && y >= 0){",
+                        
+                        
 
-       
-       ieDeferSrc : false,
+                        
+                        
+                        "v = Ext.Date.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
+
+                        
+                        "v = !strict? v : (strict === true && (z <= 364 || (Ext.Date.isLeapYear(v) && z <= 365))? Ext.Date.add(v, Ext.Date.DAY, z) : null);",
+                    "}else if(strict === true && !Ext.Date.isValid(y, m + 1, d, h, i, s, ms)){", 
+                        "v = null;", 
+                    "}else{",
+                        
+                        
+                        "v = Ext.Date.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
+                    "}",
+                "}",
+            "}",
+
+            "if(v){",
+                
+                "if(zz != null){",
+                    
+                    "v = Ext.Date.add(v, Ext.Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
+                "}else if(o){",
+                    
+                    "v = Ext.Date.add(v, Ext.Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
+                "}",
+            "}",
+
+            "return v;"
+        ].join('\n');
+
+        return function(format) {
+            var regexNum = utilDate.parseRegexes.length,
+                currentGroup = 1,
+                calc = [],
+                regex = [],
+                special = false,
+                ch = "";
+
+            for (var i = 0; i < format.length; ++i) {
+                ch = format.charAt(i);
+                if (!special && ch == "\\") {
+                    special = true;
+                } else if (special) {
+                    special = false;
+                    regex.push(Ext.String.escape(ch));
+                } else {
+                    var obj = utilDate.formatCodeToRegex(ch, currentGroup);
+                    currentGroup += obj.g;
+                    regex.push(obj.s);
+                    if (obj.g && obj.c) {
+                        calc.push(obj.c);
+                    }
+                }
+            }
+
+            utilDate.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
+            utilDate.parseFunctions[format] = Ext.functionFactory("input", "strict", xf(code, regexNum, calc.join('')));
+        };
+    })(),
+
+    
+    parseCodes : {
+        
+        d: {
+            g:1,
+            c:"d = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        j: {
+            g:1,
+            c:"d = parseInt(results[{0}], 10);\n",
+            s:"(\\d{1,2})" 
+        },
+        D: function() {
+            for (var a = [], i = 0; i < 7; a.push(utilDate.getShortDayName(i)), ++i); 
+            return {
+                g:0,
+                c:null,
+                s:"(?:" + a.join("|") +")"
+            };
+        },
+        l: function() {
+            return {
+                g:0,
+                c:null,
+                s:"(?:" + utilDate.dayNames.join("|") + ")"
+            };
+        },
+        N: {
+            g:0,
+            c:null,
+            s:"[1-7]" 
+        },
+        S: {
+            g:0,
+            c:null,
+            s:"(?:st|nd|rd|th)"
+        },
+        w: {
+            g:0,
+            c:null,
+            s:"[0-6]" 
+        },
+        z: {
+            g:1,
+            c:"z = parseInt(results[{0}], 10);\n",
+            s:"(\\d{1,3})" 
+        },
+        W: {
+            g:0,
+            c:null,
+            s:"(?:\\d{2})" 
+        },
+        F: function() {
+            return {
+                g:1,
+                c:"m = parseInt(Ext.Date.getMonthNumber(results[{0}]), 10);\n", 
+                s:"(" + utilDate.monthNames.join("|") + ")"
+            };
+        },
+        M: function() {
+            for (var a = [], i = 0; i < 12; a.push(utilDate.getShortMonthName(i)), ++i); 
+            return Ext.applyIf({
+                s:"(" + a.join("|") + ")"
+            }, utilDate.formatCodeToRegex("F"));
+        },
+        m: {
+            g:1,
+            c:"m = parseInt(results[{0}], 10) - 1;\n",
+            s:"(\\d{2})" 
+        },
+        n: {
+            g:1,
+            c:"m = parseInt(results[{0}], 10) - 1;\n",
+            s:"(\\d{1,2})" 
+        },
+        t: {
+            g:0,
+            c:null,
+            s:"(?:\\d{2})" 
+        },
+        L: {
+            g:0,
+            c:null,
+            s:"(?:1|0)"
+        },
+        o: function() {
+            return utilDate.formatCodeToRegex("Y");
+        },
+        Y: {
+            g:1,
+            c:"y = parseInt(results[{0}], 10);\n",
+            s:"(\\d{4})" 
+        },
+        y: {
+            g:1,
+            c:"var ty = parseInt(results[{0}], 10);\n"
+                + "y = ty > Ext.Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
+            s:"(\\d{1,2})"
+        },
+        
+        a: {
+            g:1,
+            c:"if (/(am)/i.test(results[{0}])) {\n"
+                + "if (!h || h == 12) { h = 0; }\n"
+                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
+            s:"(am|pm|AM|PM)"
+        },
+        A: {
+            g:1,
+            c:"if (/(am)/i.test(results[{0}])) {\n"
+                + "if (!h || h == 12) { h = 0; }\n"
+                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
+            s:"(AM|PM|am|pm)"
+        },
+        g: function() {
+            return utilDate.formatCodeToRegex("G");
+        },
+        G: {
+            g:1,
+            c:"h = parseInt(results[{0}], 10);\n",
+            s:"(\\d{1,2})" 
+        },
+        h: function() {
+            return utilDate.formatCodeToRegex("H");
+        },
+        H: {
+            g:1,
+            c:"h = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        i: {
+            g:1,
+            c:"i = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        s: {
+            g:1,
+            c:"s = parseInt(results[{0}], 10);\n",
+            s:"(\\d{2})" 
+        },
+        u: {
+            g:1,
+            c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
+            s:"(\\d+)" 
+        },
+        O: {
+            g:1,
+            c:[
+                "o = results[{0}];",
+                "var sn = o.substring(0,1),", 
+                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
+                    "mn = o.substring(3,5) % 60;", 
+                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n" 
+            ].join("\n"),
+            s: "([+\-]\\d{4})" 
+        },
+        P: {
+            g:1,
+            c:[
+                "o = results[{0}];",
+                "var sn = o.substring(0,1),", 
+                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
+                    "mn = o.substring(4,6) % 60;", 
+                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n" 
+            ].join("\n"),
+            s: "([+\-]\\d{2}:\\d{2})" 
+        },
+        T: {
+            g:0,
+            c:null,
+            s:"[A-Z]{1,4}" 
+        },
+        Z: {
+            g:1,
+            c:"zz = results[{0}] * 1;\n" 
+                  + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
+            s:"([+\-]?\\d{1,5})" 
+        },
+        c: function() {
+            var calc = [],
+                arr = [
+                    utilDate.formatCodeToRegex("Y", 1), 
+                    utilDate.formatCodeToRegex("m", 2), 
+                    utilDate.formatCodeToRegex("d", 3), 
+                    utilDate.formatCodeToRegex("h", 4), 
+                    utilDate.formatCodeToRegex("i", 5), 
+                    utilDate.formatCodeToRegex("s", 6), 
+                    {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
+                    {c:[ 
+                        "if(results[8]) {", 
+                            "if(results[8] == 'Z'){",
+                                "zz = 0;", 
+                            "}else if (results[8].indexOf(':') > -1){",
+                                utilDate.formatCodeToRegex("P", 8).c, 
+                            "}else{",
+                                utilDate.formatCodeToRegex("O", 8).c, 
+                            "}",
+                        "}"
+                    ].join('\n')}
+                ];
+
+            for (var i = 0, l = arr.length; i < l; ++i) {
+                calc.push(arr[i].c);
+            }
+
+            return {
+                g:1,
+                c:calc.join(""),
+                s:[
+                    arr[0].s, 
+                    "(?:", "-", arr[1].s, 
+                        "(?:", "-", arr[2].s, 
+                            "(?:",
+                                "(?:T| )?", 
+                                arr[3].s, ":", arr[4].s,  
+                                "(?::", arr[5].s, ")?", 
+                                "(?:(?:\\.|,)(\\d+))?", 
+                                "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
+                            ")?",
+                        ")?",
+                    ")?"
+                ].join("")
+            };
+        },
+        U: {
+            g:1,
+            c:"u = parseInt(results[{0}], 10);\n",
+            s:"(-?\\d+)" 
+        }
+    },
+
+    
+    
+    dateFormat: function(date, format) {
+        return utilDate.format(date, format);
+    },
+
+    
+    format: function(date, format) {
+        if (utilDate.formatFunctions[format] == null) {
+            utilDate.createFormat(format);
+        }
+        var result = utilDate.formatFunctions[format].call(date);
+        return result + '';
+    },
+
+    
+    getTimezone : function(date) {
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
+    },
+
+    
+    getGMTOffset : function(date, colon) {
+        var offset = date.getTimezoneOffset();
+        return (offset > 0 ? "-" : "+")
+            + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, "0")
+            + (colon ? ":" : "")
+            + Ext.String.leftPad(Math.abs(offset % 60), 2, "0");
+    },
+
+    
+    getDayOfYear: function(date) {
+        var num = 0,
+            d = Ext.Date.clone(date),
+            m = date.getMonth(),
+            i;
+
+        for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
+            num += utilDate.getDaysInMonth(d);
+        }
+        return num + date.getDate() - 1;
+    },
+
+    
+    getWeekOfYear : (function() {
+        
+        var ms1d = 864e5, 
+            ms7d = 7 * ms1d; 
+
+        return function(date) { 
+            var DC3 = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d, 
+                AWN = Math.floor(DC3 / 7), 
+                Wyr = new Date(AWN * ms7d).getUTCFullYear();
+
+            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
+        };
+    })(),
+
+    
+    isLeapYear : function(date) {
+        var year = date.getFullYear();
+        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
+    },
+
+    
+    getFirstDayOfMonth : function(date) {
+        var day = (date.getDay() - (date.getDate() - 1)) % 7;
+        return (day < 0) ? (day + 7) : day;
+    },
+
+    
+    getLastDayOfMonth : function(date) {
+        return utilDate.getLastDateOfMonth(date).getDay();
+    },
+
+
+    
+    getFirstDateOfMonth : function(date) {
+        return new Date(date.getFullYear(), date.getMonth(), 1);
+    },
+
+    
+    getLastDateOfMonth : function(date) {
+        return new Date(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));
+    },
+
+    
+    getDaysInMonth: (function() {
+        var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+        return function(date) { 
+            var m = date.getMonth();
+
+            return m == 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];
+        };
+    })(),
+
+    
+    getSuffix : function(date) {
+        switch (date.getDate()) {
+            case 1:
+            case 21:
+            case 31:
+                return "st";
+            case 2:
+            case 22:
+                return "nd";
+            case 3:
+            case 23:
+                return "rd";
+            default:
+                return "th";
+        }
+    },
+
+    
+    clone : function(date) {
+        return new Date(date.getTime());
+    },
+
+    
+    isDST : function(date) {
+        
+        
+        return new Date(date.getFullYear(), 0, 1).getTimezoneOffset() != date.getTimezoneOffset();
+    },
+
+    
+    clearTime : function(date, clone) {
+        if (clone) {
+            return Ext.Date.clearTime(Ext.Date.clone(date));
+        }
+
+        
+        var d = date.getDate();
+
+        
+        date.setHours(0);
+        date.setMinutes(0);
+        date.setSeconds(0);
+        date.setMilliseconds(0);
+
+        if (date.getDate() != d) { 
+            
+            
+
+            
+            for (var hr = 1, c = utilDate.add(date, Ext.Date.HOUR, hr); c.getDate() != d; hr++, c = utilDate.add(date, Ext.Date.HOUR, hr));
+
+            date.setDate(d);
+            date.setHours(c.getHours());
+        }
+
+        return date;
+    },
+
+    
+    add : function(date, interval, value) {
+        var d = Ext.Date.clone(date),
+            Date = Ext.Date;
+        if (!interval || value === 0) return d;
+
+        switch(interval.toLowerCase()) {
+            case Ext.Date.MILLI:
+                d.setMilliseconds(d.getMilliseconds() + value);
+                break;
+            case Ext.Date.SECOND:
+                d.setSeconds(d.getSeconds() + value);
+                break;
+            case Ext.Date.MINUTE:
+                d.setMinutes(d.getMinutes() + value);
+                break;
+            case Ext.Date.HOUR:
+                d.setHours(d.getHours() + value);
+                break;
+            case Ext.Date.DAY:
+                d.setDate(d.getDate() + value);
+                break;
+            case Ext.Date.MONTH:
+                var day = date.getDate();
+                if (day > 28) {
+                    day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), 'mo', value)).getDate());
+                }
+                d.setDate(day);
+                d.setMonth(date.getMonth() + value);
+                break;
+            case Ext.Date.YEAR:
+                d.setFullYear(date.getFullYear() + value);
+                break;
+        }
+        return d;
+    },
+
+    
+    between : function(date, start, end) {
+        var t = date.getTime();
+        return start.getTime() <= t && t <= end.getTime();
+    },
+
+    
+    compat: function() {
+        var nativeDate = window.Date,
+            p, u,
+            statics = ['useStrict', 'formatCodeToRegex', 'parseFunctions', 'parseRegexes', 'formatFunctions', 'y2kYear', 'MILLI', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR', 'defaults', 'dayNames', 'monthNames', 'monthNumbers', 'getShortMonthName', 'getShortDayName', 'getMonthNumber', 'formatCodes', 'isValid', 'parseDate', 'getFormatCode', 'createFormat', 'createParser', 'parseCodes'],
+            proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 'getFirstDayOfMonth', 'getLastDayOfMonth', 'getDaysInMonth', 'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'];
+
+        
+        Ext.Array.forEach(statics, function(s) {
+            nativeDate[s] = utilDate[s];
+        });
+
+        
+        Ext.Array.forEach(proto, function(s) {
+            nativeDate.prototype[s] = function() {
+                var args = Array.prototype.slice.call(arguments);
+                args.unshift(this);
+                return utilDate[s].apply(utilDate, args);
+            };
+        });
+    }
+};
+
+var utilDate = Ext.Date;
+
+})();
+
+
+(function(flexSetter) {
+
+var Base = Ext.Base = function() {};
+    Base.prototype = {
+        $className: 'Ext.Base',
+
+        $class: Base,
+
+        
+        self: Base,
+
+        
+        constructor: function() {
+            return this;
+        },
+
+        
+        
+        initConfig: function(config) {
+            if (!this.$configInited) {
+                this.config = Ext.Object.merge({}, this.config || {}, config || {});
+
+                this.applyConfig(this.config);
+
+                this.$configInited = true;
+            }
+
+            return this;
+        },
+
+        
+        setConfig: function(config) {
+            this.applyConfig(config || {});
+
+            return this;
+        },
+
+        
+        applyConfig: flexSetter(function(name, value) {
+            var setter = 'set' + Ext.String.capitalize(name);
+
+            if (typeof this[setter] === 'function') {
+                this[setter].call(this, value);
+            }
+
+            return this;
+        }),
+        
+
+        
+        callParent: function(args) {
+            var method = this.callParent.caller,
+                parentClass, methodName;
+
+            if (!method.$owner) {
+
+                method = method.caller;
+            }
+
+            parentClass = method.$owner.superclass;
+            methodName = method.$name;
+
+
+            return parentClass[methodName].apply(this, args || []);
+        },
+
+
+        
+        statics: function() {
+            var method = this.statics.caller,
+                self = this.self;
+
+            if (!method) {
+                return self;
+            }
+
+            return method.$owner;
+        },
+
+        
+        callOverridden: function(args) {
+            var method = this.callOverridden.caller;
+
+
+            return method.$previous.apply(this, args || []);
+        },
+
+        destroy: function() {}
+    };
+
+    
+    Ext.apply(Ext.Base, {
+        
+        create: function() {
+            return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
+        },
+
+        
+        own: function(name, value) {
+            if (typeof value == 'function') {
+                this.ownMethod(name, value);
+            }
+            else {
+                this.prototype[name] = value;
+            }
+        },
+
+        
+        ownMethod: function(name, fn) {
+            var originalFn;
+
+            if (typeof fn.$owner !== 'undefined' && fn !== Ext.emptyFn) {
+                originalFn = fn;
+
+                fn = function() {
+                    return originalFn.apply(this, arguments);
+                };
+            }
+
+            fn.$owner = this;
+            fn.$name = name;
+
+            this.prototype[name] = fn;
+        },
+
+        
+        addStatics: function(members) {
+            for (var name in members) {
+                if (members.hasOwnProperty(name)) {
+                    this[name] = members[name];
+                }
+            }
+
+            return this;
+        },
+
+        
+        addInheritableStatics: function(members) {
+            var inheritableStatics,
+                hasInheritableStatics,
+                prototype = this.prototype,
+                name, member;
+
+            inheritableStatics = prototype.$inheritableStatics;
+            hasInheritableStatics = prototype.$hasInheritableStatics;
+
+            if (!inheritableStatics) {
+                inheritableStatics = prototype.$inheritableStatics = [];
+                hasInheritableStatics = prototype.$hasInheritableStatics = {};
+            }
+
+
+            for (name in members) {
+                if (members.hasOwnProperty(name)) {
+                    member = members[name];
+                    this[name] = member;
+
+                    if (!hasInheritableStatics[name]) {
+                        hasInheritableStatics[name] = true;
+                        inheritableStatics.push(name);
+                    }
+                }
+            }
+
+            return this;
+        },
+
+        
+        implement: function(members) {
+            var prototype = this.prototype,
+                enumerables = Ext.enumerables,
+                name, i, member;
+            for (name in members) {
+                if (members.hasOwnProperty(name)) {
+                    member = members[name];
+
+                    if (typeof member === 'function') {
+                        member.$owner = this;
+                        member.$name = name;
+                    }
+
+                    prototype[name] = member;
+                }
+            }
+
+            if (enumerables) {
+                for (i = enumerables.length; i--;) {
+                    name = enumerables[i];
+
+                    if (members.hasOwnProperty(name)) {
+                        member = members[name];
+                        member.$owner = this;
+                        member.$name = name;
+                        prototype[name] = member;
+                    }
+                }
+            }
+        },
+
+        
+        borrow: function(fromClass, members) {
+            var fromPrototype = fromClass.prototype,
+                i, ln, member;
+
+            members = Ext.Array.from(members);
+
+            for (i = 0, ln = members.length; i < ln; i++) {
+                member = members[i];
+
+                this.own(member, fromPrototype[member]);
+            }
+
+            return this;
+        },
+
+        
+        override: function(members) {
+            var prototype = this.prototype,
+                enumerables = Ext.enumerables,
+                name, i, member, previous;
+
+            if (arguments.length === 2) {
+                name = members;
+                member = arguments[1];
+
+                if (typeof member == 'function') {
+                    if (typeof prototype[name] == 'function') {
+                        previous = prototype[name];
+                        member.$previous = previous;
+                    }
+
+                    this.ownMethod(name, member);
+                }
+                else {
+                    prototype[name] = member;
+                }
+
+                return this;
+            }
+
+            for (name in members) {
+                if (members.hasOwnProperty(name)) {
+                    member = members[name];
+
+                    if (typeof member === 'function') {
+                        if (typeof prototype[name] === 'function') {
+                            previous = prototype[name];
+                            member.$previous = previous;
+                        }
+
+                        this.ownMethod(name, member);
+                    }
+                    else {
+                        prototype[name] = member;
+                    }
+                }
+            }
+
+            if (enumerables) {
+                for (i = enumerables.length; i--;) {
+                    name = enumerables[i];
+
+                    if (members.hasOwnProperty(name)) {
+                        if (typeof prototype[name] !== 'undefined') {
+                            previous = prototype[name];
+                            members[name].$previous = previous;
+                        }
+
+                        this.ownMethod(name, members[name]);
+                    }
+                }
+            }
+
+            return this;
+        },
+
+        
+        
+        mixin: function(name, cls) {
+            var mixin = cls.prototype,
+                my = this.prototype,
+                key, fn;
+
+            for (key in mixin) {
+                if (mixin.hasOwnProperty(key)) {
+                    if (typeof my[key] === 'undefined' && key !== 'mixins' && key !== 'mixinId') {
+                        if (typeof mixin[key] === 'function') {
+                            fn = mixin[key];
+
+                            if (typeof fn.$owner === 'undefined') {
+                                this.ownMethod(key, fn);
+                            }
+                            else {
+                                my[key] = fn;
+                            }
+                        }
+                        else {
+                            my[key] = mixin[key];
+                        }
+                    }
+                    
+                    else if (key === 'config' && my.config && mixin.config) {
+                        Ext.Object.merge(my.config, mixin.config);
+                    }
+                    
+                }
+            }
+
+            if (typeof mixin.onClassMixedIn !== 'undefined') {
+                mixin.onClassMixedIn.call(cls, this);
+            }
+
+            if (!my.hasOwnProperty('mixins')) {
+                if ('mixins' in my) {
+                    my.mixins = Ext.Object.merge({}, my.mixins);
+                }
+                else {
+                    my.mixins = {};
+                }
+            }
+
+            my.mixins[name] = mixin;
+        },
+        
+
+        
+        getName: function() {
+            return Ext.getClassName(this);
+        },
+
+        
+        createAlias: flexSetter(function(alias, origin) {
+            this.prototype[alias] = function() {
+                return this[origin].apply(this, arguments);
+            }
+        })
+    });
+
+})(Ext.Function.flexSetter);
+
+
+(function() {
+
+    var Class,
+        Base = Ext.Base,
+        baseStaticProperties = [],
+        baseStaticProperty;
+
+    for (baseStaticProperty in Base) {
+        if (Base.hasOwnProperty(baseStaticProperty)) {
+            baseStaticProperties.push(baseStaticProperty);
+        }
+    }
+
+    
+    Ext.Class = Class = function(newClass, classData, onClassCreated) {
+        if (typeof newClass != 'function') {
+            onClassCreated = classData;
+            classData = newClass;
+            newClass = function() {
+                return this.constructor.apply(this, arguments);
+            };
+        }
+
+        if (!classData) {
+            classData = {};
+        }
+
+        var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
+            registeredPreprocessors = Class.getPreprocessors(),
+            index = 0,
+            preprocessors = [],
+            preprocessor, staticPropertyName, process, i, j, ln;
+
+        for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
+            staticPropertyName = baseStaticProperties[i];
+            newClass[staticPropertyName] = Base[staticPropertyName];
+        }
+
+        delete classData.preprocessors;
+
+        for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
+            preprocessor = preprocessorStack[j];
+
+            if (typeof preprocessor == 'string') {
+                preprocessor = registeredPreprocessors[preprocessor];
+
+                if (!preprocessor.always) {
+                    if (classData.hasOwnProperty(preprocessor.name)) {
+                        preprocessors.push(preprocessor.fn);
+                    }
+                }
+                else {
+                    preprocessors.push(preprocessor.fn);
+                }
+            }
+            else {
+                preprocessors.push(preprocessor);
+            }
+        }
+
+        classData.onClassCreated = onClassCreated || Ext.emptyFn;
+
+        classData.onBeforeClassCreated = function(cls, data) {
+            onClassCreated = data.onClassCreated;
+
+            delete data.onBeforeClassCreated;
+            delete data.onClassCreated;
+
+            cls.implement(data);
+
+            onClassCreated.call(cls, cls);
+        };
+
+        process = function(cls, data) {
+            preprocessor = preprocessors[index++];
+
+            if (!preprocessor) {
+                data.onBeforeClassCreated.apply(this, arguments);
+                return;
+            }
+
+            if (preprocessor.call(this, cls, data, process) !== false) {
+                process.apply(this, arguments);
+            }
+        };
+
+        process.call(Class, newClass, classData);
+
+        return newClass;
+    };
+
+    Ext.apply(Class, {
+
+        
+        preprocessors: {},
+
+        
+        registerPreprocessor: function(name, fn, always) {
+            this.preprocessors[name] = {
+                name: name,
+                always: always ||  false,
+                fn: fn
+            };
+
+            return this;
+        },
+
+        
+        getPreprocessor: function(name) {
+            return this.preprocessors[name];
+        },
+
+        getPreprocessors: function() {
+            return this.preprocessors;
+        },
+
+        
+        getDefaultPreprocessors: function() {
+            return this.defaultPreprocessors || [];
+        },
+
+        
+        setDefaultPreprocessors: function(preprocessors) {
+            this.defaultPreprocessors = Ext.Array.from(preprocessors);
+
+            return this;
+        },
+
+        
+        setDefaultPreprocessorPosition: function(name, offset, relativeName) {
+            var defaultPreprocessors = this.defaultPreprocessors,
+                index;
+
+            if (typeof offset == 'string') {
+                if (offset === 'first') {
+                    defaultPreprocessors.unshift(name);
+
+                    return this;
+                }
+                else if (offset === 'last') {
+                    defaultPreprocessors.push(name);
+
+                    return this;
+                }
+
+                offset = (offset === 'after') ? 1 : -1;
+            }
+
+            index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
+
+            if (index !== -1) {
+                Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
+            }
+
+            return this;
+        }
+    });
+
+    
+    Class.registerPreprocessor('extend', function(cls, data) {
+        var extend = data.extend,
+            base = Ext.Base,
+            basePrototype = base.prototype,
+            prototype = function() {},
+            parent, i, k, ln, staticName, parentStatics,
+            parentPrototype, clsPrototype;
+
+        if (extend && extend !== Object) {
+            parent = extend;
+        }
+        else {
+            parent = base;
+        }
+
+        parentPrototype = parent.prototype;
+
+        prototype.prototype = parentPrototype;
+        clsPrototype = cls.prototype = new prototype();
+
+        if (!('$class' in parent)) {
+            for (i in basePrototype) {
+                if (!parentPrototype[i]) {
+                    parentPrototype[i] = basePrototype[i];
+                }
+            }
+        }
+
+        clsPrototype.self = cls;
+
+        cls.superclass = clsPrototype.superclass = parentPrototype;
+
+        delete data.extend;
+
+        
+        
+        parentStatics = parentPrototype.$inheritableStatics;
+
+        if (parentStatics) {
+            for (k = 0, ln = parentStatics.length; k < ln; k++) {
+                staticName = parentStatics[k];
+
+                if (!cls.hasOwnProperty(staticName)) {
+                    cls[staticName] = parent[staticName];
+                }
+            }
+        }
+        
+
+        
+        
+        if (parentPrototype.config) {
+            clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
+        }
+        else {
+            clsPrototype.config = {};
+        }
+        
+
+        
+        if (clsPrototype.$onExtended) {
+            clsPrototype.$onExtended.call(cls, cls, data);
+        }
+
+        if (data.onClassExtended) {
+            clsPrototype.$onExtended = data.onClassExtended;
+            delete data.onClassExtended;
+        }
+        
+
+    }, true);
+
+    
+    
+    Class.registerPreprocessor('statics', function(cls, data) {
+        cls.addStatics(data.statics);
+
+        delete data.statics;
+    });
+    
+
+    
+    
+    Class.registerPreprocessor('inheritableStatics', function(cls, data) {
+        cls.addInheritableStatics(data.inheritableStatics);
+
+        delete data.inheritableStatics;
+    });
+    
+
+    
+    
+    Class.registerPreprocessor('config', function(cls, data) {
+        var prototype = cls.prototype;
+
+        Ext.Object.each(data.config, function(name) {
+            var cName = name.charAt(0).toUpperCase() + name.substr(1),
+                pName = name,
+                apply = 'apply' + cName,
+                setter = 'set' + cName,
+                getter = 'get' + cName;
+
+            if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
+                data[apply] = function(val) {
+                    return val;
+                };
+            }
+
+            if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
+                data[setter] = function(val) {
+                    var ret = this[apply].call(this, val, this[pName]);
+
+                    if (typeof ret != 'undefined') {
+                        this[pName] = ret;
+                    }
+
+                    return this;
+                };
+            }
+
+            if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
+                data[getter] = function() {
+                    return this[pName];
+                };
+            }
+        });
+
+        Ext.Object.merge(prototype.config, data.config);
+        delete data.config;
+    });
+    
+
+    
+    
+    Class.registerPreprocessor('mixins', function(cls, data) {
+        var mixins = data.mixins,
+            name, mixin, i, ln;
+
+        delete data.mixins;
+
+        Ext.Function.interceptBefore(data, 'onClassCreated', function(cls) {
+            if (mixins instanceof Array) {
+                for (i = 0,ln = mixins.length; i < ln; i++) {
+                    mixin = mixins[i];
+                    name = mixin.prototype.mixinId || mixin.$className;
+
+                    cls.mixin(name, mixin);
+                }
+            }
+            else {
+                for (name in mixins) {
+                    if (mixins.hasOwnProperty(name)) {
+                        cls.mixin(name, mixins[name]);
+                    }
+                }
+            }
+        });
+    });
+
+    
+
+    Class.setDefaultPreprocessors([
+        'extend'
+        
+        ,'statics'
+        
+        
+        ,'inheritableStatics'
+        
+        
+        ,'config'
+        
+        
+        ,'mixins'
+        
+    ]);
+
+    
+    
+    Ext.extend = function(subclass, superclass, members) {
+        if (arguments.length === 2 && Ext.isObject(superclass)) {
+            members = superclass;
+            superclass = subclass;
+            subclass = null;
+        }
+
+        var cls;
+
+        if (!superclass) {
+            Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
+        }
+
+        members.extend = superclass;
+        members.preprocessors = [
+            'extend'
+            
+            ,'statics'
+            
+            
+            ,'inheritableStatics'
+            
+            
+            ,'mixins'
+            
+            
+            ,'config'
+            
+        ];
+
+        if (subclass) {
+            cls = new Class(subclass, members);
+        }
+        else {
+            cls = new Class(members);
+        }
+
+        cls.prototype.override = function(o) {
+            for (var m in o) {
+                if (o.hasOwnProperty(m)) {
+                    this[m] = o[m];
+                }
+            }
+        };
+
+        return cls;
+    };
+    
+
+})();
+
+
+(function(Class, alias) {
+
+    var slice = Array.prototype.slice;
+
+    var Manager = Ext.ClassManager = {
+
+        
+        classes: {},
+
+        
+        existCache: {},
+
+        
+        namespaceRewrites: [{
+            from: 'Ext.',
+            to: Ext
+        }],
+
+        
+        maps: {
+            alternateToName: {},
+            aliasToName: {},
+            nameToAliases: {}
+        },
+
+        
+        enableNamespaceParseCache: true,
+
+        
+        namespaceParseCache: {},
+
+        
+        instantiators: [],
+
+
+        
+        isCreated: function(className) {
+            var i, ln, part, root, parts;
+
+
+            if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
+                return true;
+            }
+
+            root = Ext.global;
+            parts = this.parseNamespace(className);
+
+            for (i = 0, ln = parts.length; i < ln; i++) {
+                part = parts[i];
+
+                if (typeof part !== 'string') {
+                    root = part;
+                } else {
+                    if (!root || !root[part]) {
+                        return false;
+                    }
+
+                    root = root[part];
+                }
+            }
+
+            Ext.Loader.historyPush(className);
+
+            this.existCache[className] = true;
+
+            return true;
+        },
+
+        
+        parseNamespace: function(namespace) {
+
+            var cache = this.namespaceParseCache;
+
+            if (this.enableNamespaceParseCache) {
+                if (cache.hasOwnProperty(namespace)) {
+                    return cache[namespace];
+                }
+            }
+
+            var parts = [],
+                rewrites = this.namespaceRewrites,
+                rewrite, from, to, i, ln, root = Ext.global;
+
+            for (i = 0, ln = rewrites.length; i < ln; i++) {
+                rewrite = rewrites[i];
+                from = rewrite.from;
+                to = rewrite.to;
+
+                if (namespace === from || namespace.substring(0, from.length) === from) {
+                    namespace = namespace.substring(from.length);
+
+                    if (typeof to !== 'string') {
+                        root = to;
+                    } else {
+                        parts = parts.concat(to.split('.'));
+                    }
+
+                    break;
+                }
+            }
+
+            parts.push(root);
+
+            parts = parts.concat(namespace.split('.'));
+
+            if (this.enableNamespaceParseCache) {
+                cache[namespace] = parts;
+            }
+
+            return parts;
+        },
+
+        
+        setNamespace: function(name, value) {
+            var root = Ext.global,
+                parts = this.parseNamespace(name),
+                ln = parts.length - 1,
+                leaf = parts[ln],
+                i, part;
+
+            for (i = 0; i < ln; i++) {
+                part = parts[i];
+
+                if (typeof part !== 'string') {
+                    root = part;
+                } else {
+                    if (!root[part]) {
+                        root[part] = {};
+                    }
+
+                    root = root[part];
+                }
+            }
+
+            root[leaf] = value;
+
+            return root[leaf];
+        },
+
+        
+        createNamespaces: function() {
+            var root = Ext.global,
+                parts, part, i, j, ln, subLn;
+
+            for (i = 0, ln = arguments.length; i < ln; i++) {
+                parts = this.parseNamespace(arguments[i]);
+
+                for (j = 0, subLn = parts.length; j < subLn; j++) {
+                    part = parts[j];
+
+                    if (typeof part !== 'string') {
+                        root = part;
+                    } else {
+                        if (!root[part]) {
+                            root[part] = {};
+                        }
+
+                        root = root[part];
+                    }
+                }
+            }
+
+            return root;
+        },
+
+        
+        set: function(name, value) {
+            var targetName = this.getName(value);
+
+            this.classes[name] = this.setNamespace(name, value);
+
+            if (targetName && targetName !== name) {
+                this.maps.alternateToName[name] = targetName;
+            }
+
+            return this;
+        },
+
+        
+        get: function(name) {
+            if (this.classes.hasOwnProperty(name)) {
+                return this.classes[name];
+            }
+
+            var root = Ext.global,
+                parts = this.parseNamespace(name),
+                part, i, ln;
+
+            for (i = 0, ln = parts.length; i < ln; i++) {
+                part = parts[i];
+
+                if (typeof part !== 'string') {
+                    root = part;
+                } else {
+                    if (!root || !root[part]) {
+                        return null;
+                    }
+
+                    root = root[part];
+                }
+            }
+
+            return root;
+        },
+
+        
+        setAlias: function(cls, alias) {
+            var aliasToNameMap = this.maps.aliasToName,
+                nameToAliasesMap = this.maps.nameToAliases,
+                className;
+
+            if (typeof cls === 'string') {
+                className = cls;
+            } else {
+                className = this.getName(cls);
+            }
+
+            if (alias && aliasToNameMap[alias] !== className) {
+
+                aliasToNameMap[alias] = className;
+            }
+
+            if (!nameToAliasesMap[className]) {
+                nameToAliasesMap[className] = [];
+            }
+
+            if (alias) {
+                Ext.Array.include(nameToAliasesMap[className], alias);
+            }
+
+            return this;
+        },
+
+        
+        getByAlias: function(alias) {
+            return this.get(this.getNameByAlias(alias));
+        },
+
+        
+        getNameByAlias: function(alias) {
+            return this.maps.aliasToName[alias] || '';
+        },
+
+        
+        getNameByAlternate: function(alternate) {
+            return this.maps.alternateToName[alternate] || '';
+        },
+
+        
+        getAliasesByName: function(name) {
+            return this.maps.nameToAliases[name] || [];
+        },
+
+        
+        getName: function(object) {
+            return object && object.$className || '';
+        },
+
+        
+        getClass: function(object) {
+            return object && object.self || null;
+        },
+
+        
+        create: function(className, data, createdFn) {
+            var manager = this;
+
+
+            data.$className = className;
+
+            return new Class(data, function() {
+                var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
+                    registeredPostprocessors = manager.postprocessors,
+                    index = 0,
+                    postprocessors = [],
+                    postprocessor, process, i, ln;
+
+                delete data.postprocessors;
+
+                for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
+                    postprocessor = postprocessorStack[i];
+
+                    if (typeof postprocessor === 'string') {
+                        postprocessor = registeredPostprocessors[postprocessor];
+
+                        if (!postprocessor.always) {
+                            if (data[postprocessor.name] !== undefined) {
+                                postprocessors.push(postprocessor.fn);
+                            }
+                        }
+                        else {
+                            postprocessors.push(postprocessor.fn);
+                        }
+                    }
+                    else {
+                        postprocessors.push(postprocessor);
+                    }
+                }
+
+                process = function(clsName, cls, clsData) {
+                    postprocessor = postprocessors[index++];
+
+                    if (!postprocessor) {
+                        manager.set(className, cls);
+
+                        Ext.Loader.historyPush(className);
+
+                        if (createdFn) {
+                            createdFn.call(cls, cls);
+                        }
+
+                        return;
+                    }
+
+                    if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
+                        process.apply(this, arguments);
+                    }
+                };
+
+                process.call(manager, className, this, data);
+            });
+        },
+
+        
+        instantiateByAlias: function() {
+            var alias = arguments[0],
+                args = slice.call(arguments),
+                className = this.getNameByAlias(alias);
+
+            if (!className) {
+                className = this.maps.aliasToName[alias];
+
+
+
+                Ext.syncRequire(className);
+            }
+
+            args[0] = className;
+
+            return this.instantiate.apply(this, args);
+        },
+
+        
+        instantiate: function() {
+            var name = arguments[0],
+                args = slice.call(arguments, 1),
+                alias = name,
+                possibleName, cls;
+
+            if (typeof name !== 'function') {
+
+                cls = this.get(name);
+            }
+            else {
+                cls = name;
+            }
+
+            
+            if (!cls) {
+                possibleName = this.getNameByAlias(name);
+
+                if (possibleName) {
+                    name = possibleName;
+
+                    cls = this.get(name);
+                }
+            }
+
+            
+            if (!cls) {
+                possibleName = this.getNameByAlternate(name);
+
+                if (possibleName) {
+                    name = possibleName;
+
+                    cls = this.get(name);
+                }
+            }
+
+            
+            if (!cls) {
+
+                Ext.syncRequire(name);
+
+                cls = this.get(name);
+            }
+
+
+
+            return this.getInstantiator(args.length)(cls, args);
+        },
+
+        
+        dynInstantiate: function(name, args) {
+            args = Ext.Array.from(args, true);
+            args.unshift(name);
+
+            return this.instantiate.apply(this, args);
+        },
+
+        
+        getInstantiator: function(length) {
+            if (!this.instantiators[length]) {
+                var i = length,
+                    args = [];
+
+                for (i = 0; i < length; i++) {
+                    args.push('a['+i+']');
+                }
+
+                this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
+            }
+
+            return this.instantiators[length];
+        },
+
+        
+        postprocessors: {},
+
+        
+        defaultPostprocessors: [],
+
+        
+        registerPostprocessor: function(name, fn, always) {
+            this.postprocessors[name] = {
+                name: name,
+                always: always ||  false,
+                fn: fn
+            };
+
+            return this;
+        },
+
+        
+        setDefaultPostprocessors: function(postprocessors) {
+            this.defaultPostprocessors = Ext.Array.from(postprocessors);
+
+            return this;
+        },
+
+        
+        setDefaultPostprocessorPosition: function(name, offset, relativeName) {
+            var defaultPostprocessors = this.defaultPostprocessors,
+                index;
+
+            if (typeof offset === 'string') {
+                if (offset === 'first') {
+                    defaultPostprocessors.unshift(name);
+
+                    return this;
+                }
+                else if (offset === 'last') {
+                    defaultPostprocessors.push(name);
+
+                    return this;
+                }
+
+                offset = (offset === 'after') ? 1 : -1;
+            }
+
+            index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
+
+            if (index !== -1) {
+                Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);
+            }
+
+            return this;
+        },
+
+        
+        getNamesByExpression: function(expression) {
+            var nameToAliasesMap = this.maps.nameToAliases,
+                names = [],
+                name, alias, aliases, possibleName, regex, i, ln;
+
+
+            if (expression.indexOf('*') !== -1) {
+                expression = expression.replace(/\*/g, '(.*?)');
+                regex = new RegExp('^' + expression + '$');
+
+                for (name in nameToAliasesMap) {
+                    if (nameToAliasesMap.hasOwnProperty(name)) {
+                        aliases = nameToAliasesMap[name];
+
+                        if (name.search(regex) !== -1) {
+                            names.push(name);
+                        }
+                        else {
+                            for (i = 0, ln = aliases.length; i < ln; i++) {
+                                alias = aliases[i];
+
+                                if (alias.search(regex) !== -1) {
+                                    names.push(name);
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+
+            } else {
+                possibleName = this.getNameByAlias(expression);
+
+                if (possibleName) {
+                    names.push(possibleName);
+                } else {
+                    possibleName = this.getNameByAlternate(expression);
+
+                    if (possibleName) {
+                        names.push(possibleName);
+                    } else {
+                        names.push(expression);
+                    }
+                }
+            }
+
+            return names;
+        }
+    };
+
+    var defaultPostprocessors = Manager.defaultPostprocessors;
+    
+
+    
+    Manager.registerPostprocessor('alias', function(name, cls, data) {
+        var aliases = data.alias,
+            i, ln;
+
+        delete data.alias;
+
+        for (i = 0, ln = aliases.length; i < ln; i++) {
+            alias = aliases[i];
+
+            this.setAlias(cls, alias);
+        }
+    });
+
+    
+    Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
+        fn.call(this, name, new cls(), data);
+        return false;
+    });
+
+    
+    Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
+        var alternates = data.alternateClassName,
+            i, ln, alternate;
+
+        if (!(alternates instanceof Array)) {
+            alternates = [alternates];
+        }
+
+        for (i = 0, ln = alternates.length; i < ln; i++) {
+            alternate = alternates[i];
+
+
+            this.set(alternate, cls);
+        }
+    });
+
+    Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
+
+    Ext.apply(Ext, {
+        
+        create: alias(Manager, 'instantiate'),
+
+        
+        factory: function(item, namespace) {
+            if (item instanceof Array) {
+                var i, ln;
+
+                for (i = 0, ln = item.length; i < ln; i++) {
+                    item[i] = Ext.factory(item[i], namespace);
+                }
+
+                return item;
+            }
+
+            var isString = (typeof item === 'string');
+
+            if (isString || (item instanceof Object && item.constructor === Object)) {
+                var name, config = {};
+
+                if (isString) {
+                    name = item;
+                }
+                else {
+                    name = item.className;
+                    config = item;
+                    delete config.className;
+                }
+
+                if (namespace !== undefined && name.indexOf(namespace) === -1) {
+                    name = namespace + '.' + Ext.String.capitalize(name);
+                }
+
+                return Ext.create(name, config);
+            }
+
+            if (typeof item === 'function') {
+                return Ext.create(item);
+            }
+
+            return item;
+        },
+
+        
+        widget: function(name) {
+            var args = slice.call(arguments);
+            args[0] = 'widget.' + name;
+
+            return Manager.instantiateByAlias.apply(Manager, args);
+        },
+
+        
+        createByAlias: alias(Manager, 'instantiateByAlias'),
+
+        
+        
+        
+        define: function (className, data, createdFn) {
+            if (!data.override) {
+                return Manager.create.apply(Manager, arguments);
+            }
+
+            var requires = data.requires,
+                uses = data.uses,
+                overrideName = className;
+
+            className = data.override;
+
+            
+            data = Ext.apply({}, data);
+            delete data.requires;
+            delete data.uses;
+            delete data.override;
+
+            
+            if (typeof requires == 'string') {
+                requires = [ className, requires ];
+            } else if (requires) {
+                requires = requires.slice(0);
+                requires.unshift(className);
+            } else {
+                requires = [ className ];
+            }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+            return Manager.create(overrideName, {
+                    requires: requires,
+                    uses: uses,
+                    isPartial: true,
+                    constructor: function () {
+                    }
+                }, function () {
+                    var cls = Manager.get(className);
+                    if (cls.override) { 
+                        cls.override(data);
+                    } else { 
+                        cls.self.override(data);
+                    }
+
+                    if (createdFn) {
+                        
+                        
+                        
+                        createdFn.call(cls);
+                    }
+                });
+        },
+
+        
+        getClassName: alias(Manager, 'getName'),
+
+        
+        getDisplayName: function(object) {
+            if (object.displayName) {
+                return object.displayName;
+            }
+
+            if (object.$name && object.$class) {
+                return Ext.getClassName(object.$class) + '#' + object.$name;
+            }
+
+            if (object.$className) {
+                return object.$className;
+            }
+
+            return 'Anonymous';
+        },
+
+        
+        getClass: alias(Manager, 'getClass'),
+
+        
+        namespace: alias(Manager, 'createNamespaces')
+    });
+
+    
+    Ext.createWidget = Ext.widget;
+
+    
+    Ext.ns = Ext.namespace;
+
+    Class.registerPreprocessor('className', function(cls, data) {
+        if (data.$className) {
+            cls.$className = data.$className;
+        }
+    }, true);
+
+    Class.setDefaultPreprocessorPosition('className', 'first');
+
+    Class.registerPreprocessor('xtype', function(cls, data) {
+        var xtypes = Ext.Array.from(data.xtype),
+            widgetPrefix = 'widget.',
+            aliases = Ext.Array.from(data.alias),
+            i, ln, xtype;
+
+        data.xtype = xtypes[0];
+        data.xtypes = xtypes;
+
+        aliases = data.alias = Ext.Array.from(data.alias);
+
+        for (i = 0,ln = xtypes.length; i < ln; i++) {
+            xtype = xtypes[i];
+
+
+            aliases.push(widgetPrefix + xtype);
+        }
+
+        data.alias = aliases;
+    });
+
+    Class.setDefaultPreprocessorPosition('xtype', 'last');
+
+    Class.registerPreprocessor('alias', function(cls, data) {
+        var aliases = Ext.Array.from(data.alias),
+            xtypes = Ext.Array.from(data.xtypes),
+            widgetPrefix = 'widget.',
+            widgetPrefixLength = widgetPrefix.length,
+            i, ln, alias, xtype;
+
+        for (i = 0, ln = aliases.length; i < ln; i++) {
+            alias = aliases[i];
+
+
+            if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {
+                xtype = alias.substring(widgetPrefixLength);
+                Ext.Array.include(xtypes, xtype);
+
+                if (!cls.xtype) {
+                    cls.xtype = data.xtype = xtype;
+                }
+            }
+        }
+
+        data.alias = aliases;
+        data.xtypes = xtypes;
+    });
+
+    Class.setDefaultPreprocessorPosition('alias', 'last');
+
+})(Ext.Class, Ext.Function.alias);
+
+
+(function(Manager, Class, flexSetter, alias) {
+
+    var
+        dependencyProperties = ['extend', 'mixins', 'requires'],
+        Loader;
+
+    Loader = Ext.Loader = {
+        
+        documentHead: typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
+
+        
+        isLoading: false,
+
+        
+        queue: [],
+
+        
+        isFileLoaded: {},
+
+        
+        readyListeners: [],
+
+        
+        optionalRequires: [],
+
+        
+        requiresMap: {},
+
+        
+        numPendingFiles: 0,
+
+        
+        numLoadedFiles: 0,
+
+        
+        hasFileLoadError: false,
+
+        
+        classNameToFilePathMap: {},
+
+        
+        history: [],
+
+        
+        config: {
+            
+            enabled: false,
+
+            
+            disableCaching: true,
+
+            
+            disableCachingParam: '_dc',
+
+            
+            paths: {
+                'Ext': '.'
+            }
+        },
+
+        
+        setConfig: function(name, value) {
+            if (Ext.isObject(name) && arguments.length === 1) {
+                Ext.Object.merge(this.config, name);
+            }
+            else {
+                this.config[name] = (Ext.isObject(value)) ? Ext.Object.merge(this.config[name], value) : value;
+            }
+
+            return this;
+        },
+
+        
+        getConfig: function(name) {
+            if (name) {
+                return this.config[name];
+            }
+
+            return this.config;
+        },
+
+        
+        setPath: flexSetter(function(name, path) {
+            this.config.paths[name] = path;
+
+            return this;
+        }),
+
+        
+        getPath: function(className) {
+            var path = '',
+                paths = this.config.paths,
+                prefix = this.getPrefix(className);
+
+            if (prefix.length > 0) {
+                if (prefix === className) {
+                    return paths[prefix];
+                }
+
+                path = paths[prefix];
+                className = className.substring(prefix.length + 1);
+            }
+
+            if (path.length > 0) {
+                path += '/';
+            }
+
+            return path.replace(/\/\.\//g, '/') + className.replace(/\./g, "/") + '.js';
+        },
+
+        
+        getPrefix: function(className) {
+            var paths = this.config.paths,
+                prefix, deepestPrefix = '';
+
+            if (paths.hasOwnProperty(className)) {
+                return className;
+            }
+
+            for (prefix in paths) {
+                if (paths.hasOwnProperty(prefix) && prefix + '.' === className.substring(0, prefix.length + 1)) {
+                    if (prefix.length > deepestPrefix.length) {
+                        deepestPrefix = prefix;
+                    }
+                }
+            }
+
+            return deepestPrefix;
+        },
+
+        
+        refreshQueue: function() {
+            var ln = this.queue.length,
+                i, item, j, requires;
+
+            if (ln === 0) {
+                this.triggerReady();
+                return;
+            }
+
+            for (i = 0; i < ln; i++) {
+                item = this.queue[i];
+
+                if (item) {
+                    requires = item.requires;
+
+                    
+                    
+                    if (requires.length > this.numLoadedFiles) {
+                        continue;
+                    }
+
+                    j = 0;
+
+                    do {
+                        if (Manager.isCreated(requires[j])) {
+                            
+                            Ext.Array.erase(requires, j, 1);
+                        }
+                        else {
+                            j++;
+                        }
+                    } while (j < requires.length);
+
+                    if (item.requires.length === 0) {
+                        Ext.Array.erase(this.queue, i, 1);
+                        item.callback.call(item.scope);
+                        this.refreshQueue();
+                        break;
+                    }
+                }
+            }
+
+            return this;
+        },
+
+        
+        injectScriptElement: function(url, onLoad, onError, scope) {
+            var script = document.createElement('script'),
+                me = this,
+                onLoadFn = function() {
+                    me.cleanupScriptElement(script);
+                    onLoad.call(scope);
+                },
+                onErrorFn = function() {
+                    me.cleanupScriptElement(script);
+                    onError.call(scope);
+                };
+
+            script.type = 'text/javascript';
+            script.src = url;
+            script.onload = onLoadFn;
+            script.onerror = onErrorFn;
+            script.onreadystatechange = function() {
+                if (this.readyState === 'loaded' || this.readyState === 'complete') {
+                    onLoadFn();
+                }
+            };
+
+            this.documentHead.appendChild(script);
+
+            return script;
+        },
+
+        
+        cleanupScriptElement: function(script) {
+            script.onload = null;
+            script.onreadystatechange = null;
+            script.onerror = null;
+
+            return this;
+        },
+
+        
+        loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
+            var me = this,
+                noCacheUrl = url + (this.getConfig('disableCaching') ? ('?' + this.getConfig('disableCachingParam') + '=' + Ext.Date.now()) : ''),
+                fileName = url.split('/').pop(),
+                isCrossOriginRestricted = false,
+                xhr, status, onScriptError;
+
+            scope = scope || this;
+
+            this.isLoading = true;
+
+            if (!synchronous) {
+                onScriptError = function() {
+                    onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
+                };
+
+                if (!Ext.isReady && Ext.onDocumentReady) {
+                    Ext.onDocumentReady(function() {
+                        me.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
+                    });
+                }
+                else {
+                    this.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
+                }
+            }
+            else {
+                if (typeof XMLHttpRequest !== 'undefined') {
+                    xhr = new XMLHttpRequest();
+                } else {
+                    xhr = new ActiveXObject('Microsoft.XMLHTTP');
+                }
+
+                try {
+                    xhr.open('GET', noCacheUrl, false);
+                    xhr.send(null);
+                } catch (e) {
+                    isCrossOriginRestricted = true;
+                }
+
+                status = (xhr.status === 1223) ? 204 : xhr.status;
+
+                if (!isCrossOriginRestricted) {
+                    isCrossOriginRestricted = (status === 0);
+                }
+
+                if (isCrossOriginRestricted
+                ) {
+                    onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " +
+                                       "being loaded from a different domain or from the local file system whereby cross origin " +
+                                       "requests are not allowed due to security reasons. Use asynchronous loading with " +
+                                       "Ext.require instead.", synchronous);
+                }
+                else if (status >= 200 && status < 300
+                ) {
+                    
+                    new Function(xhr.responseText + "\n//@ sourceURL=" + fileName)();
+
+                    onLoad.call(scope);
+                }
+                else {
+                    onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; please " +
+                                       "verify that the file exists. " +
+                                       "XHR status code: " + status, synchronous);
+                }
+
+                
+                xhr = null;
+            }
+        },
+
+        
+        exclude: function(excludes) {
+            var me = this;
+
+            return {
+                require: function(expressions, fn, scope) {
+                    return me.require(expressions, fn, scope, excludes);
+                },
+
+                syncRequire: function(expressions, fn, scope) {
+                    return me.syncRequire(expressions, fn, scope, excludes);
+                }
+            };
+        },
+
+        
+        syncRequire: function() {
+            this.syncModeEnabled = true;
+            this.require.apply(this, arguments);
+            this.refreshQueue();
+            this.syncModeEnabled = false;
+        },
+
+        
+        require: function(expressions, fn, scope, excludes) {
+            var filePath, expression, exclude, className, excluded = {},
+                excludedClassNames = [],
+                possibleClassNames = [],
+                possibleClassName, classNames = [],
+                i, j, ln, subLn;
+
+            expressions = Ext.Array.from(expressions);
+            excludes = Ext.Array.from(excludes);
+
+            fn = fn || Ext.emptyFn;
+
+            scope = scope || Ext.global;
+
+            for (i = 0, ln = excludes.length; i < ln; i++) {
+                exclude = excludes[i];
+
+                if (typeof exclude === 'string' && exclude.length > 0) {
+                    excludedClassNames = Manager.getNamesByExpression(exclude);
+
+                    for (j = 0, subLn = excludedClassNames.length; j < subLn; j++) {
+                        excluded[excludedClassNames[j]] = true;
+                    }
+                }
+            }
+
+            for (i = 0, ln = expressions.length; i < ln; i++) {
+                expression = expressions[i];
+
+                if (typeof expression === 'string' && expression.length > 0) {
+                    possibleClassNames = Manager.getNamesByExpression(expression);
+
+                    for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
+                        possibleClassName = possibleClassNames[j];
+
+                        if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
+                            Ext.Array.include(classNames, possibleClassName);
+                        }
+                    }
+                }
+            }
+
+            
+            
+            if (!this.config.enabled) {
+                if (classNames.length > 0) {
+                    Ext.Error.raise({
+                        sourceClass: "Ext.Loader",
+                        sourceMethod: "require",
+                        msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
+                             "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
+                    });
+                }
+            }
+
+            if (classNames.length === 0) {
+                fn.call(scope);
+                return this;
+            }
+
+            this.queue.push({
+                requires: classNames,
+                callback: fn,
+                scope: scope
+            });
+
+            classNames = classNames.slice();
+
+            for (i = 0, ln = classNames.length; i < ln; i++) {
+                className = classNames[i];
+
+                if (!this.isFileLoaded.hasOwnProperty(className)) {
+                    this.isFileLoaded[className] = false;
+
+                    filePath = this.getPath(className);
+
+                    this.classNameToFilePathMap[className] = filePath;
+
+                    this.numPendingFiles++;
+
+                    this.loadScriptFile(
+                        filePath,
+                        Ext.Function.pass(this.onFileLoaded, [className, filePath], this),
+                        Ext.Function.pass(this.onFileLoadError, [className, filePath]),
+                        this,
+                        this.syncModeEnabled
+                    );
+                }
+            }
+
+            return this;
+        },
+
+        
+        onFileLoaded: function(className, filePath) {
+            this.numLoadedFiles++;
+
+            this.isFileLoaded[className] = true;
+
+            this.numPendingFiles--;
+
+            if (this.numPendingFiles === 0) {
+                this.refreshQueue();
+            }
+
+
+        },
+
+        
+        onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
+            this.numPendingFiles--;
+            this.hasFileLoadError = true;
+
+        },
+
+        
+        addOptionalRequires: function(requires) {
+            var optionalRequires = this.optionalRequires,
+                i, ln, require;
+
+            requires = Ext.Array.from(requires);
+
+            for (i = 0, ln = requires.length; i < ln; i++) {
+                require = requires[i];
+
+                Ext.Array.include(optionalRequires, require);
+            }
+
+            return this;
+        },
+
+        
+        triggerReady: function(force) {
+            var readyListeners = this.readyListeners,
+                optionalRequires, listener;
+
+            if (this.isLoading || force) {
+                this.isLoading = false;
+
+                if (this.optionalRequires.length) {
+                    
+                    optionalRequires = Ext.Array.clone(this.optionalRequires);
+
+                    
+                    this.optionalRequires.length = 0;
+
+                    this.require(optionalRequires, Ext.Function.pass(this.triggerReady, [true], this), this);
+                    return this;
+                }
+
+                while (readyListeners.length) {
+                    listener = readyListeners.shift();
+                    listener.fn.call(listener.scope);
+
+                    if (this.isLoading) {
+                        return this;
+                    }
+                }
+            }
+
+            return this;
+        },
+
+        
+        onReady: function(fn, scope, withDomReady, options) {
+            var oldFn;
+
+            if (withDomReady !== false && Ext.onDocumentReady) {
+                oldFn = fn;
+
+                fn = function() {
+                    Ext.onDocumentReady(oldFn, scope, options);
+                };
+            }
+
+            if (!this.isLoading) {
+                fn.call(scope);
+            }
+            else {
+                this.readyListeners.push({
+                    fn: fn,
+                    scope: scope
+                });
+            }
+        },
+
+        
+        historyPush: function(className) {
+            if (className && this.isFileLoaded.hasOwnProperty(className)) {
+                Ext.Array.include(this.history, className);
+            }
+
+            return this;
+        }
+    };
+
+    
+    Ext.require = alias(Loader, 'require');
+
+    
+    Ext.syncRequire = alias(Loader, 'syncRequire');
+
+    
+    Ext.exclude = alias(Loader, 'exclude');
+
+    
+    Ext.onReady = function(fn, scope, options) {
+        Loader.onReady(fn, scope, true, options);
+    };
+
+    
+    Class.registerPreprocessor('loader', function(cls, data, continueFn) {
+        var me = this,
+            dependencies = [],
+            className = Manager.getName(cls),
+            i, j, ln, subLn, value, propertyName, propertyValue;
+
+        
+
+        for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
+            propertyName = dependencyProperties[i];
+
+            if (data.hasOwnProperty(propertyName)) {
+                propertyValue = data[propertyName];
+
+                if (typeof propertyValue === 'string') {
+                    dependencies.push(propertyValue);
+                }
+                else if (propertyValue instanceof Array) {
+                    for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
+                        value = propertyValue[j];
+
+                        if (typeof value === 'string') {
+                            dependencies.push(value);
+                        }
+                    }
+                }
+                else if (typeof propertyValue != 'function') {
+                    for (j in propertyValue) {
+                        if (propertyValue.hasOwnProperty(j)) {
+                            value = propertyValue[j];
+
+                            if (typeof value === 'string') {
+                                dependencies.push(value);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (dependencies.length === 0) {
+
+            return;
+        }
+
+
+        Loader.require(dependencies, function() {
+            for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
+                propertyName = dependencyProperties[i];
+
+                if (data.hasOwnProperty(propertyName)) {
+                    propertyValue = data[propertyName];
+
+                    if (typeof propertyValue === 'string') {
+                        data[propertyName] = Manager.get(propertyValue);
+                    }
+                    else if (propertyValue instanceof Array) {
+                        for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
+                            value = propertyValue[j];
+
+                            if (typeof value === 'string') {
+                                data[propertyName][j] = Manager.get(value);
+                            }
+                        }
+                    }
+                    else if (typeof propertyValue != 'function') {
+                        for (var k in propertyValue) {
+                            if (propertyValue.hasOwnProperty(k)) {
+                                value = propertyValue[k];
+
+                                if (typeof value === 'string') {
+                                    data[propertyName][k] = Manager.get(value);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            continueFn.call(me, cls, data);
+        });
+
+        return false;
+    }, true);
+
+    Class.setDefaultPreprocessorPosition('loader', 'after', 'className');
+
+    
+    Manager.registerPostprocessor('uses', function(name, cls, data) {
+        var uses = Ext.Array.from(data.uses),
+            items = [],
+            i, ln, item;
+
+        for (i = 0, ln = uses.length; i < ln; i++) {
+            item = uses[i];
+
+            if (typeof item === 'string') {
+                items.push(item);
+            }
+        }
+
+        Loader.addOptionalRequires(items);
+    });
+
+    Manager.setDefaultPostprocessorPosition('uses', 'last');
+
+})(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias);
+
+
+Ext.Error = Ext.extend(Error, {
+    statics: {
+        
+        ignore: false,
+
+        
+        
+
+        
+        raise: function(err){
+            err = err || {};
+            if (Ext.isString(err)) {
+                err = { msg: err };
+            }
+
+            var method = this.raise.caller;
+
+            if (method) {
+                if (method.$name) {
+                    err.sourceMethod = method.$name;
+                }
+                if (method.$owner) {
+                    err.sourceClass = method.$owner.$className;
+                }
+            }
+
+            if (Ext.Error.handle(err) !== true) {
+                var msg = Ext.Error.prototype.toString.call(err);
+
+                Ext.log({
+                    msg: msg,
+                    level: 'error',
+                    dump: err,
+                    stack: true
+                });
+
+                throw new Ext.Error(err);
+            }
+        },
+
+        
+        handle: function(){
+            return Ext.Error.ignore;
+        }
+    },
+
+    
+    name: 'Ext.Error',
+
+    
+    constructor: function(config){
+        if (Ext.isString(config)) {
+            config = { msg: config };
+        }
+
+        var me = this;
+
+        Ext.apply(me, config);
+
+        me.message = me.message || me.msg; 
+        
+    },
+
+    
+    toString: function(){
+        var me = this,
+            className = me.className ? me.className  : '',
+            methodName = me.methodName ? '.' + me.methodName + '(): ' : '',
+            msg = me.msg || '(No description provided)';
+
+        return className + methodName + msg;
+    }
+});
+
+
+
+
+
+
+
+Ext.JSON = new(function() {
+    var useHasOwn = !! {}.hasOwnProperty,
+    isNative = function() {
+        var useNative = null;
+
+        return function() {
+            if (useNative === null) {
+                useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
+            }
+
+            return useNative;
+        };
+    }(),
+    pad = function(n) {
+        return n < 10 ? "0" + n : n;
+    },
+    doDecode = function(json) {
+        return eval("(" + json + ')');
+    },
+    doEncode = function(o) {
+        if (!Ext.isDefined(o) || o === null) {
+            return "null";
+        } else if (Ext.isArray(o)) {
+            return encodeArray(o);
+        } else if (Ext.isDate(o)) {
+            return Ext.JSON.encodeDate(o);
+        } else if (Ext.isString(o)) {
+            return encodeString(o);
+        } else if (typeof o == "number") {
+            
+            return isFinite(o) ? String(o) : "null";
+        } else if (Ext.isBoolean(o)) {
+            return String(o);
+        } else if (Ext.isObject(o)) {
+            return encodeObject(o);
+        } else if (typeof o === "function") {
+            return "null";
+        }
+        return 'undefined';
+    },
+    m = {
+        "\b": '\\b',
+        "\t": '\\t',
+        "\n": '\\n',
+        "\f": '\\f',
+        "\r": '\\r',
+        '"': '\\"',
+        "\\": '\\\\',
+        '\x0b': '\\u000b' 
+    },
+    charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g,
+    encodeString = function(s) {
+        return '"' + s.replace(charToReplace, function(a) {
+            var c = m[a];
+            return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+        }) + '"';
+    },
+    encodeArray = function(o) {
+        var a = ["[", ""],
+        
+        len = o.length,
+        i;
+        for (i = 0; i < len; i += 1) {
+            a.push(doEncode(o[i]), ',');
+        }
+        
+        a[a.length - 1] = ']';
+        return a.join("");
+    },
+    encodeObject = function(o) {
+        var a = ["{", ""],
+        
+        i;
+        for (i in o) {
+            if (!useHasOwn || o.hasOwnProperty(i)) {
+                a.push(doEncode(i), ":", doEncode(o[i]), ',');
+            }
+        }
+        
+        a[a.length - 1] = '}';
+        return a.join("");
+    };
+
+    
+    this.encodeDate = function(o) {
+        return '"' + o.getFullYear() + "-"
+        + pad(o.getMonth() + 1) + "-"
+        + pad(o.getDate()) + "T"
+        + pad(o.getHours()) + ":"
+        + pad(o.getMinutes()) + ":"
+        + pad(o.getSeconds()) + '"';
+    };
+
+    
+    this.encode = function() {
+        var ec;
+        return function(o) {
+            if (!ec) {
+                
+                ec = isNative() ? JSON.stringify : doEncode;
+            }
+            return ec(o);
+        };
+    }();
+
+
+    
+    this.decode = function() {
+        var dc;
+        return function(json, safe) {
+            if (!dc) {
+                
+                dc = isNative() ? JSON.parse : doDecode;
+            }
+            try {
+                return dc(json);
+            } catch (e) {
+                if (safe === true) {
+                    return null;
+                }
+                Ext.Error.raise({
+                    sourceClass: "Ext.JSON",
+                    sourceMethod: "decode",
+                    msg: "You're trying to decode an invalid JSON String: " + json
+                });
+            }
+        };
+    }();
+
+})();
+
+Ext.encode = Ext.JSON.encode;
+
+Ext.decode = Ext.JSON.decode;
+
+
+
+Ext.apply(Ext, {
+    userAgent: navigator.userAgent.toLowerCase(),
+    cache: {},
+    idSeed: 1000,
+    windowId: 'ext-window',
+    documentId: 'ext-document',
+
+    
+    isReady: false,
+
+    
+    enableGarbageCollector: true,
+
+    
+    enableListenerCollection: true,
+
+    
+    id: function(el, prefix) {
+        var me = this,
+            sandboxPrefix = '';
+        el = Ext.getDom(el, true) || {};
+        if (el === document) {
+            el.id = me.documentId;
+        }
+        else if (el === window) {
+            el.id = me.windowId;
+        }
+        if (!el.id) {
+            if (me.isSandboxed) {
+                if (!me.uniqueGlobalNamespace) {
+                    me.getUniqueGlobalNamespace();
+                }
+                sandboxPrefix = me.uniqueGlobalNamespace + '-';
+            }
+            el.id = sandboxPrefix + (prefix || "ext-gen") + (++Ext.idSeed);
+        }
+        return el.id;
+    },
+
+    
+    getBody: function() {
+        return Ext.get(document.body || false);
+    },
+
+    
+    getHead: function() {
+        var head;
+
+        return function() {
+            if (head == undefined) {
+                head = Ext.get(document.getElementsByTagName("head")[0]);
+            }
+
+            return head;
+        };
+    }(),
+
+    
+    getDoc: function() {
+        return Ext.get(document);
+    },
+
+    
+    getCmp: function(id) {
+        return Ext.ComponentManager.get(id);
+    },
+
+    
+    getOrientation: function() {
+        return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
+    },
+
+    
+    destroy: function() {
+        var ln = arguments.length,
+        i, arg;
+
+        for (i = 0; i < ln; i++) {
+            arg = arguments[i];
+            if (arg) {
+                if (Ext.isArray(arg)) {
+                    this.destroy.apply(this, arg);
+                }
+                else if (Ext.isFunction(arg.destroy)) {
+                    arg.destroy();
+                }
+                else if (arg.dom) {
+                    arg.remove();
+                }
+            }
+        }
+    },
+
+    
+    callback: function(callback, scope, args, delay){
+        if(Ext.isFunction(callback)){
+            args = args || [];
+            scope = scope || window;
+            if (delay) {
+                Ext.defer(callback, delay, scope, args);
+            } else {
+                callback.apply(scope, args);
+            }
+        }
+    },
+
+    
+    htmlEncode : function(value) {
+        return Ext.String.htmlEncode(value);
+    },
+
+    
+    htmlDecode : function(value) {
+         return Ext.String.htmlDecode(value);
+    },
+
+    
+    urlAppend : function(url, s) {
+        if (!Ext.isEmpty(s)) {
+            return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
+        }
+        return url;
+    }
+});
+
+
+Ext.ns = Ext.namespace;
+
+
+window.undefined = window.undefined;
+
+
+(function(){
+
+    var check = function(regex){
+            return regex.test(Ext.userAgent);
+        },
+        isStrict = document.compatMode == "CSS1Compat",
+        version = function (is, regex) {
+            var m;
+            return (is && (m = regex.exec(Ext.userAgent))) ? parseFloat(m[1]) : 0;
+        },
+        docMode = document.documentMode,
+        isOpera = check(/opera/),
+        isOpera10_5 = isOpera && check(/version\/10\.5/),
+        isChrome = check(/\bchrome\b/),
+        isWebKit = check(/webkit/),
+        isSafari = !isChrome && check(/safari/),
+        isSafari2 = isSafari && check(/applewebkit\/4/), 
+        isSafari3 = isSafari && check(/version\/3/),
+        isSafari4 = isSafari && check(/version\/4/),
+        isSafari5 = isSafari && check(/version\/5/),
+        isIE = !isOpera && check(/msie/),
+        isIE7 = isIE && (check(/msie 7/) || docMode == 7),
+        isIE8 = isIE && (check(/msie 8/) && docMode != 7 && docMode != 9 || docMode == 8),
+        isIE9 = isIE && (check(/msie 9/) && docMode != 7 && docMode != 8 || docMode == 9),
+        isIE6 = isIE && check(/msie 6/),
+        isGecko = !isWebKit && check(/gecko/),
+        isGecko3 = isGecko && check(/rv:1\.9/),
+        isGecko4 = isGecko && check(/rv:2\.0/),
+        isGecko5 = isGecko && check(/rv:5\./),
+        isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
+        isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
+        isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
+        isWindows = check(/windows|win32/),
+        isMac = check(/macintosh|mac os x/),
+        isLinux = check(/linux/),
+        scrollbarSize = null,
+        chromeVersion = version(true, /\bchrome\/(\d+\.\d+)/),
+        firefoxVersion = version(true, /\bfirefox\/(\d+\.\d+)/),
+        ieVersion = version(isIE, /msie (\d+\.\d+)/),
+        operaVersion = version(isOpera, /version\/(\d+\.\d+)/),
+        safariVersion = version(isSafari, /version\/(\d+\.\d+)/),
+        webKitVersion = version(isWebKit, /webkit\/(\d+\.\d+)/),
+        isSecure = /^https/i.test(window.location.protocol);
+
+    
+    try {
+        document.execCommand("BackgroundImageCache", false, true);
+    } catch(e) {}
+
+
+    Ext.setVersion('extjs', '4.0.7');
+    Ext.apply(Ext, {
+        
+        SSL_SECURE_URL : isSecure && isIE ? 'javascript:""' : 'about:blank',
+
+        
+
+        
+        scopeResetCSS : Ext.buildSettings.scopeResetCSS,
+
+        
+        enableNestedListenerRemoval : false,
+
+        
+        USE_NATIVE_JSON : false,
+
+        
+        getDom : function(el, strict) {
+            if (!el || !document) {
+                return null;
+            }
+            if (el.dom) {
+                return el.dom;
+            } else {
+                if (typeof el == 'string') {
+                    var e = document.getElementById(el);
+                    
+                    
+                    if (e && isIE && strict) {
+                        if (el == e.getAttribute('id')) {
+                            return e;
+                        } else {
+                            return null;
+                        }
+                    }
+                    return e;
+                } else {
+                    return el;
+                }
+            }
+        },
+
+        
+        removeNode : isIE6 || isIE7 ? function() {
+            var d;
+            return function(n){
+                if(n && n.tagName != 'BODY'){
+                    (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
+                    d = d || document.createElement('div');
+                    d.appendChild(n);
+                    d.innerHTML = '';
+                    delete Ext.cache[n.id];
+                }
+            };
+        }() : function(n) {
+            if (n && n.parentNode && n.tagName != 'BODY') {
+                (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
+                n.parentNode.removeChild(n);
+                delete Ext.cache[n.id];
+            }
+        },
+
+        isStrict: isStrict,
+
+        isIEQuirks: isIE && !isStrict,
+
+        
+        isOpera : isOpera,
+
+        
+        isOpera10_5 : isOpera10_5,
+
+        
+        isWebKit : isWebKit,
+
+        
+        isChrome : isChrome,
+
+        
+        isSafari : isSafari,
+
+        
+        isSafari3 : isSafari3,
+
+        
+        isSafari4 : isSafari4,
+
+        
+        isSafari5 : isSafari5,
+
+        
+        isSafari2 : isSafari2,
+
+        
+        isIE : isIE,
+
+        
+        isIE6 : isIE6,
+
+        
+        isIE7 : isIE7,
+
+        
+        isIE8 : isIE8,
+
+        
+        isIE9 : isIE9,
+
+        
+        isGecko : isGecko,
+
+        
+        isGecko3 : isGecko3,
+
+        
+        isGecko4 : isGecko4,
+
+        
+        isGecko5 : isGecko5,
+
+        
+        isFF3_0 : isFF3_0,
+
+        
+        isFF3_5 : isFF3_5,
+
+        
+        isFF3_6 : isFF3_6,
+
+        
+        isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,
+
+        
+        isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,
+
+        
+        isLinux : isLinux,
+
+        
+        isWindows : isWindows,
+
+        
+        isMac : isMac,
+
+        
+        chromeVersion: chromeVersion,
+
+        
+        firefoxVersion: firefoxVersion,
+
+        
+        ieVersion: ieVersion,
+
+        
+        operaVersion: operaVersion,
+
+        
+        safariVersion: safariVersion,
+
+        
+        webKitVersion: webKitVersion,
+
+        
+        isSecure: isSecure,
+
+        
+        BLANK_IMAGE_URL : (isIE6 || isIE7) ? '/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
+
+        
+        value : function(v, defaultValue, allowBlank){
+            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
+        },
+
+        
+        escapeRe : function(s) {
+            return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
+        },
+
+        
+        addBehaviors : function(o){
+            if(!Ext.isReady){
+                Ext.onReady(function(){
+                    Ext.addBehaviors(o);
+                });
+            } else {
+                var cache = {}, 
+                    parts,
+                    b,
+                    s;
+                for (b in o) {
+                    if ((parts = b.split('@'))[1]) { 
+                        s = parts[0];
+                        if(!cache[s]){
+                            cache[s] = Ext.select(s);
+                        }
+                        cache[s].on(parts[1], o[b]);
+                    }
+                }
+                cache = null;
+            }
+        },
+
+        
+        getScrollbarSize: function (force) {
+            if(!Ext.isReady){
+                return 0;
+            }
+
+            if(force === true || scrollbarSize === null){
+                
+                
+                
+                var cssClass = Ext.isIE9 ? '' : Ext.baseCSSPrefix + 'hide-offsets',
+                    
+                    div = Ext.getBody().createChild('<div class="' + cssClass + '" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
+                    child = div.child('div', true),
+                    w1 = child.offsetWidth;
+
+                div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
+
+                var w2 = child.offsetWidth, width = w1 - w2;
+                div.remove();
+
+                
+                scrollbarSize = { width: width, height: width };
+            }
+
+            return scrollbarSize;
+        },
+
+        
+        getScrollBarWidth: function(force){
+            var size = Ext.getScrollbarSize(force);
+            return size.width + 2; 
+        },
+
+        
+        copyTo : function(dest, source, names, usePrototypeKeys){
+            if(typeof names == 'string'){
+                names = names.split(/[,;\s]/);
+            }
+            Ext.each(names, function(name){
+                if(usePrototypeKeys || source.hasOwnProperty(name)){
+                    dest[name] = source[name];
+                }
+            }, this);
+            return dest;
+        },
+
+        
+        destroyMembers : function(o){
+            for (var i = 1, a = arguments, len = a.length; i < len; i++) {
+                Ext.destroy(o[a[i]]);
+                delete o[a[i]];
+            }
+        },
+
+        
+        log :
+            Ext.emptyFn,
+
+        
+        partition : function(arr, truth){
+            var ret = [[],[]];
+            Ext.each(arr, function(v, i, a) {
+                ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
+            });
+            return ret;
+        },
+
+        
+        invoke : function(arr, methodName){
+            var ret = [],
+                args = Array.prototype.slice.call(arguments, 2);
+            Ext.each(arr, function(v,i) {
+                if (v && typeof v[methodName] == 'function') {
+                    ret.push(v[methodName].apply(v, args));
+                } else {
+                    ret.push(undefined);
+                }
+            });
+            return ret;
+        },
+
+        
+        zip : function(){
+            var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
+                arrs = parts[0],
+                fn = parts[1][0],
+                len = Ext.max(Ext.pluck(arrs, "length")),
+                ret = [];
+
+            for (var i = 0; i < len; i++) {
+                ret[i] = [];
+                if(fn){
+                    ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
+                }else{
+                    for (var j = 0, aLen = arrs.length; j < aLen; j++){
+                        ret[i].push( arrs[j][i] );
+                    }
+                }
+            }
+            return ret;
+        },
+
+        
+        toSentence: function(items, connector) {
+            var length = items.length;
+
+            if (length <= 1) {
+                return items[0];
+            } else {
+                var head = items.slice(0, length - 1),
+                    tail = items[length - 1];
+
+                return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
+            }
+        },
+
+        
+        useShims: isIE6
+    });
+})();
+
+
+Ext.application = function(config) {
+    Ext.require('Ext.app.Application');
+
+    Ext.onReady(function() {
+        Ext.create('Ext.app.Application', config);
+    });
+};
+
+
+(function() {
+    Ext.ns('Ext.util');
+
+    Ext.util.Format = {};
+    var UtilFormat     = Ext.util.Format,
+        stripTagsRE    = /<\/?[^>]+>/gi,
+        stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
+        nl2brRe        = /\r?\n/g,
+
+        
+        formatCleanRe  = /[^\d\.]/g,
+
+        
+        
+        I18NFormatCleanRe;
+
+    Ext.apply(UtilFormat, {
+        
+        thousandSeparator: ',',
+
+        
+        decimalSeparator: '.',
+
+        
+        currencyPrecision: 2,
+
+        
+        currencySign: '$',
+
+        
+        currencyAtEnd: false,
+
+        
+        undef : function(value) {
+            return value !== undefined ? value : "";
+        },
+
+        
+        defaultValue : function(value, defaultValue) {
+            return value !== undefined && value !== '' ? value : defaultValue;
+        },
+
+        
+        substr : function(value, start, length) {
+            return String(value).substr(start, length);
+        },
+
+        
+        lowercase : function(value) {
+            return String(value).toLowerCase();
+        },
+
+        
+        uppercase : function(value) {
+            return String(value).toUpperCase();
+        },
+
+        
+        usMoney : function(v) {
+            return UtilFormat.currency(v, '$', 2);
+        },
+
+        
+        currency: function(v, currencySign, decimals, end) {
+            var negativeSign = '',
+                format = ",0",
+                i = 0;
+            v = v - 0;
+            if (v < 0) {
+                v = -v;
+                negativeSign = '-';
+            }
+            decimals = decimals || UtilFormat.currencyPrecision;
+            format += format + (decimals > 0 ? '.' : '');
+            for (; i < decimals; i++) {
+                format += '0';
+            }
+            v = UtilFormat.number(v, format);
+            if ((end || UtilFormat.currencyAtEnd) === true) {
+                return Ext.String.format("{0}{1}{2}", negativeSign, v, currencySign || UtilFormat.currencySign);
+            } else {
+                return Ext.String.format("{0}{1}{2}", negativeSign, currencySign || UtilFormat.currencySign, v);
+            }
+        },
+
+        
+        date: function(v, format) {
+            if (!v) {
+                return "";
+            }
+            if (!Ext.isDate(v)) {
+                v = new Date(Date.parse(v));
+            }
+            return Ext.Date.dateFormat(v, format || Ext.Date.defaultFormat);
+        },
+
+        
+        dateRenderer : function(format) {
+            return function(v) {
+                return UtilFormat.date(v, format);
+            };
+        },
+
+        
+        stripTags : function(v) {
+            return !v ? v : String(v).replace(stripTagsRE, "");
+        },
+
+        
+        stripScripts : function(v) {
+            return !v ? v : String(v).replace(stripScriptsRe, "");
+        },
+
+        
+        fileSize : function(size) {
+            if (size < 1024) {
+                return size + " bytes";
+            } else if (size < 1048576) {
+                return (Math.round(((size*10) / 1024))/10) + " KB";
+            } else {
+                return (Math.round(((size*10) / 1048576))/10) + " MB";
+            }
+        },
+
+        
+        math : function(){
+            var fns = {};
+
+            return function(v, a){
+                if (!fns[a]) {
+                    fns[a] = Ext.functionFactory('v', 'return v ' + a + ';');
+                }
+                return fns[a](v);
+            };
+        }(),
+
+        
+        round : function(value, precision) {
+            var result = Number(value);
+            if (typeof precision == 'number') {
+                precision = Math.pow(10, precision);
+                result = Math.round(value * precision) / precision;
+            }
+            return result;
+        },
+
+        
+        number: function(v, formatString) {
+            if (!formatString) {
+                return v;
+            }
+            v = Ext.Number.from(v, NaN);
+            if (isNaN(v)) {
+                return '';
+            }
+            var comma = UtilFormat.thousandSeparator,
+                dec   = UtilFormat.decimalSeparator,
+                i18n  = false,
+                neg   = v < 0,
+                hasComma,
+                psplit;
+
+            v = Math.abs(v);
+
+            
+            
+            
+            
+            if (formatString.substr(formatString.length - 2) == '/i') {
+                if (!I18NFormatCleanRe) {
+                    I18NFormatCleanRe = new RegExp('[^\\d\\' + UtilFormat.decimalSeparator + ']','g');
+                }
+                formatString = formatString.substr(0, formatString.length - 2);
+                i18n   = true;
+                hasComma = formatString.indexOf(comma) != -1;
+                psplit = formatString.replace(I18NFormatCleanRe, '').split(dec);
+            } else {
+                hasComma = formatString.indexOf(',') != -1;
+                psplit = formatString.replace(formatCleanRe, '').split('.');
+            }
+
+            if (1 < psplit.length) {
+                v = v.toFixed(psplit[1].length);
+            } else if(2 < psplit.length) {
+            } else {
+                v = v.toFixed(0);
+            }
+
+            var fnum = v.toString();
+
+            psplit = fnum.split('.');
+
+            if (hasComma) {
+                var cnum = psplit[0],
+                    parr = [],
+                    j    = cnum.length,
+                    m    = Math.floor(j / 3),
+                    n    = cnum.length % 3 || 3,
+                    i;
+
+                for (i = 0; i < j; i += n) {
+                    if (i !== 0) {
+                        n = 3;
+                    }
+
+                    parr[parr.length] = cnum.substr(i, n);
+                    m -= 1;
+                }
+                fnum = parr.join(comma);
+                if (psplit[1]) {
+                    fnum += dec + psplit[1];
+                }
+            } else {
+                if (psplit[1]) {
+                    fnum = psplit[0] + dec + psplit[1];
+                }
+            }
+
+            if (neg) {
+                
+                neg = fnum.replace(/[^1-9]/g, '') !== '';
+            }
+
+            return (neg ? '-' : '') + formatString.replace(/[\d,?\.?]+/, fnum);
+        },
+
+        
+        numberRenderer : function(format) {
+            return function(v) {
+                return UtilFormat.number(v, format);
+            };
+        },
+
+        
+        plural : function(v, s, p) {
+            return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
+        },
+
+        
+        nl2br : function(v) {
+            return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
+        },
+
+        
+        capitalize: Ext.String.capitalize,
+
+        
+        ellipsis: Ext.String.ellipsis,
+
+        
+        format: Ext.String.format,
+
+        
+        htmlDecode: Ext.String.htmlDecode,
+
+        
+        htmlEncode: Ext.String.htmlEncode,
+
+        
+        leftPad: Ext.String.leftPad,
+
+        
+        trim : Ext.String.trim,
+
+        
+        parseBox : function(box) {
+            if (Ext.isNumber(box)) {
+                box = box.toString();
+            }
+            var parts  = box.split(' '),
+                ln = parts.length;
+
+            if (ln == 1) {
+                parts[1] = parts[2] = parts[3] = parts[0];
+            }
+            else if (ln == 2) {
+                parts[2] = parts[0];
+                parts[3] = parts[1];
+            }
+            else if (ln == 3) {
+                parts[3] = parts[1];
+            }
+
+            return {
+                top   :parseInt(parts[0], 10) || 0,
+                right :parseInt(parts[1], 10) || 0,
+                bottom:parseInt(parts[2], 10) || 0,
+                left  :parseInt(parts[3], 10) || 0
+            };
+        },
+
+        
+        escapeRegex : function(s) {
+            return s.replace(/([\-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
+        }
+    });
+})();
+
+
+Ext.ns('Ext.util');
+
+Ext.util.TaskRunner = function(interval) {
+    interval = interval || 10;
+    var tasks = [],
+    removeQueue = [],
+    id = 0,
+    running = false,
+
+    
+    stopThread = function() {
+        running = false;
+        clearInterval(id);
+        id = 0;
+    },
+
+    
+    startThread = function() {
+        if (!running) {
+            running = true;
+            id = setInterval(runTasks, interval);
+        }
+    },
+
+    
+    removeTask = function(t) {
+        removeQueue.push(t);
+        if (t.onStop) {
+            t.onStop.apply(t.scope || t);
+        }
+    },
+
+    
+    runTasks = function() {
+        var rqLen = removeQueue.length,
+            now = new Date().getTime(),
+            i;
+
+        if (rqLen > 0) {
+            for (i = 0; i < rqLen; i++) {
+                Ext.Array.remove(tasks, removeQueue[i]);
+            }
+            removeQueue = [];
+            if (tasks.length < 1) {
+                stopThread();
+                return;
+            }
+        }
+        i = 0;
+        var t,
+            itime,
+            rt,
+            len = tasks.length;
+        for (; i < len; ++i) {
+            t = tasks[i];
+            itime = now - t.taskRunTime;
+            if (t.interval <= itime) {
+                rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
+                t.taskRunTime = now;
+                if (rt === false || t.taskRunCount === t.repeat) {
+                    removeTask(t);
+                    return;
+                }
+            }
+            if (t.duration && t.duration <= (now - t.taskStartTime)) {
+                removeTask(t);
+            }
+        }
+    };
+
+    
+    this.start = function(task) {
+        tasks.push(task);
+        task.taskStartTime = new Date().getTime();
+        task.taskRunTime = 0;
+        task.taskRunCount = 0;
+        startThread();
+        return task;
+    };
+
+    
+    this.stop = function(task) {
+        removeTask(task);
+        return task;
+    };
+
+    
+    this.stopAll = function() {
+        stopThread();
+        for (var i = 0, len = tasks.length; i < len; i++) {
+            if (tasks[i].onStop) {
+                tasks[i].onStop();
+            }
+        }
+        tasks = [];
+        removeQueue = [];
+    };
+};
+
+
+Ext.TaskManager = Ext.create('Ext.util.TaskRunner');
+
+Ext.is = {
+    init : function(navigator) {
+        var platforms = this.platforms,
+            ln = platforms.length,
+            i, platform;
+
+        navigator = navigator || window.navigator;
+
+        for (i = 0; i < ln; i++) {
+            platform = platforms[i];
+            this[platform.identity] = platform.regex.test(navigator[platform.property]);
+        }
+
+        
+        this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
+        
+        this.Tablet = this.iPad;
+        
+        this.Phone = !this.Desktop && !this.Tablet;
+        
+        this.iOS = this.iPhone || this.iPad || this.iPod;
+        
+        
+        this.Standalone = !!window.navigator.standalone;
+    },
+    
+    
+    platforms: [{
+        property: 'platform',
+        regex: /iPhone/i,
+        identity: 'iPhone'
+    },
+    
+    
+    {
+        property: 'platform',
+        regex: /iPod/i,
+        identity: 'iPod'
+    },
+    
+    
+    {
+        property: 'userAgent',
+        regex: /iPad/i,
+        identity: 'iPad'
+    },
+    
+    
+    {
+        property: 'userAgent',
+        regex: /Blackberry/i,
+        identity: 'Blackberry'
+    },
+    
+    
+    {
+        property: 'userAgent',
+        regex: /Android/i,
+        identity: 'Android'
+    },
+    
+    
+    {
+        property: 'platform',
+        regex: /Mac/i,
+        identity: 'Mac'
+    },
+    
+    
+    {
+        property: 'platform',
+        regex: /Win/i,
+        identity: 'Windows'
+    },
+    
+    
+    {
+        property: 'platform',
+        regex: /Linux/i,
+        identity: 'Linux'
+    }]
+};
+
+Ext.is.init();
+
+
+Ext.supports = {
+    init : function() {
+        var doc = document,
+            div = doc.createElement('div'),
+            tests = this.tests,
+            ln = tests.length,
+            i, test;
+
+        div.innerHTML = [
+            '<div style="height:30px;width:50px;">',
+                '<div style="height:20px;width:20px;"></div>',
+            '</div>',
+            '<div style="width: 200px; height: 200px; position: relative; padding: 5px;">',
+                '<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>',
+            '</div>',
+            '<div style="float:left; background-color:transparent;"></div>'
+        ].join('');
+
+        doc.body.appendChild(div);
+
+        for (i = 0; i < ln; i++) {
+            test = tests[i];
+            this[test.identity] = test.fn.call(this, doc, div);
+        }
+
+        doc.body.removeChild(div);
+    },
+
+    
+    CSS3BoxShadow: Ext.isDefined(document.documentElement.style.boxShadow),
+
+    
+    ClassList: !!document.documentElement.classList,
+
+    
+    OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
+    
+    
+    DeviceMotion: ('ondevicemotion' in window),
+    
+    
+    
+    
+    Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
+
+    tests: [
+        
+        {
+            identity: 'Transitions',
+            fn: function(doc, div) {
+                var prefix = [
+                        'webkit',
+                        'Moz',
+                        'o',
+                        'ms',
+                        'khtml'
+                    ],
+                    TE = 'TransitionEnd',
+                    transitionEndName = [
+                        prefix[0] + TE,
+                        'transitionend', 
+                        prefix[2] + TE,
+                        prefix[3] + TE,
+                        prefix[4] + TE
+                    ],
+                    ln = prefix.length,
+                    i = 0,
+                    out = false;
+                div = Ext.get(div);
+                for (; i < ln; i++) {
+                    if (div.getStyle(prefix[i] + "TransitionProperty")) {
+                        Ext.supports.CSS3Prefix = prefix[i];
+                        Ext.supports.CSS3TransitionEnd = transitionEndName[i];
+                        out = true;
+                        break;
+                    }
+                }
+                return out;
+            }
+        },
+        
+        
+        {
+            identity: 'RightMargin',
+            fn: function(doc, div) {
+                var view = doc.defaultView;
+                return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px');
+            }
+        },
+
+        
+        {
+            identity: 'DisplayChangeInputSelectionBug',
+            fn: function() {
+                var webKitVersion = Ext.webKitVersion;
+                
+                return 0 < webKitVersion && webKitVersion < 533;
+            }
+        },
+
+        
+        {
+            identity: 'DisplayChangeTextAreaSelectionBug',
+            fn: function() {
+                var webKitVersion = Ext.webKitVersion;
+
+                
+                return 0 < webKitVersion && webKitVersion < 534.24;
+            }
+        },
+
+        
+        {
+            identity: 'TransparentColor',
+            fn: function(doc, div, view) {
+                view = doc.defaultView;
+                return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent');
+            }
+        },
+
+        
+        {
+            identity: 'ComputedStyle',
+            fn: function(doc, div, view) {
+                view = doc.defaultView;
+                return view && view.getComputedStyle;
+            }
+        },
+        
+        
+        {
+            identity: 'Svg',
+            fn: function(doc) {
+                return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect;
+            }
+        },
+    
+        
+        {
+            identity: 'Canvas',
+            fn: function(doc) {
+                return !!doc.createElement('canvas').getContext;
+            }
+        },
+        
+        
+        {
+            identity: 'Vml',
+            fn: function(doc) {
+                var d = doc.createElement("div");
+                d.innerHTML = "<!--[if vml]><br><br><![endif]-->";
+                return (d.childNodes.length == 2);
+            }
+        },
+        
+        
+        {
+            identity: 'Float',
+            fn: function(doc, div) {
+                return !!div.lastChild.style.cssFloat;
+            }
+        },
+        
+        
+        {
+            identity: 'AudioTag',
+            fn: function(doc) {
+                return !!doc.createElement('audio').canPlayType;
+            }
+        },
+        
+        
+        {
+            identity: 'History',
+            fn: function() {
+                return !!(window.history && history.pushState);
+            }
+        },
+        
+        
+        {
+            identity: 'CSS3DTransform',
+            fn: function() {
+                return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));
+            }
+        },
+
+               
+        {
+            identity: 'CSS3LinearGradient',
+            fn: function(doc, div) {
+                var property = 'background-image:',
+                    webkit   = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',
+                    w3c      = 'linear-gradient(left top, black, white)',
+                    moz      = '-moz-' + w3c,
+                    options  = [property + webkit, property + w3c, property + moz];
+                
+                div.style.cssText = options.join(';');
+                
+                return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
+            }
+        },
+        
+        
+        {
+            identity: 'CSS3BorderRadius',
+            fn: function(doc, div) {
+                var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'],
+                    pass = false,
+                    i;
+                for (i = 0; i < domPrefixes.length; i++) {
+                    if (document.body.style[domPrefixes[i]] !== undefined) {
+                        return true;
+                    }
+                }
+                return pass;
+            }
+        },
+        
+        
+        {
+            identity: 'GeoLocation',
+            fn: function() {
+                return (typeof navigator != 'undefined' && typeof navigator.geolocation != 'undefined') || (typeof google != 'undefined' && typeof google.gears != 'undefined');
+            }
+        },
+        
+        {
+            identity: 'MouseEnterLeave',
+            fn: function(doc, div){
+                return ('onmouseenter' in div && 'onmouseleave' in div);
+            }
+        },
+        
+        {
+            identity: 'MouseWheel',
+            fn: function(doc, div) {
+                return ('onmousewheel' in div);
+            }
+        },
+        
+        {
+            identity: 'Opacity',
+            fn: function(doc, div){
+                
+                if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
+                    return false;
+                }
+                div.firstChild.style.cssText = 'opacity:0.73';
+                return div.firstChild.style.opacity == '0.73';
+            }
+        },
+        
+        {
+            identity: 'Placeholder',
+            fn: function(doc) {
+                return 'placeholder' in doc.createElement('input');
+            }
+        },
+        
+        
+        {
+            identity: 'Direct2DBug',
+            fn: function() {
+                return Ext.isString(document.body.style.msTransformOrigin);
+            }
+        },
+        
+        {
+            identity: 'BoundingClientRect',
+            fn: function(doc, div) {
+                return Ext.isFunction(div.getBoundingClientRect);
+            }
+        },
+        {
+            identity: 'IncludePaddingInWidthCalculation',
+            fn: function(doc, div){
+                var el = Ext.get(div.childNodes[1].firstChild);
+                return el.getWidth() == 210;
+            }
+        },
+        {
+            identity: 'IncludePaddingInHeightCalculation',
+            fn: function(doc, div){
+                var el = Ext.get(div.childNodes[1].firstChild);
+                return el.getHeight() == 210;
+            }
+        },
+        
+        
+        {
+            identity: 'ArraySort',
+            fn: function() {
+                var a = [1,2,3,4,5].sort(function(){ return 0; });
+                return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
+            }
+        },
+        
+        {
+            identity: 'Range',
+            fn: function() {
+                return !!document.createRange;
+            }
+        },
+        
+        {
+            identity: 'CreateContextualFragment',
+            fn: function() {
+                var range = Ext.supports.Range ? document.createRange() : false;
+                
+                return range && !!range.createContextualFragment;
+            }
+        },
+
+        
+        {
+            identity: 'WindowOnError',
+            fn: function () {
+                
+                return Ext.isIE || Ext.isGecko || Ext.webKitVersion >= 534.16; 
+            }
+        }
+    ]
+};
+
+
+
+
+
+Ext.ns('Ext.core');
+Ext.core.DomHelper = Ext.DomHelper = function(){
+    var tempTableEl = null,
+        emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
+        tableRe = /^table|tbody|tr|td$/i,
+        confRe = /tag|children|cn|html$/i,
+        tableElRe = /td|tr|tbody/i,
+        endRe = /end/i,
+        pub,
+        
+        afterbegin = 'afterbegin',
+        afterend = 'afterend',
+        beforebegin = 'beforebegin',
+        beforeend = 'beforeend',
+        ts = '<table>',
+        te = '</table>',
+        tbs = ts+'<tbody>',
+        tbe = '</tbody>'+te,
+        trs = tbs + '<tr>',
+        tre = '</tr>'+tbe;
+
+    
+    function doInsert(el, o, returnElement, pos, sibling, append){
+        el = Ext.getDom(el);
+        var newNode;
+        if (pub.useDom) {
+            newNode = createDom(o, null);
+            if (append) {
+                el.appendChild(newNode);
+            } else {
+                (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
+            }
+        } else {
+            newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
+        }
+        return returnElement ? Ext.get(newNode, true) : newNode;
+    }
+
+    function createDom(o, parentNode){
+        var el,
+            doc = document,
+            useSet,
+            attr,
+            val,
+            cn;
+
+        if (Ext.isArray(o)) {                       
+            el = doc.createDocumentFragment(); 
+            for (var i = 0, l = o.length; i < l; i++) {
+                createDom(o[i], el);
+            }
+        } else if (typeof o == 'string') {         
+            el = doc.createTextNode(o);
+        } else {
+            el = doc.createElement( o.tag || 'div' );
+            useSet = !!el.setAttribute; 
+            for (attr in o) {
+                if(!confRe.test(attr)){
+                    val = o[attr];
+                    if(attr == 'cls'){
+                        el.className = val;
+                    }else{
+                        if(useSet){
+                            el.setAttribute(attr, val);
+                        }else{
+                            el[attr] = val;
+                        }
+                    }
+                }
+            }
+            Ext.DomHelper.applyStyles(el, o.style);
+
+            if ((cn = o.children || o.cn)) {
+                createDom(cn, el);
+            } else if (o.html) {
+                el.innerHTML = o.html;
+            }
+        }
+        if(parentNode){
+           parentNode.appendChild(el);
+        }
+        return el;
+    }
+
+    
+    function createHtml(o){
+        var b = '',
+            attr,
+            val,
+            key,
+            cn,
+            i;
+
+        if(typeof o == "string"){
+            b = o;
+        } else if (Ext.isArray(o)) {
+            for (i=0; i < o.length; i++) {
+                if(o[i]) {
+                    b += createHtml(o[i]);
+                }
+            }
+        } else {
+            b += '<' + (o.tag = o.tag || 'div');
+            for (attr in o) {
+                val = o[attr];
+                if(!confRe.test(attr)){
+                    if (typeof val == "object") {
+                        b += ' ' + attr + '="';
+                        for (key in val) {
+                            b += key + ':' + val[key] + ';';
+                        }
+                        b += '"';
+                    }else{
+                        b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
+                    }
+                }
+            }
+            
+            if (emptyTags.test(o.tag)) {
+                b += '/>';
+            } else {
+                b += '>';
+                if ((cn = o.children || o.cn)) {
+                    b += createHtml(cn);
+                } else if(o.html){
+                    b += o.html;
+                }
+                b += '</' + o.tag + '>';
+            }
+        }
+        return b;
+    }
+
+    function ieTable(depth, s, h, e){
+        tempTableEl.innerHTML = [s, h, e].join('');
+        var i = -1,
+            el = tempTableEl,
+            ns;
+        while(++i < depth){
+            el = el.firstChild;
+        }
+
+        ns = el.nextSibling;
+        if (ns){
+            var df = document.createDocumentFragment();
+            while(el){
+                ns = el.nextSibling;
+                df.appendChild(el);
+                el = ns;
+            }
+            el = df;
+        }
+        return el;
+    }
+
+    
+    function insertIntoTable(tag, where, el, html) {
+        var node,
+            before;
+
+        tempTableEl = tempTableEl || document.createElement('div');
+
+        if(tag == 'td' && (where == afterbegin || where == beforeend) ||
+           !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
+            return null;
+        }
+        before = where == beforebegin ? el :
+                 where == afterend ? el.nextSibling :
+                 where == afterbegin ? el.firstChild : null;
+
+        if (where == beforebegin || where == afterend) {
+            el = el.parentNode;
+        }
+
+        if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
+            node = ieTable(4, trs, html, tre);
+        } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
+                   (tag == 'tr' && (where == beforebegin || where == afterend))) {
+            node = ieTable(3, tbs, html, tbe);
+        } else {
+            node = ieTable(2, ts, html, te);
+        }
+        el.insertBefore(node, before);
+        return node;
+    }
+
+    
+    function createContextualFragment(html){
+        var div = document.createElement("div"),
+            fragment = document.createDocumentFragment(),
+            i = 0,
+            length, childNodes;
+
+        div.innerHTML = html;
+        childNodes = div.childNodes;
+        length = childNodes.length;
+
+        for (; i < length; i++) {
+            fragment.appendChild(childNodes[i].cloneNode(true));
+        }
+
+        return fragment;
+    }
+
+    pub = {
+        
+        markup : function(o){
+            return createHtml(o);
+        },
+
+        
+        applyStyles : function(el, styles){
+            if (styles) {
+                el = Ext.fly(el);
+                if (typeof styles == "function") {
+                    styles = styles.call();
+                }
+                if (typeof styles == "string") {
+                    styles = Ext.Element.parseStyles(styles);
+                }
+                if (typeof styles == "object") {
+                    el.setStyle(styles);
+                }
+            }
+        },
+
+        
+        insertHtml : function(where, el, html){
+            var hash = {},
+                hashVal,
+                range,
+                rangeEl,
+                setStart,
+                frag,
+                rs;
+
+            where = where.toLowerCase();
+            
+            hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
+            hash[afterend] = ['AfterEnd', 'nextSibling'];
+
+            
+            if (el.insertAdjacentHTML) {
+                if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
+                    return rs;
+                }
+
+                
+                hash[afterbegin] = ['AfterBegin', 'firstChild'];
+                hash[beforeend] = ['BeforeEnd', 'lastChild'];
+                if ((hashVal = hash[where])) {
+                    el.insertAdjacentHTML(hashVal[0], html);
+                    return el[hashVal[1]];
+                }
+            
+            } else {
+                
+                if (Ext.isTextNode(el)) {
+                    where = where === 'afterbegin' ? 'beforebegin' : where;
+                    where = where === 'beforeend' ? 'afterend' : where;
+                }
+                range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
+                setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
+                if (hash[where]) {
+                    if (range) {
+                        range[setStart](el);
+                        frag = range.createContextualFragment(html);
+                    } else {
+                        frag = createContextualFragment(html);
+                    }
+                    el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
+                    return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
+                } else {
+                    rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
+                    if (el.firstChild) {
+                        if (range) {
+                            range[setStart](el[rangeEl]);
+                            frag = range.createContextualFragment(html);
+                        } else {
+                            frag = createContextualFragment(html);
+                        }
+
+                        if(where == afterbegin){
+                            el.insertBefore(frag, el.firstChild);
+                        }else{
+                            el.appendChild(frag);
+                        }
+                    } else {
+                        el.innerHTML = html;
+                    }
+                    return el[rangeEl];
+                }
+            }
+        },
+
+        
+        insertBefore : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, beforebegin);
+        },
+
+        
+        insertAfter : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, afterend, 'nextSibling');
+        },
+
+        
+        insertFirst : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
+        },
+
+        
+        append : function(el, o, returnElement){
+            return doInsert(el, o, returnElement, beforeend, '', true);
+        },
+
+        
+        overwrite : function(el, o, returnElement){
+            el = Ext.getDom(el);
+            el.innerHTML = createHtml(o);
+            return returnElement ? Ext.get(el.firstChild) : el.firstChild;
+        },
+
+        createHtml : createHtml,
+
+        
+        createDom: createDom,
+
+        
+        useDom : false,
+
+        
+        createTemplate : function(o){
+            var html = Ext.DomHelper.createHtml(o);
+            return Ext.create('Ext.Template', html);
+        }
+    };
+    return pub;
+}();
+
+
+
+Ext.ns('Ext.core');
+
+Ext.core.DomQuery = Ext.DomQuery = function(){
+    var cache = {},
+        simpleCache = {},
+        valueCache = {},
+        nonSpace = /\S/,
+        trimRe = /^\s+|\s+$/g,
+        tplRe = /\{(\d+)\}/g,
+        modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
+        tagTokenRe = /^(#)?([\w-\*]+)/,
+        nthRe = /(\d*)n\+?(\d*)/,
+        nthRe2 = /\D/,
+        startIdRe = /^\s*\#/,
+        
+    
+    
+    isIE = window.ActiveXObject ? true : false,
+    key = 30803;
+
+    
+    
+    eval("var batch = 30803;");
+
+    
+    
+    function child(parent, index){
+        var i = 0,
+            n = parent.firstChild;
+        while(n){
+            if(n.nodeType == 1){
+               if(++i == index){
+                   return n;
+               }
+            }
+            n = n.nextSibling;
+        }
+        return null;
+    }
+
+    
+    function next(n){
+        while((n = n.nextSibling) && n.nodeType != 1);
+        return n;
+    }
+
+    
+    function prev(n){
+        while((n = n.previousSibling) && n.nodeType != 1);
+        return n;
+    }
+
+    
+    
+    function children(parent){
+        var n = parent.firstChild,
+        nodeIndex = -1,
+        nextNode;
+        while(n){
+            nextNode = n.nextSibling;
+            
+            if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
+            parent.removeChild(n);
+            }else{
+            
+            n.nodeIndex = ++nodeIndex;
+            }
+            n = nextNode;
+        }
+        return this;
+    }
+
+
+    
+    
+    function byClassName(nodeSet, cls){
+        if(!cls){
+            return nodeSet;
+        }
+        var result = [], ri = -1;
+        for(var i = 0, ci; ci = nodeSet[i]; i++){
+            if((' '+ci.className+' ').indexOf(cls) != -1){
+                result[++ri] = ci;
+            }
+        }
+        return result;
+    };
+
+    function attrValue(n, attr){
+        
+        if(!n.tagName && typeof n.length != "undefined"){
+            n = n[0];
+        }
+        if(!n){
+            return null;
+        }
+
+        if(attr == "for"){
+            return n.htmlFor;
+        }
+        if(attr == "class" || attr == "className"){
+            return n.className;
+        }
+        return n.getAttribute(attr) || n[attr];
+
+    };
+
+
+    
+    
+    
+    function getNodes(ns, mode, tagName){
+        var result = [], ri = -1, cs;
+        if(!ns){
+            return result;
+        }
+        tagName = tagName || "*";
+        
+        if(typeof ns.getElementsByTagName != "undefined"){
+            ns = [ns];
+        }
+
+        
+        
+        if(!mode){
+            for(var i = 0, ni; ni = ns[i]; i++){
+                cs = ni.getElementsByTagName(tagName);
+                for(var j = 0, ci; ci = cs[j]; j++){
+                    result[++ri] = ci;
+                }
+            }
+        
+        
+        } else if(mode == "/" || mode == ">"){
+            var utag = tagName.toUpperCase();
+            for(var i = 0, ni, cn; ni = ns[i]; i++){
+                cn = ni.childNodes;
+                for(var j = 0, cj; cj = cn[j]; j++){
+                    if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
+                        result[++ri] = cj;
+                    }
+                }
+            }
+        
+        
+        }else if(mode == "+"){
+            var utag = tagName.toUpperCase();
+            for(var i = 0, n; n = ns[i]; i++){
+                while((n = n.nextSibling) && n.nodeType != 1);
+                if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
+                    result[++ri] = n;
+                }
+            }
+        
+        
+        }else if(mode == "~"){
+            var utag = tagName.toUpperCase();
+            for(var i = 0, n; n = ns[i]; i++){
+                while((n = n.nextSibling)){
+                    if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
+                        result[++ri] = n;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    function concat(a, b){
+        if(b.slice){
+            return a.concat(b);
+        }
+        for(var i = 0, l = b.length; i < l; i++){
+            a[a.length] = b[i];
+        }
+        return a;
+    }
+
+    function byTag(cs, tagName){
+        if(cs.tagName || cs == document){
+            cs = [cs];
+        }
+        if(!tagName){
+            return cs;
+        }
+        var result = [], ri = -1;
+        tagName = tagName.toLowerCase();
+        for(var i = 0, ci; ci = cs[i]; i++){
+            if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
+                result[++ri] = ci;
+            }
+        }
+        return result;
+    }
+
+    function byId(cs, id){
+        if(cs.tagName || cs == document){
+            cs = [cs];
+        }
+        if(!id){
+            return cs;
+        }
+        var result = [], ri = -1;
+        for(var i = 0, ci; ci = cs[i]; i++){
+            if(ci && ci.id == id){
+                result[++ri] = ci;
+                return result;
+            }
+        }
+        return result;
+    }
+
+    
+    
+    function byAttribute(cs, attr, value, op, custom){
+        var result = [],
+            ri = -1,
+            useGetStyle = custom == "{",
+            fn = Ext.DomQuery.operators[op],
+            a,
+            xml,
+            hasXml;
+
+        for(var i = 0, ci; ci = cs[i]; i++){
+            
+            if(ci.nodeType != 1){
+                continue;
+            }
+            
+            if(!hasXml){
+                xml = Ext.DomQuery.isXml(ci);
+                hasXml = true;
+            }
+
+            
+            if(!xml){
+                if(useGetStyle){
+                    a = Ext.DomQuery.getStyle(ci, attr);
+                } else if (attr == "class" || attr == "className"){
+                    a = ci.className;
+                } else if (attr == "for"){
+                    a = ci.htmlFor;
+                } else if (attr == "href"){
+                    
+                    
+                    a = ci.getAttribute("href", 2);
+                } else{
+                    a = ci.getAttribute(attr);
+                }
+            }else{
+                a = ci.getAttribute(attr);
+            }
+            if((fn && fn(a, value)) || (!fn && a)){
+                result[++ri] = ci;
+            }
+        }
+        return result;
+    }
+
+    function byPseudo(cs, name, value){
+        return Ext.DomQuery.pseudos[name](cs, value);
+    }
+
+    function nodupIEXml(cs){
+        var d = ++key,
+            r;
+        cs[0].setAttribute("_nodup", d);
+        r = [cs[0]];
+        for(var i = 1, len = cs.length; i < len; i++){
+            var c = cs[i];
+            if(!c.getAttribute("_nodup") != d){
+                c.setAttribute("_nodup", d);
+                r[r.length] = c;
+            }
+        }
+        for(var i = 0, len = cs.length; i < len; i++){
+            cs[i].removeAttribute("_nodup");
+        }
+        return r;
+    }
+
+    function nodup(cs){
+        if(!cs){
+            return [];
+        }
+        var len = cs.length, c, i, r = cs, cj, ri = -1;
+        if(!len || typeof cs.nodeType != "undefined" || len == 1){
+            return cs;
+        }
+        if(isIE && typeof cs[0].selectSingleNode != "undefined"){
+            return nodupIEXml(cs);
+        }
+        var d = ++key;
+        cs[0]._nodup = d;
+        for(i = 1; c = cs[i]; i++){
+            if(c._nodup != d){
+                c._nodup = d;
+            }else{
+                r = [];
+                for(var j = 0; j < i; j++){
+                    r[++ri] = cs[j];
+                }
+                for(j = i+1; cj = cs[j]; j++){
+                    if(cj._nodup != d){
+                        cj._nodup = d;
+                        r[++ri] = cj;
+                    }
+                }
+                return r;
+            }
+        }
+        return r;
+    }
+
+    function quickDiffIEXml(c1, c2){
+        var d = ++key,
+            r = [];
+        for(var i = 0, len = c1.length; i < len; i++){
+            c1[i].setAttribute("_qdiff", d);
+        }
+        for(var i = 0, len = c2.length; i < len; i++){
+            if(c2[i].getAttribute("_qdiff") != d){
+                r[r.length] = c2[i];
+            }
+        }
+        for(var i = 0, len = c1.length; i < len; i++){
+           c1[i].removeAttribute("_qdiff");
+        }
+        return r;
+    }
+
+    function quickDiff(c1, c2){
+        var len1 = c1.length,
+            d = ++key,
+            r = [];
+        if(!len1){
+            return c2;
+        }
+        if(isIE && typeof c1[0].selectSingleNode != "undefined"){
+            return quickDiffIEXml(c1, c2);
+        }
+        for(var i = 0; i < len1; i++){
+            c1[i]._qdiff = d;
+        }
+        for(var i = 0, len = c2.length; i < len; i++){
+            if(c2[i]._qdiff != d){
+                r[r.length] = c2[i];
+            }
+        }
+        return r;
+    }
+
+    function quickId(ns, mode, root, id){
+        if(ns == root){
+           var d = root.ownerDocument || root;
+           return d.getElementById(id);
+        }
+        ns = getNodes(ns, mode, "*");
+        return byId(ns, id);
+    }
+
+    return {
+        getStyle : function(el, name){
+            return Ext.fly(el).getStyle(name);
+        },
+        
+        compile : function(path, type){
+            type = type || "select";
+
+            
+            var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
+                mode,
+                lastPath,
+                matchers = Ext.DomQuery.matchers,
+                matchersLn = matchers.length,
+                modeMatch,
+                
+                lmode = path.match(modeRe);
+
+            if(lmode && lmode[1]){
+                fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
+                path = path.replace(lmode[1], "");
+            }
+
+            
+            while(path.substr(0, 1)=="/"){
+                path = path.substr(1);
+            }
+
+            while(path && lastPath != path){
+                lastPath = path;
+                var tokenMatch = path.match(tagTokenRe);
+                if(type == "select"){
+                    if(tokenMatch){
+                        
+                        if(tokenMatch[1] == "#"){
+                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';
+                        }else{
+                            fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
+                        }
+                        path = path.replace(tokenMatch[0], "");
+                    }else if(path.substr(0, 1) != '@'){
+                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
+                    }
+                
+                }else{
+                    if(tokenMatch){
+                        if(tokenMatch[1] == "#"){
+                            fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
+                        }else{
+                            fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
+                        }
+                        path = path.replace(tokenMatch[0], "");
+                    }
+                }
+                while(!(modeMatch = path.match(modeRe))){
+                    var matched = false;
+                    for(var j = 0; j < matchersLn; j++){
+                        var t = matchers[j];
+                        var m = path.match(t.re);
+                        if(m){
+                            fn[fn.length] = t.select.replace(tplRe, function(x, i){
+                                return m[i];
+                            });
+                            path = path.replace(m[0], "");
+                            matched = true;
+                            break;
+                        }
+                    }
+                    
+                    if(!matched){
+                    }
+                }
+                if(modeMatch[1]){
+                    fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
+                    path = path.replace(modeMatch[1], "");
+                }
+            }
+            
+            fn[fn.length] = "return nodup(n);\n}";
+
+            
+            eval(fn.join(""));
+            return f;
+        },
+
+        
+        jsSelect: function(path, root, type){
+            
+            root = root || document;
+
+            if(typeof root == "string"){
+                root = document.getElementById(root);
+            }
+            var paths = path.split(","),
+                results = [];
+
+            
+            for(var i = 0, len = paths.length; i < len; i++){
+                var subPath = paths[i].replace(trimRe, "");
+                
+                if(!cache[subPath]){
+                    cache[subPath] = Ext.DomQuery.compile(subPath);
+                    if(!cache[subPath]){
+                    }
+                }
+                var result = cache[subPath](root);
+                if(result && result != document){
+                    results = results.concat(result);
+                }
+            }
+
+            
+            
+            if(paths.length > 1){
+                return nodup(results);
+            }
+            return results;
+        },
+
+        isXml: function(el) {
+            var docEl = (el ? el.ownerDocument || el : 0).documentElement;
+            return docEl ? docEl.nodeName !== "HTML" : false;
+        },
+
+        
+        select : document.querySelectorAll ? function(path, root, type) {
+            root = root || document;
+            
+            if (!Ext.DomQuery.isXml(root) && !(Ext.isSafari3 && !Ext.isStrict)) { 
+                try {
+                    
+                    var isDocumentRoot = root.nodeType === 9,
+                        _path = path,
+                        _root = root;
+
+                    if (!isDocumentRoot && path.indexOf(',') === -1 && !startIdRe.test(path)) {
+                        _path = '#' + Ext.id(root) + ' ' + path;
+                        _root = root.parentNode;
+                    }
+                    return Ext.Array.toArray(_root.querySelectorAll(_path));
+                }
+                catch (e) {
+                }
+            }
+            return Ext.DomQuery.jsSelect.call(this, path, root, type);
+        } : function(path, root, type) {
+            return Ext.DomQuery.jsSelect.call(this, path, root, type);
+        },
+
+        
+        selectNode : function(path, root){
+            return Ext.DomQuery.select(path, root)[0];
+        },
+
+        
+        selectValue : function(path, root, defaultValue){
+            path = path.replace(trimRe, "");
+            if(!valueCache[path]){
+                valueCache[path] = Ext.DomQuery.compile(path, "select");
+            }
+            var n = valueCache[path](root), v;
+            n = n[0] ? n[0] : n;
+
+            
+            
+            
+            
+            if (typeof n.normalize == 'function') n.normalize();
+
+            v = (n && n.firstChild ? n.firstChild.nodeValue : null);
+            return ((v === null||v === undefined||v==='') ? defaultValue : v);
+        },
+
+        
+        selectNumber : function(path, root, defaultValue){
+            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
+            return parseFloat(v);
+        },
+
+        
+        is : function(el, ss){
+            if(typeof el == "string"){
+                el = document.getElementById(el);
+            }
+            var isArray = Ext.isArray(el),
+                result = Ext.DomQuery.filter(isArray ? el : [el], ss);
+            return isArray ? (result.length == el.length) : (result.length > 0);
+        },
+
+        
+        filter : function(els, ss, nonMatches){
+            ss = ss.replace(trimRe, "");
+            if(!simpleCache[ss]){
+                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
+            }
+            var result = simpleCache[ss](els);
+            return nonMatches ? quickDiff(result, els) : result;
+        },
+
+        
+        matchers : [{
+                re: /^\.([\w-]+)/,
+                select: 'n = byClassName(n, " {1} ");'
+            }, {
+                re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
+                select: 'n = byPseudo(n, "{1}", "{2}");'
+            },{
+                re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
+                select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
+            }, {
+                re: /^#([\w-]+)/,
+                select: 'n = byId(n, "{1}");'
+            },{
+                re: /^@([\w-]+)/,
+                select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
+            }
+        ],
+
+        
+        operators : {
+            "=" : function(a, v){
+                return a == v;
+            },
+            "!=" : function(a, v){
+                return a != v;
+            },
+            "^=" : function(a, v){
+                return a && a.substr(0, v.length) == v;
+            },
+            "$=" : function(a, v){
+                return a && a.substr(a.length-v.length) == v;
+            },
+            "*=" : function(a, v){
+                return a && a.indexOf(v) !== -1;
+            },
+            "%=" : function(a, v){
+                return (a % v) == 0;
+            },
+            "|=" : function(a, v){
+                return a && (a == v || a.substr(0, v.length+1) == v+'-');
+            },
+            "~=" : function(a, v){
+                return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
+            }
+        },
+
+        
+        pseudos : {
+            "first-child" : function(c){
+                var r = [], ri = -1, n;
+                for(var i = 0, ci; ci = n = c[i]; i++){
+                    while((n = n.previousSibling) && n.nodeType != 1);
+                    if(!n){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "last-child" : function(c){
+                var r = [], ri = -1, n;
+                for(var i = 0, ci; ci = n = c[i]; i++){
+                    while((n = n.nextSibling) && n.nodeType != 1);
+                    if(!n){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "nth-child" : function(c, a) {
+                var r = [], ri = -1,
+                    m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
+                    f = (m[1] || 1) - 0, l = m[2] - 0;
+                for(var i = 0, n; n = c[i]; i++){
+                    var pn = n.parentNode;
+                    if (batch != pn._batch) {
+                        var j = 0;
+                        for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
+                            if(cn.nodeType == 1){
+                               cn.nodeIndex = ++j;
+                            }
+                        }
+                        pn._batch = batch;
+                    }
+                    if (f == 1) {
+                        if (l == 0 || n.nodeIndex == l){
+                            r[++ri] = n;
+                        }
+                    } else if ((n.nodeIndex + l) % f == 0){
+                        r[++ri] = n;
+                    }
+                }
+
+                return r;
+            },
+
+            "only-child" : function(c){
+                var r = [], ri = -1;;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(!prev(ci) && !next(ci)){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "empty" : function(c){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    var cns = ci.childNodes, j = 0, cn, empty = true;
+                    while(cn = cns[j]){
+                        ++j;
+                        if(cn.nodeType == 1 || cn.nodeType == 3){
+                            empty = false;
+                            break;
+                        }
+                    }
+                    if(empty){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "contains" : function(c, v){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "nodeValue" : function(c, v){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(ci.firstChild && ci.firstChild.nodeValue == v){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "checked" : function(c){
+                var r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(ci.checked == true){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "not" : function(c, ss){
+                return Ext.DomQuery.filter(c, ss, true);
+            },
+
+            "any" : function(c, selectors){
+                var ss = selectors.split('|'),
+                    r = [], ri = -1, s;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    for(var j = 0; s = ss[j]; j++){
+                        if(Ext.DomQuery.is(ci, s)){
+                            r[++ri] = ci;
+                            break;
+                        }
+                    }
+                }
+                return r;
+            },
+
+            "odd" : function(c){
+                return this["nth-child"](c, "odd");
+            },
+
+            "even" : function(c){
+                return this["nth-child"](c, "even");
+            },
+
+            "nth" : function(c, a){
+                return c[a-1] || [];
+            },
+
+            "first" : function(c){
+                return c[0] || [];
+            },
+
+            "last" : function(c){
+                return c[c.length-1] || [];
+            },
+
+            "has" : function(c, ss){
+                var s = Ext.DomQuery.select,
+                    r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    if(s(ss, ci).length > 0){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "next" : function(c, ss){
+                var is = Ext.DomQuery.is,
+                    r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    var n = next(ci);
+                    if(n && is(n, ss)){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            },
+
+            "prev" : function(c, ss){
+                var is = Ext.DomQuery.is,
+                    r = [], ri = -1;
+                for(var i = 0, ci; ci = c[i]; i++){
+                    var n = prev(ci);
+                    if(n && is(n, ss)){
+                        r[++ri] = ci;
+                    }
+                }
+                return r;
+            }
+        }
+    };
+}();
+
+
+Ext.query = Ext.DomQuery.select;
+
+
+ (function() {
+    var DOC = document,
+        EC = Ext.cache;
+
+    Ext.Element = Ext.core.Element = function(element, forceNew) {
+        var dom = typeof element == "string" ? DOC.getElementById(element) : element,
+        id;
+
+        if (!dom) {
+            return null;
+        }
+
+        id = dom.id;
+
+        if (!forceNew && id && EC[id]) {
+            
+            return EC[id].el;
+        }
+
+        
+        this.dom = dom;
+
+        
+        this.id = id || Ext.id(dom);
+    };
+
+    var DH = Ext.DomHelper,
+    El = Ext.Element;
+
+
+    El.prototype = {
+        
+        set: function(o, useSet) {
+            var el = this.dom,
+                attr,
+                val;
+            useSet = (useSet !== false) && !!el.setAttribute;
+
+            for (attr in o) {
+                if (o.hasOwnProperty(attr)) {
+                    val = o[attr];
+                    if (attr == 'style') {
+                        DH.applyStyles(el, val);
+                    } else if (attr == 'cls') {
+                        el.className = val;
+                    } else if (useSet) {
+                        el.setAttribute(attr, val);
+                    } else {
+                        el[attr] = val;
+                    }
+                }
+            }
+            return this;
+        },
+
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+
+        
+        
+        
+        
+
+
+        
+        
+        
+        
+        
+        
+        
+
+        
+        
+        
+        
+        
+        
+        
+
+        
+        
+        
+        
+
+        
+        
+        
+        
+        
+        
+        
+        
+
+        
+        defaultUnit: "px",
+
+        
+        is: function(simpleSelector) {
+            return Ext.DomQuery.is(this.dom, simpleSelector);
+        },
+
+        
+        focus: function(defer,
+                        
+                        dom) {
+            var me = this;
+            dom = dom || me.dom;
+            try {
+                if (Number(defer)) {
+                    Ext.defer(me.focus, defer, null, [null, dom]);
+                } else {
+                    dom.focus();
+                }
+            } catch(e) {}
+            return me;
+        },
+
+        
+        blur: function() {
+            try {
+                this.dom.blur();
+            } catch(e) {}
+            return this;
+        },
+
+        
+        getValue: function(asNumber) {
+            var val = this.dom.value;
+            return asNumber ? parseInt(val, 10) : val;
+        },
+
+        
+        addListener: function(eventName, fn, scope, options) {
+            Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
+            return this;
+        },
+
+        
+        removeListener: function(eventName, fn, scope) {
+            Ext.EventManager.un(this.dom, eventName, fn, scope || this);
+            return this;
+        },
+
+        
+        removeAllListeners: function() {
+            Ext.EventManager.removeAll(this.dom);
+            return this;
+        },
+
+        
+        purgeAllListeners: function() {
+            Ext.EventManager.purgeElement(this);
+            return this;
+        },
+
+        
+        addUnits: function(size, units) {
+
+            
+            if (Ext.isNumber(size)) {
+                return size + (units || this.defaultUnit || 'px');
+            }
+
+            
+            if (size === "" || size == "auto" || size == null) {
+                return size || '';
+            }
+
+            
+            if (!unitPattern.test(size)) {
+                return size || '';
+            }
+            return size;
+        },
+
+        
+        isBorderBox: function() {
+            return Ext.isBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
+        },
+
+        
+        remove: function() {
+            var me = this,
+            dom = me.dom;
+
+            if (dom) {
+                delete me.dom;
+                Ext.removeNode(dom);
+            }
+        },
+
+        
+        hover: function(overFn, outFn, scope, options) {
+            var me = this;
+            me.on('mouseenter', overFn, scope || me.dom, options);
+            me.on('mouseleave', outFn, scope || me.dom, options);
+            return me;
+        },
+
+        
+        contains: function(el) {
+            return ! el ? false: Ext.Element.isAncestor(this.dom, el.dom ? el.dom: el);
+        },
+
+        
+        getAttributeNS: function(ns, name) {
+            return this.getAttribute(name, ns);
+        },
+
+        
+        getAttribute: (Ext.isIE && !(Ext.isIE9 && document.documentMode === 9)) ?
+        function(name, ns) {
+            var d = this.dom,
+            type;
+            if(ns) {
+                type = typeof d[ns + ":" + name];
+                if (type != 'undefined' && type != 'unknown') {
+                    return d[ns + ":" + name] || null;
+                }
+                return null;
+            }
+            if (name === "for") {
+                name = "htmlFor";
+            }
+            return d[name] || null;
+        }: function(name, ns) {
+            var d = this.dom;
+            if (ns) {
+               return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name);
+            }
+            return  d.getAttribute(name) || d[name] || null;
+        },
+
+        
+        update: function(html) {
+            if (this.dom) {
+                this.dom.innerHTML = html;
+            }
+            return this;
+        }
+    };
+
+    var ep = El.prototype;
+
+    El.addMethods = function(o) {
+        Ext.apply(ep, o);
+    };
+
+    
+    ep.on = ep.addListener;
+
+    
+    ep.un = ep.removeListener;
+
+    
+    ep.clearListeners = ep.removeAllListeners;
+
+    
+    ep.destroy = ep.remove;
+
+    
+    ep.autoBoxAdjust = true;
+
+    
+    var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
+    docEl;
+
+    
+    El.get = function(el) {
+        var ex,
+        elm,
+        id;
+        if (!el) {
+            return null;
+        }
+        if (typeof el == "string") {
+            
+            if (! (elm = DOC.getElementById(el))) {
+                return null;
+            }
+            if (EC[el] && EC[el].el) {
+                ex = EC[el].el;
+                ex.dom = elm;
+            } else {
+                ex = El.addToCache(new El(elm));
+            }
+            return ex;
+        } else if (el.tagName) {
+            
+            if (! (id = el.id)) {
+                id = Ext.id(el);
+            }
+            if (EC[id] && EC[id].el) {
+                ex = EC[id].el;
+                ex.dom = el;
+            } else {
+                ex = El.addToCache(new El(el));
+            }
+            return ex;
+        } else if (el instanceof El) {
+            if (el != docEl) {
+                
+                
+                
+                if (Ext.isIE && (el.id == undefined || el.id == '')) {
+                    el.dom = el.dom;
+                } else {
+                    el.dom = DOC.getElementById(el.id) || el.dom;
+                }
+            }
+            return el;
+        } else if (el.isComposite) {
+            return el;
+        } else if (Ext.isArray(el)) {
+            return El.select(el);
+        } else if (el == DOC) {
+            
+            if (!docEl) {
+                var f = function() {};
+                f.prototype = El.prototype;
+                docEl = new f();
+                docEl.dom = DOC;
+            }
+            return docEl;
+        }
+        return null;
+    };
+
+    
+    ep.getById = (!Ext.isIE6 && !Ext.isIE7 && !Ext.isIE8) ? El.get :
+        function (id) {
+            var dom = this.dom,
+                cached, el, ret;
+
+            if (dom) {
+                el = dom.all[id];
+                if (el) {
+                    
+                    
+                    cached = EC[id];
+                    if (cached && cached.el) {
+                        ret = cached.el;
+                        ret.dom = el;
+                    } else {
+                        ret = El.addToCache(new El(el));
+                    }
+                    return ret;
+                }
+            }
+
+            return El.get(id);
+        };
+
+    El.addToCache = function(el, id) {
+        if (el) {
+            id = id || el.id;
+            EC[id] = {
+                el: el,
+                data: {},
+                events: {}
+            };
+        }
+        return el;
+    };
+
+    
+    El.data = function(el, key, value) {
+        el = El.get(el);
+        if (!el) {
+            return null;
+        }
+        var c = EC[el.id].data;
+        if (arguments.length == 2) {
+            return c[key];
+        } else {
+            return (c[key] = value);
+        }
+    };
+
+    
+    
+    
+    function garbageCollect() {
+        if (!Ext.enableGarbageCollector) {
+            clearInterval(El.collectorThreadId);
+        } else {
+            var eid,
+            el,
+            d,
+            o;
+
+            for (eid in EC) {
+                if (!EC.hasOwnProperty(eid)) {
+                    continue;
+                }
+                o = EC[eid];
+                if (o.skipGarbageCollection) {
+                    continue;
+                }
+                el = o.el;
+                d = el.dom;
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                if (!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))) {
+                    if (d && Ext.enableListenerCollection) {
+                        Ext.EventManager.removeAll(d);
+                    }
+                    delete EC[eid];
+                }
+            }
+            
+            if (Ext.isIE) {
+                var t = {};
+                for (eid in EC) {
+                    if (!EC.hasOwnProperty(eid)) {
+                        continue;
+                    }
+                    t[eid] = EC[eid];
+                }
+                EC = Ext.cache = t;
+            }
+        }
+    }
+    El.collectorThreadId = setInterval(garbageCollect, 30000);
+
+    var flyFn = function() {};
+    flyFn.prototype = El.prototype;
+
+    
+    El.Flyweight = function(dom) {
+        this.dom = dom;
+    };
+
+    El.Flyweight.prototype = new flyFn();
+    El.Flyweight.prototype.isFlyweight = true;
+    El._flyweights = {};
+
+    
+    El.fly = function(el, named) {
+        var ret = null;
+        named = named || '_global';
+        el = Ext.getDom(el);
+        if (el) {
+            (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
+            ret = El._flyweights[named];
+        }
+        return ret;
+    };
+
+    
+    Ext.get = El.get;
+
+    
+    Ext.fly = El.fly;
+
+    
+    var noBoxAdjust = Ext.isStrict ? {
+        select: 1
+    }: {
+        input: 1,
+        select: 1,
+        textarea: 1
+    };
+    if (Ext.isIE || Ext.isGecko) {
+        noBoxAdjust['button'] = 1;
+    }
+})();
+
+
+Ext.Element.addMethods({
+    
+    findParent : function(simpleSelector, maxDepth, returnEl) {
+        var p = this.dom,
+            b = document.body,
+            depth = 0,
+            stopEl;
+
+        maxDepth = maxDepth || 50;
+        if (isNaN(maxDepth)) {
+            stopEl = Ext.getDom(maxDepth);
+            maxDepth = Number.MAX_VALUE;
+        }
+        while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
+            if (Ext.DomQuery.is(p, simpleSelector)) {
+                return returnEl ? Ext.get(p) : p;
+            }
+            depth++;
+            p = p.parentNode;
+        }
+        return null;
+    },
+
+    
+    findParentNode : function(simpleSelector, maxDepth, returnEl) {
+        var p = Ext.fly(this.dom.parentNode, '_internal');
+        return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
+    },
+
+    
+    up : function(simpleSelector, maxDepth) {
+        return this.findParentNode(simpleSelector, maxDepth, true);
+    },
+
+    
+    select : function(selector) {
+        return Ext.Element.select(selector, false,  this.dom);
+    },
+
+    
+    query : function(selector) {
+        return Ext.DomQuery.select(selector, this.dom);
+    },
+
+    
+    down : function(selector, returnDom) {
+        var n = Ext.DomQuery.selectNode(selector, this.dom);
+        return returnDom ? n : Ext.get(n);
+    },
+
+    
+    child : function(selector, returnDom) {
+        var node,
+            me = this,
+            id;
+        id = Ext.get(me).id;
+        
+        id = id.replace(/[\.:]/g, "\\$0");
+        node = Ext.DomQuery.selectNode('#' + id + " > " + selector, me.dom);
+        return returnDom ? node : Ext.get(node);
+    },
+
+     
+    parent : function(selector, returnDom) {
+        return this.matchNode('parentNode', 'parentNode', selector, returnDom);
+    },
+
+     
+    next : function(selector, returnDom) {
+        return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
+    },
+
+    
+    prev : function(selector, returnDom) {
+        return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
+    },
+
+
+    
+    first : function(selector, returnDom) {
+        return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
+    },
+
+    
+    last : function(selector, returnDom) {
+        return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
+    },
+
+    matchNode : function(dir, start, selector, returnDom) {
+        if (!this.dom) {
+            return null;
+        }
+
+        var n = this.dom[start];
+        while (n) {
+            if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) {
+                return !returnDom ? Ext.get(n) : n;
+            }
+            n = n[dir];
+        }
+        return null;
+    }
+});
+
+
+Ext.Element.addMethods({
+    
+    appendChild : function(el) {
+        return Ext.get(el).appendTo(this);
+    },
+
+    
+    appendTo : function(el) {
+        Ext.getDom(el).appendChild(this.dom);
+        return this;
+    },
+
+    
+    insertBefore : function(el) {
+        el = Ext.getDom(el);
+        el.parentNode.insertBefore(this.dom, el);
+        return this;
+    },
+
+    
+    insertAfter : function(el) {
+        el = Ext.getDom(el);
+        el.parentNode.insertBefore(this.dom, el.nextSibling);
+        return this;
+    },
+
+    
+    insertFirst : function(el, returnDom) {
+        el = el || {};
+        if (el.nodeType || el.dom || typeof el == 'string') { 
+            el = Ext.getDom(el);
+            this.dom.insertBefore(el, this.dom.firstChild);
+            return !returnDom ? Ext.get(el) : el;
+        }
+        else { 
+            return this.createChild(el, this.dom.firstChild, returnDom);
+        }
+    },
+
+    
+    insertSibling: function(el, where, returnDom){
+        var me = this, rt,
+        isAfter = (where || 'before').toLowerCase() == 'after',
+        insertEl;
+
+        if(Ext.isArray(el)){
+            insertEl = me;
+            Ext.each(el, function(e) {
+                rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
+                if(isAfter){
+                    insertEl = rt;
+                }
+            });
+            return rt;
+        }
+
+        el = el || {};
+
+        if(el.nodeType || el.dom){
+            rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom);
+            if (!returnDom) {
+                rt = Ext.get(rt);
+            }
+        }else{
+            if (isAfter && !me.dom.nextSibling) {
+                rt = Ext.DomHelper.append(me.dom.parentNode, el, !returnDom);
+            } else {
+                rt = Ext.DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
+            }
+        }
+        return rt;
+    },
+
+    
+    replace : function(el) {
+        el = Ext.get(el);
+        this.insertBefore(el);
+        el.remove();
+        return this;
+    },
+    
+    
+    replaceWith: function(el){
+        var me = this;
+            
+        if(el.nodeType || el.dom || typeof el == 'string'){
+            el = Ext.get(el);
+            me.dom.parentNode.insertBefore(el, me.dom);
+        }else{
+            el = Ext.DomHelper.insertBefore(me.dom, el);
+        }
+        
+        delete Ext.cache[me.id];
+        Ext.removeNode(me.dom);      
+        me.id = Ext.id(me.dom = el);
+        Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
+        return me;
+    },
+    
+    
+    createChild : function(config, insertBefore, returnDom) {
+        config = config || {tag:'div'};
+        if (insertBefore) {
+            return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
+        }
+        else {
+            return Ext.DomHelper[!this.dom.firstChild ? 'insertFirst' : 'append'](this.dom, config,  returnDom !== true);
+        }
+    },
+
+    
+    wrap : function(config, returnDom) {
+        var newEl = Ext.DomHelper.insertBefore(this.dom, config || {tag: "div"}, !returnDom),
+            d = newEl.dom || newEl;
+
+        d.appendChild(this.dom);
+        return newEl;
+    },
+
+    
+    insertHtml : function(where, html, returnEl) {
+        var el = Ext.DomHelper.insertHtml(where, this.dom, html);
+        return returnEl ? Ext.get(el) : el;
+    }
+});
+
+
+(function(){
+    
+    var ELEMENT = Ext.Element,
+        supports = Ext.supports,
+        view = document.defaultView,
+        opacityRe = /alpha\(opacity=(.*)\)/i,
+        trimRe = /^\s+|\s+$/g,
+        spacesRe = /\s+/,
+        wordsRe = /\w/g,
+        adjustDirect2DTableRe = /table-row|table-.*-group/,
+        INTERNAL = '_internal',
+        PADDING = 'padding',
+        MARGIN = 'margin',
+        BORDER = 'border',
+        LEFT = '-left',
+        RIGHT = '-right',
+        TOP = '-top',
+        BOTTOM = '-bottom',
+        WIDTH = '-width',
+        MATH = Math,
+        HIDDEN = 'hidden',
+        ISCLIPPED = 'isClipped',
+        OVERFLOW = 'overflow',
+        OVERFLOWX = 'overflow-x',
+        OVERFLOWY = 'overflow-y',
+        ORIGINALCLIP = 'originalClip',
+        
+        borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
+        paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
+        margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
+        data = ELEMENT.data;
+
+    ELEMENT.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
+
+    
+    
+    ELEMENT.inheritedProps = {
+        fontSize: 1,
+        fontStyle: 1,
+        opacity: 1
+    };
+
+    Ext.override(ELEMENT, {
+
+        
+        
+        adjustWidth : function(width) {
+            var me = this,
+                isNum = (typeof width == 'number');
+
+            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+               width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+            }
+            return (isNum && width < 0) ? 0 : width;
+        },
+
+        
+        adjustHeight : function(height) {
+            var me = this,
+                isNum = (typeof height == "number");
+
+            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+               height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+            }
+            return (isNum && height < 0) ? 0 : height;
+        },
+
+
+        
+        addCls : function(className){
+            var me = this,
+                cls = [],
+                space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "),
+                i, len, v;
+            if (className === undefined) {
+                return me;
+            }
+            
+            if (Object.prototype.toString.call(className) !== '[object Array]') {
+                if (typeof className === 'string') {
+                    className = className.replace(trimRe, '').split(spacesRe);
+                    if (className.length === 1) {
+                        className = className[0];
+                        if (!me.hasCls(className)) {
+                            me.dom.className += space + className;
+                        }
+                    } else {
+                        this.addCls(className);
+                    }
+                }
+            } else {
+                for (i = 0, len = className.length; i < len; i++) {
+                    v = className[i];
+                    if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
+                        cls.push(v);
+                    }
+                }
+                if (cls.length) {
+                    me.dom.className += space + cls.join(" ");
+                }
+            }
+            return me;
+        },
+
+        
+        removeCls : function(className){
+            var me = this,
+                i, idx, len, cls, elClasses;
+            if (className === undefined) {
+                return me;
+            }
+            if (Object.prototype.toString.call(className) !== '[object Array]') {
+                className = className.replace(trimRe, '').split(spacesRe);
+            }
+            if (me.dom && me.dom.className) {
+                elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
+                for (i = 0, len = className.length; i < len; i++) {
+                    cls = className[i];
+                    if (typeof cls == 'string') {
+                        cls = cls.replace(trimRe, '');
+                        idx = Ext.Array.indexOf(elClasses, cls);
+                        if (idx != -1) {
+                            Ext.Array.erase(elClasses, idx, 1);
+                        }
+                    }
+                }
+                me.dom.className = elClasses.join(" ");
+            }
+            return me;
+        },
+
+        
+        radioCls : function(className){
+            var cn = this.dom.parentNode.childNodes,
+                v, i, len;
+            className = Ext.isArray(className) ? className : [className];
+            for (i = 0, len = cn.length; i < len; i++) {
+                v = cn[i];
+                if (v && v.nodeType == 1) {
+                    Ext.fly(v, '_internal').removeCls(className);
+                }
+            }
+            return this.addCls(className);
+        },
+
+        
+        toggleCls : Ext.supports.ClassList ?
+            function(className) {
+                this.dom.classList.toggle(Ext.String.trim(className));
+                return this;
+            } :
+            function(className) {
+                return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
+            },
+
+        
+        hasCls : Ext.supports.ClassList ?
+            function(className) {
+                if (!className) {
+                    return false;
+                }
+                className = className.split(spacesRe);
+                var ln = className.length,
+                    i = 0;
+                for (; i < ln; i++) {
+                    if (className[i] && this.dom.classList.contains(className[i])) {
+                        return true;
+                    }
+                }
+                return false;
+            } :
+            function(className){
+                return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
+            },
+
+        
+        replaceCls : function(oldClassName, newClassName){
+            return this.removeCls(oldClassName).addCls(newClassName);
+        },
+
+        isStyle : function(style, val) {
+            return this.getStyle(style) == val;
+        },
+
+        
+        getStyle : function() {
+            return view && view.getComputedStyle ?
+                function(prop){
+                    var el = this.dom,
+                        v, cs, out, display, cleaner;
+
+                    if(el == document){
+                        return null;
+                    }
+                    prop = ELEMENT.normalize(prop);
+                    out = (v = el.style[prop]) ? v :
+                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
+
+                    
+                    
+                    if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
+                        cleaner = ELEMENT.getRightMarginFixCleaner(el);
+                        display = this.getStyle('display');
+                        el.style.display = 'inline-block';
+                        out = view.getComputedStyle(el, '').marginRight;
+                        el.style.display = display;
+                        cleaner();
+                    }
+
+                    if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
+                        out = 'transparent';
+                    }
+                    return out;
+                } :
+                function (prop) {
+                    var el = this.dom,
+                        m, cs;
+
+                    if (el == document) {
+                        return null;
+                    }
+                    prop = ELEMENT.normalize(prop);
+
+                    do {
+                        if (prop == 'opacity') {
+                            if (el.style.filter.match) {
+                                m = el.style.filter.match(opacityRe);
+                                if(m){
+                                    var fv = parseFloat(m[1]);
+                                    if(!isNaN(fv)){
+                                        return fv ? fv / 100 : 0;
+                                    }
+                                }
+                            }
+                            return 1;
+                        }
+
+                        
+                        
+                        if (!Ext.isIE6) {
+                            return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
+                        }
+
+                        try {
+                            return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
+                        } catch (e) {
+                            
+                            
+                        }
+
+                        if (!ELEMENT.inheritedProps[prop]) {
+                            break;
+                        }
+
+                        el = el.parentNode;
+                        
+                        
+                        
+                    } while (el);
+
+                    return null;
+                }
+        }(),
+
+        
+        getColor : function(attr, defaultValue, prefix){
+            var v = this.getStyle(attr),
+                color = prefix || prefix === '' ? prefix : '#',
+                h;
+
+            if(!v || (/transparent|inherit/.test(v))) {
+                return defaultValue;
+            }
+            if(/^r/.test(v)){
+                Ext.each(v.slice(4, v.length -1).split(','), function(s){
+                    h = parseInt(s, 10);
+                    color += (h < 16 ? '0' : '') + h.toString(16);
+                });
+            }else{
+                v = v.replace('#', '');
+                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
+            }
+            return(color.length > 5 ? color.toLowerCase() : defaultValue);
+        },
+
+        
+        setStyle : function(prop, value){
+            var me = this,
+                tmp, style;
+
+            if (!me.dom) {
+                return me;
+            }
+            if (typeof prop === 'string') {
+                tmp = {};
+                tmp[prop] = value;
+                prop = tmp;
+            }
+            for (style in prop) {
+                if (prop.hasOwnProperty(style)) {
+                    value = Ext.value(prop[style], '');
+                    if (style == 'opacity') {
+                        me.setOpacity(value);
+                    }
+                    else {
+                        me.dom.style[ELEMENT.normalize(style)] = value;
+                    }
+                }
+            }
+            return me;
+        },
+
+        
+        setOpacity: function(opacity, animate) {
+            var me = this,
+                dom = me.dom,
+                val,
+                style;
+
+            if (!me.dom) {
+                return me;
+            }
+
+            style = me.dom.style;
+
+            if (!animate || !me.anim) {
+                if (!Ext.supports.Opacity) {
+                    opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')': '';
+                    val = style.filter.replace(opacityRe, '').replace(trimRe, '');
+
+                    style.zoom = 1;
+                    style.filter = val + (val.length > 0 ? ' ': '') + opacity;
+                }
+                else {
+                    style.opacity = opacity;
+                }
+            }
+            else {
+                if (!Ext.isObject(animate)) {
+                    animate = {
+                        duration: 350,
+                        easing: 'ease-in'
+                    };
+                }
+                me.animate(Ext.applyIf({
+                    to: {
+                        opacity: opacity
+                    }
+                },
+                animate));
+            }
+            return me;
+        },
+
+
+        
+        clearOpacity : function(){
+            var style = this.dom.style;
+            if(!Ext.supports.Opacity){
+                if(!Ext.isEmpty(style.filter)){
+                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
+                }
+            }else{
+                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
+            }
+            return this;
+        },
+
+        
+        adjustDirect2DDimension: function(dimension) {
+            var me = this,
+                dom = me.dom,
+                display = me.getStyle('display'),
+                inlineDisplay = dom.style['display'],
+                inlinePosition = dom.style['position'],
+                originIndex = dimension === 'width' ? 0 : 1,
+                floating;
+
+            if (display === 'inline') {
+                dom.style['display'] = 'inline-block';
+            }
+
+            dom.style['position'] = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
+
+            
+            
+            floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
+
+            dom.style['position'] = inlinePosition;
+
+            if (display === 'inline') {
+                dom.style['display'] = inlineDisplay;
+            }
+
+            return floating;
+        },
+
+        
+        getHeight: function(contentHeight, preciseHeight) {
+            var me = this,
+                dom = me.dom,
+                hidden = Ext.isIE && me.isStyle('display', 'none'),
+                height, overflow, style, floating;
+
+            
+            
+            if (Ext.isIEQuirks) {
+                style = dom.style;
+                overflow = style.overflow;
+                me.setStyle({ overflow: 'hidden'});
+            }
+
+            height = dom.offsetHeight;
+
+            height = MATH.max(height, hidden ? 0 : dom.clientHeight) || 0;
+
+            
+            if (!hidden && Ext.supports.Direct2DBug) {
+                floating = me.adjustDirect2DDimension('height');
+                if (preciseHeight) {
+                    height += floating;
+                }
+                else if (floating > 0 && floating < 0.5) {
+                    height++;
+                }
+            }
+
+            if (contentHeight) {
+                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+            }
+
+            if (Ext.isIEQuirks) {
+                me.setStyle({ overflow: overflow});
+            }
+
+            if (height < 0) {
+                height = 0;
+            }
+            return height;
+        },
+
+        
+        getWidth: function(contentWidth, preciseWidth) {
+            var me = this,
+                dom = me.dom,
+                hidden = Ext.isIE && me.isStyle('display', 'none'),
+                rect, width, overflow, style, floating, parentPosition;
+
+            
+            
+            if (Ext.isIEQuirks) {
+                style = dom.style;
+                overflow = style.overflow;
+                me.setStyle({overflow: 'hidden'});
+            }
+
+            
+            if (Ext.isOpera10_5) {
+                if (dom.parentNode.currentStyle.position === 'relative') {
+                    parentPosition = dom.parentNode.style.position;
+                    dom.parentNode.style.position = 'static';
+                    width = dom.offsetWidth;
+                    dom.parentNode.style.position = parentPosition;
+                }
+                width = Math.max(width || 0, dom.offsetWidth);
+
+            
+            
+            
+            
+            
+            } else if (Ext.supports.BoundingClientRect) {
+                rect = dom.getBoundingClientRect();
+                width = rect.right - rect.left;
+                width = preciseWidth ? width : Math.ceil(width);
+            } else {
+                width = dom.offsetWidth;
+            }
+
+            width = MATH.max(width, hidden ? 0 : dom.clientWidth) || 0;
+
+            
+            if (!hidden && Ext.supports.Direct2DBug) {
+                floating = me.adjustDirect2DDimension('width');
+                if (preciseWidth) {
+                    width += floating;
+                }
+                else if (floating > 0 && floating < 0.5) {
+                    width++;
+                }
+            }
+
+            if (contentWidth) {
+                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+            }
+
+            if (Ext.isIEQuirks) {
+                me.setStyle({ overflow: overflow});
+            }
+
+            if (width < 0) {
+                width = 0;
+            }
+            return width;
+        },
+
+        
+        setWidth : function(width, animate){
+            var me = this;
+            width = me.adjustWidth(width);
+            if (!animate || !me.anim) {
+                me.dom.style.width = me.addUnits(width);
+            }
+            else {
+                if (!Ext.isObject(animate)) {
+                    animate = {};
+                }
+                me.animate(Ext.applyIf({
+                    to: {
+                        width: width
+                    }
+                }, animate));
+            }
+            return me;
+        },
+
+        
+         setHeight : function(height, animate){
+            var me = this;
+            height = me.adjustHeight(height);
+            if (!animate || !me.anim) {
+                me.dom.style.height = me.addUnits(height);
+            }
+            else {
+                if (!Ext.isObject(animate)) {
+                    animate = {};
+                }
+                me.animate(Ext.applyIf({
+                    to: {
+                        height: height
+                    }
+                }, animate));
+            }
+            return me;
+        },
+
+        
+        getBorderWidth : function(side){
+            return this.addStyles(side, borders);
+        },
+
+        
+        getPadding : function(side){
+            return this.addStyles(side, paddings);
+        },
+
+        
+        clip : function(){
+            var me = this,
+                dom = me.dom;
+
+            if(!data(dom, ISCLIPPED)){
+                data(dom, ISCLIPPED, true);
+                data(dom, ORIGINALCLIP, {
+                    o: me.getStyle(OVERFLOW),
+                    x: me.getStyle(OVERFLOWX),
+                    y: me.getStyle(OVERFLOWY)
+                });
+                me.setStyle(OVERFLOW, HIDDEN);
+                me.setStyle(OVERFLOWX, HIDDEN);
+                me.setStyle(OVERFLOWY, HIDDEN);
+            }
+            return me;
+        },
+
+        
+        unclip : function(){
+            var me = this,
+                dom = me.dom,
+                clip;
+
+            if(data(dom, ISCLIPPED)){
+                data(dom, ISCLIPPED, false);
+                clip = data(dom, ORIGINALCLIP);
+                if(clip.o){
+                    me.setStyle(OVERFLOW, clip.o);
+                }
+                if(clip.x){
+                    me.setStyle(OVERFLOWX, clip.x);
+                }
+                if(clip.y){
+                    me.setStyle(OVERFLOWY, clip.y);
+                }
+            }
+            return me;
+        },
+
+        
+        addStyles : function(sides, styles){
+            var totalSize = 0,
+                sidesArr = sides.match(wordsRe),
+                i = 0,
+                len = sidesArr.length,
+                side, size;
+            for (; i < len; i++) {
+                side = sidesArr[i];
+                size = side && parseInt(this.getStyle(styles[side]), 10);
+                if (size) {
+                    totalSize += MATH.abs(size);
+                }
+            }
+            return totalSize;
+        },
+
+        margins : margins,
+
+        
+        applyStyles : function(style){
+            Ext.DomHelper.applyStyles(this.dom, style);
+            return this;
+        },
+
+        
+        getStyles : function(){
+            var styles = {},
+                len = arguments.length,
+                i = 0, style;
+
+            for(; i < len; ++i) {
+                style = arguments[i];
+                styles[style] = this.getStyle(style);
+            }
+            return styles;
+        },
 
        
-       
-       useKeydown: useKeydown
-   };
+        boxWrap : function(cls){
+            cls = cls || Ext.baseCSSPrefix + 'box';
+            var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(ELEMENT.boxMarkup, cls) + "</div>"));
+            Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
+            return el;
+        },
+
+        
+        setSize : function(width, height, animate){
+            var me = this;
+            if (Ext.isObject(width)) { 
+                animate = height;
+                height = width.height;
+                width = width.width;
+            }
+            width = me.adjustWidth(width);
+            height = me.adjustHeight(height);
+            if(!animate || !me.anim){
+                
+                
+                if (!Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7)) {
+                    me.dom.offsetTop;
+                }
+                me.dom.style.width = me.addUnits(width);
+                me.dom.style.height = me.addUnits(height);
+            }
+            else {
+                if (animate === true) {
+                    animate = {};
+                }
+                me.animate(Ext.applyIf({
+                    to: {
+                        width: width,
+                        height: height
+                    }
+                }, animate));
+            }
+            return me;
+        },
+
+        
+        getComputedHeight : function(){
+            var me = this,
+                h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
+            if(!h){
+                h = parseFloat(me.getStyle('height')) || 0;
+                if(!me.isBorderBox()){
+                    h += me.getFrameWidth('tb');
+                }
+            }
+            return h;
+        },
+
+        
+        getComputedWidth : function(){
+            var me = this,
+                w = Math.max(me.dom.offsetWidth, me.dom.clientWidth);
+
+            if(!w){
+                w = parseFloat(me.getStyle('width')) || 0;
+                if(!me.isBorderBox()){
+                    w += me.getFrameWidth('lr');
+                }
+            }
+            return w;
+        },
+
+        
+        getFrameWidth : function(sides, onlyContentBox){
+            return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
+        },
+
+        
+        addClsOnOver : function(className){
+            var dom = this.dom;
+            this.hover(
+                function(){
+                    Ext.fly(dom, INTERNAL).addCls(className);
+                },
+                function(){
+                    Ext.fly(dom, INTERNAL).removeCls(className);
+                }
+            );
+            return this;
+        },
+
+        
+        addClsOnFocus : function(className){
+            var me = this,
+                dom = me.dom;
+            me.on("focus", function(){
+                Ext.fly(dom, INTERNAL).addCls(className);
+            });
+            me.on("blur", function(){
+                Ext.fly(dom, INTERNAL).removeCls(className);
+            });
+            return me;
+        },
+
+        
+        addClsOnClick : function(className){
+            var dom = this.dom;
+            this.on("mousedown", function(){
+                Ext.fly(dom, INTERNAL).addCls(className);
+                var d = Ext.getDoc(),
+                    fn = function(){
+                        Ext.fly(dom, INTERNAL).removeCls(className);
+                        d.removeListener("mouseup", fn);
+                    };
+                d.on("mouseup", fn);
+            });
+            return this;
+        },
+
+        
+
+        getViewSize : function(){
+            var me = this,
+                dom = me.dom,
+                isDoc = (dom == Ext.getDoc().dom || dom == Ext.getBody().dom),
+                style, overflow, ret;
+
+            
+            if (isDoc) {
+                ret = {
+                    width : ELEMENT.getViewWidth(),
+                    height : ELEMENT.getViewHeight()
+                };
+
+            
+            }
+            else {
+                
+                
+                if (Ext.isIE6 || Ext.isIEQuirks) {
+                    style = dom.style;
+                    overflow = style.overflow;
+                    me.setStyle({ overflow: 'hidden'});
+                }
+                ret = {
+                    width : dom.clientWidth,
+                    height : dom.clientHeight
+                };
+                if (Ext.isIE6 || Ext.isIEQuirks) {
+                    me.setStyle({ overflow: overflow });
+                }
+            }
+            return ret;
+        },
+
+        
+
+        getStyleSize : function(){
+            var me = this,
+                doc = document,
+                d = this.dom,
+                isDoc = (d == doc || d == doc.body),
+                s = d.style,
+                w, h;
+
+            
+            if (isDoc) {
+                return {
+                    width : ELEMENT.getViewWidth(),
+                    height : ELEMENT.getViewHeight()
+                };
+            }
+            
+            if(s.width && s.width != 'auto'){
+                w = parseFloat(s.width);
+                if(me.isBorderBox()){
+                   w -= me.getFrameWidth('lr');
+                }
+            }
+            
+            if(s.height && s.height != 'auto'){
+                h = parseFloat(s.height);
+                if(me.isBorderBox()){
+                   h -= me.getFrameWidth('tb');
+                }
+            }
+            
+            return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
+        },
+
+        
+        getSize : function(contentSize){
+            return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
+        },
+
+        
+        repaint : function(){
+            var dom = this.dom;
+            this.addCls(Ext.baseCSSPrefix + 'repaint');
+            setTimeout(function(){
+                Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
+            }, 1);
+            return this;
+        },
+
+        
+        selectable : function() {
+            var me = this;
+            me.dom.unselectable = "off";
+            
+            me.on('selectstart', function (e) {
+                e.stopPropagation();
+                return true;
+            });
+            me.applyStyles("-moz-user-select: text; -khtml-user-select: text;");
+            me.removeCls(Ext.baseCSSPrefix + 'unselectable');
+            return me;
+        },
+
+        
+        unselectable : function(){
+            var me = this;
+            me.dom.unselectable = "on";
+
+            me.swallowEvent("selectstart", true);
+            me.applyStyles("-moz-user-select:-moz-none;-khtml-user-select:none;");
+            me.addCls(Ext.baseCSSPrefix + 'unselectable');
+
+            return me;
+        },
+
+        
+        getMargin : function(side){
+            var me = this,
+                hash = {t:"top", l:"left", r:"right", b: "bottom"},
+                o = {},
+                key;
+
+            if (!side) {
+                for (key in me.margins){
+                    o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
+                }
+                return o;
+            } else {
+                return me.addStyles.call(me, side, me.margins);
+            }
+        }
+    });
+})();
+
+
+Ext.Element.VISIBILITY = 1;
+
+Ext.Element.DISPLAY = 2;
+
+
+Ext.Element.OFFSETS = 3;
+
+
+Ext.Element.ASCLASS = 4;
+
+
+Ext.Element.visibilityCls = Ext.baseCSSPrefix + 'hide-nosize';
+
+Ext.Element.addMethods(function(){
+    var El = Ext.Element,
+        OPACITY = "opacity",
+        VISIBILITY = "visibility",
+        DISPLAY = "display",
+        HIDDEN = "hidden",
+        OFFSETS = "offsets",
+        ASCLASS = "asclass",
+        NONE = "none",
+        NOSIZE = 'nosize',
+        ORIGINALDISPLAY = 'originalDisplay',
+        VISMODE = 'visibilityMode',
+        ISVISIBLE = 'isVisible',
+        data = El.data,
+        getDisplay = function(dom){
+            var d = data(dom, ORIGINALDISPLAY);
+            if(d === undefined){
+                data(dom, ORIGINALDISPLAY, d = '');
+            }
+            return d;
+        },
+        getVisMode = function(dom){
+            var m = data(dom, VISMODE);
+            if(m === undefined){
+                data(dom, VISMODE, m = 1);
+            }
+            return m;
+        };
+
+    return {
+        
+        originalDisplay : "",
+        visibilityMode : 1,
+
+        
+        setVisibilityMode : function(visMode){
+            data(this.dom, VISMODE, visMode);
+            return this;
+        },
+
+        
+        isVisible : function() {
+            var me = this,
+                dom = me.dom,
+                visible = data(dom, ISVISIBLE);
+
+            if(typeof visible == 'boolean'){ 
+                return visible;
+            }
+            
+            visible = !me.isStyle(VISIBILITY, HIDDEN) &&
+                      !me.isStyle(DISPLAY, NONE) &&
+                      !((getVisMode(dom) == El.ASCLASS) && me.hasCls(me.visibilityCls || El.visibilityCls));
+
+            data(dom, ISVISIBLE, visible);
+            return visible;
+        },
+
+        
+        setVisible : function(visible, animate){
+            var me = this, isDisplay, isVisibility, isOffsets, isNosize,
+                dom = me.dom,
+                visMode = getVisMode(dom);
+
+
+            
+            if (typeof animate == 'string'){
+                switch (animate) {
+                    case DISPLAY:
+                        visMode = El.DISPLAY;
+                        break;
+                    case VISIBILITY:
+                        visMode = El.VISIBILITY;
+                        break;
+                    case OFFSETS:
+                        visMode = El.OFFSETS;
+                        break;
+                    case NOSIZE:
+                    case ASCLASS:
+                        visMode = El.ASCLASS;
+                        break;
+                }
+                me.setVisibilityMode(visMode);
+                animate = false;
+            }
+
+            if (!animate || !me.anim) {
+                if(visMode == El.ASCLASS ){
+
+                    me[visible?'removeCls':'addCls'](me.visibilityCls || El.visibilityCls);
+
+                } else if (visMode == El.DISPLAY){
+
+                    return me.setDisplayed(visible);
+
+                } else if (visMode == El.OFFSETS){
+
+                    if (!visible){
+                        
+                        if (!me.hideModeStyles) {
+                            me.hideModeStyles = {
+                                position: me.getStyle('position'),
+                                top: me.getStyle('top'),
+                                left: me.getStyle('left')
+                            };
+                        }
+                        me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
+                    }
+
+                    
+                    
+                    else if (me.hideModeStyles) {
+                        me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
+                        delete me.hideModeStyles;
+                    }
+
+                }else{
+                    me.fixDisplay();
+                    
+                    dom.style.visibility = visible ? '' : HIDDEN;
+                }
+            }else{
+                
+                if(visible){
+                    me.setOpacity(0.01);
+                    me.setVisible(true);
+                }
+                if (!Ext.isObject(animate)) {
+                    animate = {
+                        duration: 350,
+                        easing: 'ease-in'
+                    };
+                }
+                me.animate(Ext.applyIf({
+                    callback: function() {
+                        visible || me.setVisible(false).setOpacity(1);
+                    },
+                    to: {
+                        opacity: (visible) ? 1 : 0
+                    }
+                }, animate));
+            }
+            data(dom, ISVISIBLE, visible);  
+            return me;
+        },
+
+
+        
+        hasMetrics  : function(){
+            var dom = this.dom;
+            return this.isVisible() || (getVisMode(dom) == El.OFFSETS) || (getVisMode(dom) == El.VISIBILITY);
+        },
+
+        
+        toggle : function(animate){
+            var me = this;
+            me.setVisible(!me.isVisible(), me.anim(animate));
+            return me;
+        },
+
+        
+        setDisplayed : function(value) {
+            if(typeof value == "boolean"){
+               value = value ? getDisplay(this.dom) : NONE;
+            }
+            this.setStyle(DISPLAY, value);
+            return this;
+        },
+
+        
+        fixDisplay : function(){
+            var me = this;
+            if (me.isStyle(DISPLAY, NONE)) {
+                me.setStyle(VISIBILITY, HIDDEN);
+                me.setStyle(DISPLAY, getDisplay(this.dom)); 
+                if (me.isStyle(DISPLAY, NONE)) { 
+                    me.setStyle(DISPLAY, "block");
+                }
+            }
+        },
+
+        
+        hide : function(animate){
+            
+            if (typeof animate == 'string'){
+                this.setVisible(false, animate);
+                return this;
+            }
+            this.setVisible(false, this.anim(animate));
+            return this;
+        },
+
+        
+        show : function(animate){
+            
+            if (typeof animate == 'string'){
+                this.setVisible(true, animate);
+                return this;
+            }
+            this.setVisible(true, this.anim(animate));
+            return this;
+        }
+    };
+}());
+
+Ext.applyIf(Ext.Element.prototype, {
+    
+    animate: function(config) {
+        var me = this;
+        if (!me.id) {
+            me = Ext.get(me.dom);
+        }
+        if (Ext.fx.Manager.hasFxBlock(me.id)) {
+            return me;
+        }
+        Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config)));
+        return this;
+    },
+
+    
+    anim: function(config) {
+        if (!Ext.isObject(config)) {
+            return (config) ? {} : false;
+        }
+
+        var me = this,
+            duration = config.duration || Ext.fx.Anim.prototype.duration,
+            easing = config.easing || 'ease',
+            animConfig;
+
+        if (config.stopAnimation) {
+            me.stopAnimation();
+        }
+
+        Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
+
+        
+        Ext.fx.Manager.setFxDefaults(me.id, {
+            delay: 0
+        });
+
+        animConfig = {
+            target: me,
+            remove: config.remove,
+            alternate: config.alternate || false,
+            duration: duration,
+            easing: easing,
+            callback: config.callback,
+            listeners: config.listeners,
+            iterations: config.iterations || 1,
+            scope: config.scope,
+            block: config.block,
+            concurrent: config.concurrent,
+            delay: config.delay || 0,
+            paused: true,
+            keyframes: config.keyframes,
+            from: config.from || {},
+            to: Ext.apply({}, config)
+        };
+        Ext.apply(animConfig.to, config.to);
+
+        
+        delete animConfig.to.to;
+        delete animConfig.to.from;
+        delete animConfig.to.remove;
+        delete animConfig.to.alternate;
+        delete animConfig.to.keyframes;
+        delete animConfig.to.iterations;
+        delete animConfig.to.listeners;
+        delete animConfig.to.target;
+        delete animConfig.to.paused;
+        delete animConfig.to.callback;
+        delete animConfig.to.scope;
+        delete animConfig.to.duration;
+        delete animConfig.to.easing;
+        delete animConfig.to.concurrent;
+        delete animConfig.to.block;
+        delete animConfig.to.stopAnimation;
+        delete animConfig.to.delay;
+        return animConfig;
+    },
+
+    
+    slideIn: function(anchor, obj, slideOut) {
+        var me = this,
+            elStyle = me.dom.style,
+            beforeAnim, wrapAnim;
+
+        anchor = anchor || "t";
+        obj = obj || {};
+
+        beforeAnim = function() {
+            var animScope = this,
+                listeners = obj.listeners,
+                box, position, restoreSize, wrap, anim;
+
+            if (!slideOut) {
+                me.fixDisplay();
+            }
+
+            box = me.getBox();
+            if ((anchor == 't' || anchor == 'b') && box.height === 0) {
+                box.height = me.dom.scrollHeight;
+            }
+            else if ((anchor == 'l' || anchor == 'r') && box.width === 0) {
+                box.width = me.dom.scrollWidth;
+            }
+
+            position = me.getPositioning();
+            me.setSize(box.width, box.height);
+
+            wrap = me.wrap({
+                style: {
+                    visibility: slideOut ? 'visible' : 'hidden'
+                }
+            });
+            wrap.setPositioning(position);
+            if (wrap.isStyle('position', 'static')) {
+                wrap.position('relative');
+            }
+            me.clearPositioning('auto');
+            wrap.clip();
+
+            
+            
+            
+            me.setStyle({
+                visibility: '',
+                position: 'absolute'
+            });
+            if (slideOut) {
+                wrap.setSize(box.width, box.height);
+            }
+
+            switch (anchor) {
+                case 't':
+                    anim = {
+                        from: {
+                            width: box.width + 'px',
+                            height: '0px'
+                        },
+                        to: {
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    elStyle.bottom = '0px';
+                    break;
+                case 'l':
+                    anim = {
+                        from: {
+                            width: '0px',
+                            height: box.height + 'px'
+                        },
+                        to: {
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    elStyle.right = '0px';
+                    break;
+                case 'r':
+                    anim = {
+                        from: {
+                            x: box.x + box.width,
+                            width: '0px',
+                            height: box.height + 'px'
+                        },
+                        to: {
+                            x: box.x,
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    break;
+                case 'b':
+                    anim = {
+                        from: {
+                            y: box.y + box.height,
+                            width: box.width + 'px',
+                            height: '0px'
+                        },
+                        to: {
+                            y: box.y,
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    break;
+                case 'tl':
+                    anim = {
+                        from: {
+                            x: box.x,
+                            y: box.y,
+                            width: '0px',
+                            height: '0px'
+                        },
+                        to: {
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    elStyle.bottom = '0px';
+                    elStyle.right = '0px';
+                    break;
+                case 'bl':
+                    anim = {
+                        from: {
+                            x: box.x + box.width,
+                            width: '0px',
+                            height: '0px'
+                        },
+                        to: {
+                            x: box.x,
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    elStyle.right = '0px';
+                    break;
+                case 'br':
+                    anim = {
+                        from: {
+                            x: box.x + box.width,
+                            y: box.y + box.height,
+                            width: '0px',
+                            height: '0px'
+                        },
+                        to: {
+                            x: box.x,
+                            y: box.y,
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    break;
+                case 'tr':
+                    anim = {
+                        from: {
+                            y: box.y + box.height,
+                            width: '0px',
+                            height: '0px'
+                        },
+                        to: {
+                            y: box.y,
+                            width: box.width + 'px',
+                            height: box.height + 'px'
+                        }
+                    };
+                    elStyle.bottom = '0px';
+                    break;
+            }
+
+            wrap.show();
+            wrapAnim = Ext.apply({}, obj);
+            delete wrapAnim.listeners;
+            wrapAnim = Ext.create('Ext.fx.Anim', Ext.applyIf(wrapAnim, {
+                target: wrap,
+                duration: 500,
+                easing: 'ease-out',
+                from: slideOut ? anim.to : anim.from,
+                to: slideOut ? anim.from : anim.to
+            }));
+
+            
+            wrapAnim.on('afteranimate', function() {
+                if (slideOut) {
+                    me.setPositioning(position);
+                    if (obj.useDisplay) {
+                        me.setDisplayed(false);
+                    } else {
+                        me.hide();
+                    }
+                }
+                else {
+                    me.clearPositioning();
+                    me.setPositioning(position);
+                }
+                if (wrap.dom) {
+                    wrap.dom.parentNode.insertBefore(me.dom, wrap.dom);
+                    wrap.remove();
+                }
+                me.setSize(box.width, box.height);
+                animScope.end();
+            });
+            
+            if (listeners) {
+                wrapAnim.on(listeners);
+            }
+        };
+
+        me.animate({
+            duration: obj.duration ? obj.duration * 2 : 1000,
+            listeners: {
+                beforeanimate: {
+                    fn: beforeAnim
+                },
+                afteranimate: {
+                    fn: function() {
+                        if (wrapAnim && wrapAnim.running) {
+                            wrapAnim.end();
+                        }
+                    }
+                }
+            }
+        });
+        return me;
+    },
+
+
+    
+    slideOut: function(anchor, o) {
+        return this.slideIn(anchor, o, true);
+    },
+
+    
+    puff: function(obj) {
+        var me = this,
+            beforeAnim;
+        obj = Ext.applyIf(obj || {}, {
+            easing: 'ease-out',
+            duration: 500,
+            useDisplay: false
+        });
+
+        beforeAnim = function() {
+            me.clearOpacity();
+            me.show();
+
+            var box = me.getBox(),
+                fontSize = me.getStyle('fontSize'),
+                position = me.getPositioning();
+            this.to = {
+                width: box.width * 2,
+                height: box.height * 2,
+                x: box.x - (box.width / 2),
+                y: box.y - (box.height /2),
+                opacity: 0,
+                fontSize: '200%'
+            };
+            this.on('afteranimate',function() {
+                if (me.dom) {
+                    if (obj.useDisplay) {
+                        me.setDisplayed(false);
+                    } else {
+                        me.hide();
+                    }
+                    me.clearOpacity();
+                    me.setPositioning(position);
+                    me.setStyle({fontSize: fontSize});
+                }
+            });
+        };
+
+        me.animate({
+            duration: obj.duration,
+            easing: obj.easing,
+            listeners: {
+                beforeanimate: {
+                    fn: beforeAnim
+                }
+            }
+        });
+        return me;
+    },
+
+    
+    switchOff: function(obj) {
+        var me = this,
+            beforeAnim;
+
+        obj = Ext.applyIf(obj || {}, {
+            easing: 'ease-in',
+            duration: 500,
+            remove: false,
+            useDisplay: false
+        });
+
+        beforeAnim = function() {
+            var animScope = this,
+                size = me.getSize(),
+                xy = me.getXY(),
+                keyframe, position;
+            me.clearOpacity();
+            me.clip();
+            position = me.getPositioning();
+
+            keyframe = Ext.create('Ext.fx.Animator', {
+                target: me,
+                duration: obj.duration,
+                easing: obj.easing,
+                keyframes: {
+                    33: {
+                        opacity: 0.3
+                    },
+                    66: {
+                        height: 1,
+                        y: xy[1] + size.height / 2
+                    },
+                    100: {
+                        width: 1,
+                        x: xy[0] + size.width / 2
+                    }
+                }
+            });
+            keyframe.on('afteranimate', function() {
+                if (obj.useDisplay) {
+                    me.setDisplayed(false);
+                } else {
+                    me.hide();
+                }
+                me.clearOpacity();
+                me.setPositioning(position);
+                me.setSize(size);
+                animScope.end();
+            });
+        };
+        me.animate({
+            duration: (obj.duration * 2),
+            listeners: {
+                beforeanimate: {
+                    fn: beforeAnim
+                }
+            }
+        });
+        return me;
+    },
+
+    
+    frame : function(color, count, obj){
+        var me = this,
+            beforeAnim;
+
+        color = color || '#C3DAF9';
+        count = count || 1;
+        obj = obj || {};
+
+        beforeAnim = function() {
+            me.show();
+            var animScope = this,
+                box = me.getBox(),
+                proxy = Ext.getBody().createChild({
+                    style: {
+                        position : 'absolute',
+                        'pointer-events': 'none',
+                        'z-index': 35000,
+                        border : '0px solid ' + color
+                    }
+                }),
+                proxyAnim;
+            proxyAnim = Ext.create('Ext.fx.Anim', {
+                target: proxy,
+                duration: obj.duration || 1000,
+                iterations: count,
+                from: {
+                    top: box.y,
+                    left: box.x,
+                    borderWidth: 0,
+                    opacity: 1,
+                    height: box.height,
+                    width: box.width
+                },
+                to: {
+                    top: box.y - 20,
+                    left: box.x - 20,
+                    borderWidth: 10,
+                    opacity: 0,
+                    height: box.height + 40,
+                    width: box.width + 40
+                }
+            });
+            proxyAnim.on('afteranimate', function() {
+                proxy.remove();
+                animScope.end();
+            });
+        };
+
+        me.animate({
+            duration: (obj.duration * 2) || 2000,
+            listeners: {
+                beforeanimate: {
+                    fn: beforeAnim
+                }
+            }
+        });
+        return me;
+    },
+
+    
+    ghost: function(anchor, obj) {
+        var me = this,
+            beforeAnim;
+
+        anchor = anchor || "b";
+        beforeAnim = function() {
+            var width = me.getWidth(),
+                height = me.getHeight(),
+                xy = me.getXY(),
+                position = me.getPositioning(),
+                to = {
+                    opacity: 0
+                };
+            switch (anchor) {
+                case 't':
+                    to.y = xy[1] - height;
+                    break;
+                case 'l':
+                    to.x = xy[0] - width;
+                    break;
+                case 'r':
+                    to.x = xy[0] + width;
+                    break;
+                case 'b':
+                    to.y = xy[1] + height;
+                    break;
+                case 'tl':
+                    to.x = xy[0] - width;
+                    to.y = xy[1] - height;
+                    break;
+                case 'bl':
+                    to.x = xy[0] - width;
+                    to.y = xy[1] + height;
+                    break;
+                case 'br':
+                    to.x = xy[0] + width;
+                    to.y = xy[1] + height;
+                    break;
+                case 'tr':
+                    to.x = xy[0] + width;
+                    to.y = xy[1] - height;
+                    break;
+            }
+            this.to = to;
+            this.on('afteranimate', function () {
+                if (me.dom) {
+                    me.hide();
+                    me.clearOpacity();
+                    me.setPositioning(position);
+                }
+            });
+        };
+
+        me.animate(Ext.applyIf(obj || {}, {
+            duration: 500,
+            easing: 'ease-out',
+            listeners: {
+                beforeanimate: {
+                    fn: beforeAnim
+                }
+            }
+        }));
+        return me;
+    },
+
+    
+    highlight: function(color, o) {
+        var me = this,
+            dom = me.dom,
+            from = {},
+            restore, to, attr, lns, event, fn;
+
+        o = o || {};
+        lns = o.listeners || {};
+        attr = o.attr || 'backgroundColor';
+        from[attr] = color || 'ffff9c';
+
+        if (!o.to) {
+            to = {};
+            to[attr] = o.endColor || me.getColor(attr, 'ffffff', '');
+        }
+        else {
+            to = o.to;
+        }
+
+        
+        o.listeners = Ext.apply(Ext.apply({}, lns), {
+            beforeanimate: function() {
+                restore = dom.style[attr];
+                me.clearOpacity();
+                me.show();
+
+                event = lns.beforeanimate;
+                if (event) {
+                    fn = event.fn || event;
+                    return fn.apply(event.scope || lns.scope || window, arguments);
+                }
+            },
+            afteranimate: function() {
+                if (dom) {
+                    dom.style[attr] = restore;
+                }
+
+                event = lns.afteranimate;
+                if (event) {
+                    fn = event.fn || event;
+                    fn.apply(event.scope || lns.scope || window, arguments);
+                }
+            }
+        });
+
+        me.animate(Ext.apply({}, o, {
+            duration: 1000,
+            easing: 'ease-in',
+            from: from,
+            to: to
+        }));
+        return me;
+    },
+
+   
+    pause: function(ms) {
+        var me = this;
+        Ext.fx.Manager.setFxDefaults(me.id, {
+            delay: ms
+        });
+        return me;
+    },
+
+    
+    fadeIn: function(o) {
+        this.animate(Ext.apply({}, o, {
+            opacity: 1
+        }));
+        return this;
+    },
+
+    
+    fadeOut: function(o) {
+        this.animate(Ext.apply({}, o, {
+            opacity: 0
+        }));
+        return this;
+    },
+
+    
+    scale: function(w, h, o) {
+        this.animate(Ext.apply({}, o, {
+            width: w,
+            height: h
+        }));
+        return this;
+    },
+
+    
+    shift: function(config) {
+        this.animate(config);
+        return this;
+    }
+});
+
+
+Ext.applyIf(Ext.Element, {
+    unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
+    camelRe: /(-[a-z])/gi,
+    opacityRe: /alpha\(opacity=(.*)\)/i,
+    cssRe: /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
+    propertyCache: {},
+    defaultUnit : "px",
+    borders: {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'},
+    paddings: {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'},
+    margins: {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'},
+
+    
+    addUnits : Ext.Element.prototype.addUnits,
+
+    
+    parseBox : function(box) {
+        if (Ext.isObject(box)) {
+            return {
+                top: box.top || 0,
+                right: box.right || 0,
+                bottom: box.bottom || 0,
+                left: box.left || 0
+            };
+        } else {
+            if (typeof box != 'string') {
+                box = box.toString();
+            }
+            var parts  = box.split(' '),
+                ln = parts.length;
+    
+            if (ln == 1) {
+                parts[1] = parts[2] = parts[3] = parts[0];
+            }
+            else if (ln == 2) {
+                parts[2] = parts[0];
+                parts[3] = parts[1];
+            }
+            else if (ln == 3) {
+                parts[3] = parts[1];
+            }
+    
+            return {
+                top   :parseFloat(parts[0]) || 0,
+                right :parseFloat(parts[1]) || 0,
+                bottom:parseFloat(parts[2]) || 0,
+                left  :parseFloat(parts[3]) || 0
+            };
+        }
+        
+    },
+    
+    
+    unitizeBox : function(box, units) {
+        var A = this.addUnits,
+            B = this.parseBox(box);
+            
+        return A(B.top, units) + ' ' +
+               A(B.right, units) + ' ' +
+               A(B.bottom, units) + ' ' +
+               A(B.left, units);
+        
+    },
+
+    
+    camelReplaceFn : function(m, a) {
+        return a.charAt(1).toUpperCase();
+    },
+
+    
+    normalize : function(prop) {
+        if (prop == 'float') {
+            prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';
+        }
+        return this.propertyCache[prop] || (this.propertyCache[prop] = prop.replace(this.camelRe, this.camelReplaceFn));
+    },
+
+    
+    getDocumentHeight: function() {
+        return Math.max(!Ext.isStrict ? document.body.scrollHeight : document.documentElement.scrollHeight, this.getViewportHeight());
+    },
+
+    
+    getDocumentWidth: function() {
+        return Math.max(!Ext.isStrict ? document.body.scrollWidth : document.documentElement.scrollWidth, this.getViewportWidth());
+    },
+
+    
+    getViewportHeight: function(){
+        return window.innerHeight;
+    },
+
+    
+    getViewportWidth : function() {
+        return window.innerWidth;
+    },
+
+    
+    getViewSize : function() {
+        return {
+            width: window.innerWidth,
+            height: window.innerHeight
+        };
+    },
+
+    
+    getOrientation : function() {
+        if (Ext.supports.OrientationChange) {
+            return (window.orientation == 0) ? 'portrait' : 'landscape';
+        }
+        
+        return (window.innerHeight > window.innerWidth) ? 'portrait' : 'landscape';
+    },
+
+    
+    fromPoint: function(x, y) {
+        return Ext.get(document.elementFromPoint(x, y));
+    },
+    
+    
+    parseStyles: function(styles){
+        var out = {},
+            cssRe = this.cssRe,
+            matches;
+            
+        if (styles) {
+            
+            
+            
+            
+            cssRe.lastIndex = 0;
+            while ((matches = cssRe.exec(styles))) {
+                out[matches[1]] = matches[2];
+            }
+        }
+        return out;
+    }
+});
+
+
+Ext.CompositeElementLite = function(els, root){
+    
+    this.elements = [];
+    this.add(els, root);
+    this.el = new Ext.Element.Flyweight();
+};
+
+Ext.CompositeElementLite.prototype = {
+    isComposite: true,
+
+    
+    getElement : function(el){
+        
+        var e = this.el;
+        e.dom = el;
+        e.id = el.id;
+        return e;
+    },
+
+    
+    transformElement : function(el){
+        return Ext.getDom(el);
+    },
+
+    
+    getCount : function(){
+        return this.elements.length;
+    },
+    
+    add : function(els, root){
+        var me = this,
+            elements = me.elements;
+        if(!els){
+            return this;
+        }
+        if(typeof els == "string"){
+            els = Ext.Element.selectorFunction(els, root);
+        }else if(els.isComposite){
+            els = els.elements;
+        }else if(!Ext.isIterable(els)){
+            els = [els];
+        }
+
+        for(var i = 0, len = els.length; i < len; ++i){
+            elements.push(me.transformElement(els[i]));
+        }
+        return me;
+    },
+
+    invoke : function(fn, args){
+        var me = this,
+            els = me.elements,
+            len = els.length,
+            e,
+            i;
+
+        for(i = 0; i < len; i++) {
+            e = els[i];
+            if(e){
+                Ext.Element.prototype[fn].apply(me.getElement(e), args);
+            }
+        }
+        return me;
+    },
+    
+    item : function(index){
+        var me = this,
+            el = me.elements[index],
+            out = null;
+
+        if(el){
+            out = me.getElement(el);
+        }
+        return out;
+    },
+
+    
+    addListener : function(eventName, handler, scope, opt){
+        var els = this.elements,
+            len = els.length,
+            i, e;
+
+        for(i = 0; i<len; i++) {
+            e = els[i];
+            if(e) {
+                Ext.EventManager.on(e, eventName, handler, scope || e, opt);
+            }
+        }
+        return this;
+    },
+    
+    each : function(fn, scope){
+        var me = this,
+            els = me.elements,
+            len = els.length,
+            i, e;
+
+        for(i = 0; i<len; i++) {
+            e = els[i];
+            if(e){
+                e = this.getElement(e);
+                if(fn.call(scope || e, e, me, i) === false){
+                    break;
+                }
+            }
+        }
+        return me;
+    },
+
+    
+    fill : function(els){
+        var me = this;
+        me.elements = [];
+        me.add(els);
+        return me;
+    },
+
+    
+    filter : function(selector){
+        var els = [],
+            me = this,
+            fn = Ext.isFunction(selector) ? selector
+                : function(el){
+                    return el.is(selector);
+                };
+
+        me.each(function(el, self, i) {
+            if (fn(el, i) !== false) {
+                els[els.length] = me.transformElement(el);
+            }
+        });
+
+        me.elements = els;
+        return me;
+    },
+
+    
+    indexOf : function(el){
+        return Ext.Array.indexOf(this.elements, this.transformElement(el));
+    },
+
+    
+    replaceElement : function(el, replacement, domReplace){
+        var index = !isNaN(el) ? el : this.indexOf(el),
+            d;
+        if(index > -1){
+            replacement = Ext.getDom(replacement);
+            if(domReplace){
+                d = this.elements[index];
+                d.parentNode.insertBefore(replacement, d);
+                Ext.removeNode(d);
+            }
+            Ext.Array.splice(this.elements, index, 1, replacement);
+        }
+        return this;
+    },
+
+    
+    clear : function(){
+        this.elements = [];
+    }
+};
+
+Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
+
+
+Ext.CompositeElementLite.importElementMethods = function() {
+    var fnName,
+        ElProto = Ext.Element.prototype,
+        CelProto = Ext.CompositeElementLite.prototype;
+
+    for (fnName in ElProto) {
+        if (typeof ElProto[fnName] == 'function'){
+            (function(fnName) {
+                CelProto[fnName] = CelProto[fnName] || function() {
+                    return this.invoke(fnName, arguments);
+                };
+            }).call(CelProto, fnName);
+
+        }
+    }
+};
+
+Ext.CompositeElementLite.importElementMethods();
+
+if(Ext.DomQuery){
+    Ext.Element.selectorFunction = Ext.DomQuery.select;
+}
+
+
+Ext.Element.select = function(selector, root){
+    var els;
+    if(typeof selector == "string"){
+        els = Ext.Element.selectorFunction(selector, root);
+    }else if(selector.length !== undefined){
+        els = selector;
+    }else{
+    }
+    return new Ext.CompositeElementLite(els);
+};
+
+Ext.select = Ext.Element.select;
+
+
+Ext.util.DelayedTask = function(fn, scope, args) {
+    var me = this,
+        id,
+        call = function() {
+            clearInterval(id);
+            id = null;
+            fn.apply(scope, args || []);
+        };
+
+    
+    this.delay = function(delay, newFn, newScope, newArgs) {
+        me.cancel();
+        fn = newFn || fn;
+        scope = newScope || scope;
+        args = newArgs || args;
+        id = setInterval(call, delay);
+    };
+
+    
+    this.cancel = function(){
+        if (id) {
+            clearInterval(id);
+            id = null;
+        }
+    };
+};
+Ext.require('Ext.util.DelayedTask', function() {
+
+    Ext.util.Event = Ext.extend(Object, (function() {
+        function createBuffered(handler, listener, o, scope) {
+            listener.task = new Ext.util.DelayedTask();
+            return function() {
+                listener.task.delay(o.buffer, handler, scope, Ext.Array.toArray(arguments));
+            };
+        }
+
+        function createDelayed(handler, listener, o, scope) {
+            return function() {
+                var task = new Ext.util.DelayedTask();
+                if (!listener.tasks) {
+                    listener.tasks = [];
+                }
+                listener.tasks.push(task);
+                task.delay(o.delay || 10, handler, scope, Ext.Array.toArray(arguments));
+            };
+        }
+
+        function createSingle(handler, listener, o, scope) {
+            return function() {
+                listener.ev.removeListener(listener.fn, scope);
+                return handler.apply(scope, arguments);
+            };
+        }
+
+        return {
+            isEvent: true,
+
+            constructor: function(observable, name) {
+                this.name = name;
+                this.observable = observable;
+                this.listeners = [];
+            },
+
+            addListener: function(fn, scope, options) {
+                var me = this,
+                    listener;
+                    scope = scope || me.observable;
+
+
+                if (!me.isListening(fn, scope)) {
+                    listener = me.createListener(fn, scope, options);
+                    if (me.firing) {
+                        
+                        me.listeners = me.listeners.slice(0);
+                    }
+                    me.listeners.push(listener);
+                }
+            },
+
+            createListener: function(fn, scope, o) {
+                o = o || {};
+                scope = scope || this.observable;
+
+                var listener = {
+                        fn: fn,
+                        scope: scope,
+                        o: o,
+                        ev: this
+                    },
+                    handler = fn;
+
+                
+                
+                if (o.single) {
+                    handler = createSingle(handler, listener, o, scope);
+                }
+                if (o.delay) {
+                    handler = createDelayed(handler, listener, o, scope);
+                }
+                if (o.buffer) {
+                    handler = createBuffered(handler, listener, o, scope);
+                }
+
+                listener.fireFn = handler;
+                return listener;
+            },
+
+            findListener: function(fn, scope) {
+                var listeners = this.listeners,
+                i = listeners.length,
+                listener,
+                s;
+
+                while (i--) {
+                    listener = listeners[i];
+                    if (listener) {
+                        s = listener.scope;
+                        if (listener.fn == fn && (s == scope || s == this.observable)) {
+                            return i;
+                        }
+                    }
+                }
+
+                return - 1;
+            },
+
+            isListening: function(fn, scope) {
+                return this.findListener(fn, scope) !== -1;
+            },
+
+            removeListener: function(fn, scope) {
+                var me = this,
+                    index,
+                    listener,
+                    k;
+                index = me.findListener(fn, scope);
+                if (index != -1) {
+                    listener = me.listeners[index];
+
+                    if (me.firing) {
+                        me.listeners = me.listeners.slice(0);
+                    }
+
+                    
+                    if (listener.task) {
+                        listener.task.cancel();
+                        delete listener.task;
+                    }
+
+                    
+                    k = listener.tasks && listener.tasks.length;
+                    if (k) {
+                        while (k--) {
+                            listener.tasks[k].cancel();
+                        }
+                        delete listener.tasks;
+                    }
+
+                    
+                    Ext.Array.erase(me.listeners, index, 1);
+                    return true;
+                }
+
+                return false;
+            },
+
+            
+            clearListeners: function() {
+                var listeners = this.listeners,
+                    i = listeners.length;
+
+                while (i--) {
+                    this.removeListener(listeners[i].fn, listeners[i].scope);
+                }
+            },
+
+            fire: function() {
+                var me = this,
+                    listeners = me.listeners,
+                    count = listeners.length,
+                    i,
+                    args,
+                    listener;
+
+                if (count > 0) {
+                    me.firing = true;
+                    for (i = 0; i < count; i++) {
+                        listener = listeners[i];
+                        args = arguments.length ? Array.prototype.slice.call(arguments, 0) : [];
+                        if (listener.o) {
+                            args.push(listener.o);
+                        }
+                        if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) {
+                            return (me.firing = false);
+                        }
+                    }
+                }
+                me.firing = false;
+                return true;
+            }
+        };
+    })());
+});
+
+
+Ext.EventManager = {
+
+    
+
+    
+    hasBoundOnReady: false,
+
+    
+    hasFiredReady: false,
+
+    
+    readyTimeout: null,
+
+    
+    hasOnReadyStateChange: false,
+
+    
+    readyEvent: new Ext.util.Event(),
+
+    
+    checkReadyState: function(){
+        var me = Ext.EventManager;
+
+        if(window.attachEvent){
+            
+            
+            if (window != top) {
+                return false;
+            }
+            try{
+                document.documentElement.doScroll('left');
+            }catch(e){
+                return false;
+            }
+            me.fireDocReady();
+            return true;
+        }
+        if (document.readyState == 'complete') {
+            me.fireDocReady();
+            return true;
+        }
+        me.readyTimeout = setTimeout(arguments.callee, 2);
+        return false;
+    },
+
+    
+    bindReadyEvent: function(){
+        var me = Ext.EventManager;
+        if (me.hasBoundOnReady) {
+            return;
+        }
+
+        if (document.addEventListener) {
+            document.addEventListener('DOMContentLoaded', me.fireDocReady, false);
+            
+            window.addEventListener('load', me.fireDocReady, false);
+        } else {
+            
+            if (!me.checkReadyState()) {
+                document.attachEvent('onreadystatechange', me.checkReadyState);
+                me.hasOnReadyStateChange = true;
+            }
+            
+            window.attachEvent('onload', me.fireDocReady, false);
+        }
+        me.hasBoundOnReady = true;
+    },
+
+    
+    fireDocReady: function(){
+        var me = Ext.EventManager;
+
+        
+        if (!me.hasFiredReady) {
+            me.hasFiredReady = true;
+
+            if (document.addEventListener) {
+                document.removeEventListener('DOMContentLoaded', me.fireDocReady, false);
+                window.removeEventListener('load', me.fireDocReady, false);
+            } else {
+                if (me.readyTimeout !== null) {
+                    clearTimeout(me.readyTimeout);
+                }
+                if (me.hasOnReadyStateChange) {
+                    document.detachEvent('onreadystatechange', me.checkReadyState);
+                }
+                window.detachEvent('onload', me.fireDocReady);
+            }
+            Ext.supports.init();
+        }
+        if (!Ext.isReady) {
+            Ext.isReady = true;
+            me.onWindowUnload();
+            me.readyEvent.fire();
+        }
+    },
+
+    
+    onDocumentReady: function(fn, scope, options){
+        options = options || {};
+        var me = Ext.EventManager,
+            readyEvent = me.readyEvent;
+
+        
+        options.single = true;
+
+        
+        if (Ext.isReady) {
+            readyEvent.addListener(fn, scope, options);
+            readyEvent.fire();
+        } else {
+            options.delay = options.delay || 1;
+            readyEvent.addListener(fn, scope, options);
+            me.bindReadyEvent();
+        }
+    },
+
+
+    
+
+    
+    stoppedMouseDownEvent: new Ext.util.Event(),
+
+    
+    propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/,
+
+    
+    getId : function(element) {
+        var skipGarbageCollection = false,
+            id;
+
+        element = Ext.getDom(element);
+
+        if (element === document || element === window) {
+            id = element === document ? Ext.documentId : Ext.windowId;
+        }
+        else {
+            id = Ext.id(element);
+        }
+        
+        if (element && (element.getElementById || element.navigator)) {
+            skipGarbageCollection = true;
+        }
+
+        if (!Ext.cache[id]){
+            Ext.Element.addToCache(new Ext.Element(element), id);
+            if (skipGarbageCollection) {
+                Ext.cache[id].skipGarbageCollection = true;
+            }
+        }
+        return id;
+    },
+
+    
+    prepareListenerConfig: function(element, config, isRemove){
+        var me = this,
+            propRe = me.propRe,
+            key, value, args;
+
+        
+        for (key in config) {
+            if (config.hasOwnProperty(key)) {
+                
+                if (!propRe.test(key)) {
+                    value = config[key];
+                    
+                    
+                    if (Ext.isFunction(value)) {
+                        
+                        args = [element, key, value, config.scope, config];
+                    } else {
+                        
+                        args = [element, key, value.fn, value.scope, value];
+                    }
+
+                    if (isRemove === true) {
+                        me.removeListener.apply(this, args);
+                    } else {
+                        me.addListener.apply(me, args);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    normalizeEvent: function(eventName, fn){
+        if (/mouseenter|mouseleave/.test(eventName) && !Ext.supports.MouseEnterLeave) {
+            if (fn) {
+                fn = Ext.Function.createInterceptor(fn, this.contains, this);
+            }
+            eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout';
+        } else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera){
+            eventName = 'DOMMouseScroll';
+        }
+        return {
+            eventName: eventName,
+            fn: fn
+        };
+    },
+
+    
+    contains: function(event){
+        var parent = event.browserEvent.currentTarget,
+            child = this.getRelatedTarget(event);
+
+        if (parent && parent.firstChild) {
+            while (child) {
+                if (child === parent) {
+                    return false;
+                }
+                child = child.parentNode;
+                if (child && (child.nodeType != 1)) {
+                    child = null;
+                }
+            }
+        }
+        return true;
+    },
+
+    
+    addListener: function(element, eventName, fn, scope, options){
+        
+        if (typeof eventName !== 'string') {
+            this.prepareListenerConfig(element, eventName);
+            return;
+        }
+
+        var dom = Ext.getDom(element),
+            bind,
+            wrap;
+
+
+        
+        options = options || {};
+
+        bind = this.normalizeEvent(eventName, fn);
+        wrap = this.createListenerWrap(dom, eventName, bind.fn, scope, options);
+
+
+        if (dom.attachEvent) {
+            dom.attachEvent('on' + bind.eventName, wrap);
+        } else {
+            dom.addEventListener(bind.eventName, wrap, options.capture || false);
+        }
+
+        if (dom == document && eventName == 'mousedown') {
+            this.stoppedMouseDownEvent.addListener(wrap);
+        }
+
+        
+        this.getEventListenerCache(dom, eventName).push({
+            fn: fn,
+            wrap: wrap,
+            scope: scope
+        });
+    },
+
+    
+    removeListener : function(element, eventName, fn, scope) {
+        
+        if (typeof eventName !== 'string') {
+            this.prepareListenerConfig(element, eventName, true);
+            return;
+        }
+
+        var dom = Ext.getDom(element),
+            cache = this.getEventListenerCache(dom, eventName),
+            bindName = this.normalizeEvent(eventName).eventName,
+            i = cache.length, j,
+            listener, wrap, tasks;
+
+
+        while (i--) {
+            listener = cache[i];
+
+            if (listener && (!fn || listener.fn == fn) && (!scope || listener.scope === scope)) {
+                wrap = listener.wrap;
+
+                
+                if (wrap.task) {
+                    clearTimeout(wrap.task);
+                    delete wrap.task;
+                }
+
+                
+                j = wrap.tasks && wrap.tasks.length;
+                if (j) {
+                    while (j--) {
+                        clearTimeout(wrap.tasks[j]);
+                    }
+                    delete wrap.tasks;
+                }
+
+                if (dom.detachEvent) {
+                    dom.detachEvent('on' + bindName, wrap);
+                } else {
+                    dom.removeEventListener(bindName, wrap, false);
+                }
+
+                if (wrap && dom == document && eventName == 'mousedown') {
+                    this.stoppedMouseDownEvent.removeListener(wrap);
+                }
+
+                
+                Ext.Array.erase(cache, i, 1);
+            }
+        }
+    },
+
+    
+    removeAll : function(element){
+        var dom = Ext.getDom(element),
+            cache, ev;
+        if (!dom) {
+            return;
+        }
+        cache = this.getElementEventCache(dom);
+
+        for (ev in cache) {
+            if (cache.hasOwnProperty(ev)) {
+                this.removeListener(dom, ev);
+            }
+        }
+        Ext.cache[dom.id].events = {};
+    },
+
+    
+    purgeElement : function(element, eventName) {
+        var dom = Ext.getDom(element),
+            i = 0, len;
+
+        if(eventName) {
+            this.removeListener(dom, eventName);
+        }
+        else {
+            this.removeAll(dom);
+        }
+
+        if(dom && dom.childNodes) {
+            for(len = element.childNodes.length; i < len; i++) {
+                this.purgeElement(element.childNodes[i], eventName);
+            }
+        }
+    },
+
+    
+    createListenerWrap : function(dom, ename, fn, scope, options) {
+        options = options || {};
+
+        var f, gen;
+
+        return function wrap(e, args) {
+            
+            if (!gen) {
+                f = ['if(!Ext) {return;}'];
+
+                if(options.buffer || options.delay || options.freezeEvent) {
+                    f.push('e = new Ext.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');');
+                } else {
+                    f.push('e = Ext.EventObject.setEvent(e);');
+                }
+
+                if (options.delegate) {
+                    f.push('var t = e.getTarget("' + options.delegate + '", this);');
+                    f.push('if(!t) {return;}');
+                } else {
+                    f.push('var t = e.target;');
+                }
+
+                if (options.target) {
+                    f.push('if(e.target !== options.target) {return;}');
+                }
+
+                if(options.stopEvent) {
+                    f.push('e.stopEvent();');
+                } else {
+                    if(options.preventDefault) {
+                        f.push('e.preventDefault();');
+                    }
+                    if(options.stopPropagation) {
+                        f.push('e.stopPropagation();');
+                    }
+                }
+
+                if(options.normalized === false) {
+                    f.push('e = e.browserEvent;');
+                }
+
+                if(options.buffer) {
+                    f.push('(wrap.task && clearTimeout(wrap.task));');
+                    f.push('wrap.task = setTimeout(function(){');
+                }
+
+                if(options.delay) {
+                    f.push('wrap.tasks = wrap.tasks || [];');
+                    f.push('wrap.tasks.push(setTimeout(function(){');
+                }
+
+                
+                f.push('fn.call(scope || dom, e, t, options);');
+
+                if(options.single) {
+                    f.push('Ext.EventManager.removeListener(dom, ename, fn, scope);');
+                }
+
+                if(options.delay) {
+                    f.push('}, ' + options.delay + '));');
+                }
+
+                if(options.buffer) {
+                    f.push('}, ' + options.buffer + ');');
+                }
+
+                gen = Ext.functionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', f.join('\n'));
+            }
+
+            gen.call(dom, e, options, fn, scope, ename, dom, wrap, args);
+        };
+    },
+
+    
+    getEventListenerCache : function(element, eventName) {
+        if (!element) {
+            return [];
+        }
+
+        var eventCache = this.getElementEventCache(element);
+        return eventCache[eventName] || (eventCache[eventName] = []);
+    },
+
+    
+    getElementEventCache : function(element) {
+        if (!element) {
+            return {};
+        }
+        var elementCache = Ext.cache[this.getId(element)];
+        return elementCache.events || (elementCache.events = {});
+    },
+
+    
+    mouseLeaveRe: /(mouseout|mouseleave)/,
+    mouseEnterRe: /(mouseover|mouseenter)/,
+
+    
+    stopEvent: function(event) {
+        this.stopPropagation(event);
+        this.preventDefault(event);
+    },
+
+    
+    stopPropagation: function(event) {
+        event = event.browserEvent || event;
+        if (event.stopPropagation) {
+            event.stopPropagation();
+        } else {
+            event.cancelBubble = true;
+        }
+    },
+
+    
+    preventDefault: function(event) {
+        event = event.browserEvent || event;
+        if (event.preventDefault) {
+            event.preventDefault();
+        } else {
+            event.returnValue = false;
+            
+            try {
+              
+              if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
+                  event.keyCode = -1;
+              }
+            } catch (e) {
+                
+            }
+        }
+    },
+
+    
+    getRelatedTarget: function(event) {
+        event = event.browserEvent || event;
+        var target = event.relatedTarget;
+        if (!target) {
+            if (this.mouseLeaveRe.test(event.type)) {
+                target = event.toElement;
+            } else if (this.mouseEnterRe.test(event.type)) {
+                target = event.fromElement;
+            }
+        }
+        return this.resolveTextNode(target);
+    },
+
+    
+    getPageX: function(event) {
+        return this.getXY(event)[0];
+    },
+
+    
+    getPageY: function(event) {
+        return this.getXY(event)[1];
+    },
+
+    
+    getPageXY: function(event) {
+        event = event.browserEvent || event;
+        var x = event.pageX,
+            y = event.pageY,
+            doc = document.documentElement,
+            body = document.body;
+
+        
+        if (!x && x !== 0) {
+            x = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+            y = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
+        }
+        return [x, y];
+    },
+
+    
+    getTarget: function(event) {
+        event = event.browserEvent || event;
+        return this.resolveTextNode(event.target || event.srcElement);
+    },
+
+    
+    
+    resolveTextNode: Ext.isGecko ?
+        function(node) {
+            if (!node) {
+                return;
+            }
+            
+            var s = HTMLElement.prototype.toString.call(node);
+            if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]') {
+                return;
+            }
+                return node.nodeType == 3 ? node.parentNode: node;
+            }: function(node) {
+                return node && node.nodeType == 3 ? node.parentNode: node;
+            },
+
+    
+
+    
+    curWidth: 0,
+    curHeight: 0,
+
+    
+    onWindowResize: function(fn, scope, options){
+        var resize = this.resizeEvent;
+        if(!resize){
+            this.resizeEvent = resize = new Ext.util.Event();
+            this.on(window, 'resize', this.fireResize, this, {buffer: 100});
+        }
+        resize.addListener(fn, scope, options);
+    },
+
+    
+    fireResize: function(){
+        var me = this,
+            w = Ext.Element.getViewWidth(),
+            h = Ext.Element.getViewHeight();
+
+         
+         if(me.curHeight != h || me.curWidth != w){
+             me.curHeight = h;
+             me.curWidth = w;
+             me.resizeEvent.fire(w, h);
+         }
+    },
+
+    
+    removeResizeListener: function(fn, scope){
+        if (this.resizeEvent) {
+            this.resizeEvent.removeListener(fn, scope);
+        }
+    },
+
+    onWindowUnload: function() {
+        var unload = this.unloadEvent;
+        if (!unload) {
+            this.unloadEvent = unload = new Ext.util.Event();
+            this.addListener(window, 'unload', this.fireUnload, this);
+        }
+    },
+
+    
+    fireUnload: function() {
+        
+        try {
+            this.removeUnloadListener();
+            
+            if (Ext.isGecko3) {
+                var gridviews = Ext.ComponentQuery.query('gridview'),
+                    i = 0,
+                    ln = gridviews.length;
+                for (; i < ln; i++) {
+                    gridviews[i].scrollToTop();
+                }
+            }
+            
+            var el,
+                cache = Ext.cache;
+            for (el in cache) {
+                if (cache.hasOwnProperty(el)) {
+                    Ext.EventManager.removeAll(el);
+                }
+            }
+        } catch(e) {
+        }
+    },
+
+    
+    removeUnloadListener: function(){
+        if (this.unloadEvent) {
+            this.removeListener(window, 'unload', this.fireUnload);
+        }
+    },
+
+    
+    useKeyDown: Ext.isWebKit ?
+                   parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 :
+                   !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera),
+
+    
+    getKeyEvent: function(){
+        return this.useKeyDown ? 'keydown' : 'keypress';
+    }
+};
+
+
+Ext.onReady = function(fn, scope, options) {
+    Ext.Loader.onReady(fn, scope, true, options);
+};
+
+
+Ext.onDocumentReady = Ext.EventManager.onDocumentReady;
+
+
+Ext.EventManager.on = Ext.EventManager.addListener;
+
+
+Ext.EventManager.un = Ext.EventManager.removeListener;
+
+(function(){
+    var initExtCss = function() {
+        
+        var bd = document.body || document.getElementsByTagName('body')[0],
+            baseCSSPrefix = Ext.baseCSSPrefix,
+            cls = [baseCSSPrefix + 'body'],
+            htmlCls = [],
+            html;
+
+        if (!bd) {
+            return false;
+        }
+
+        html = bd.parentNode;
+
+        function add (c) {
+            cls.push(baseCSSPrefix + c);
+        }
+
+        
+        if (Ext.isIE) {
+            add('ie');
+
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            if (Ext.isIE6) {
+                add('ie6');
+            } else { 
+                add('ie7p');
+
+                if (Ext.isIE7) {
+                    add('ie7');
+                } else {
+                    add('ie8p');
+
+                    if (Ext.isIE8) {
+                        add('ie8');
+                    } else {
+                        add('ie9p');
+
+                        if (Ext.isIE9) {
+                            add('ie9');
+                        }
+                    }
+                }
+            }
+
+            if (Ext.isIE6 || Ext.isIE7) {
+                add('ie7m');
+            }
+            if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
+                add('ie8m');
+            }
+            if (Ext.isIE7 || Ext.isIE8) {
+                add('ie78');
+            }
+        }
+        if (Ext.isGecko) {
+            add('gecko');
+            if (Ext.isGecko3) {
+                add('gecko3');
+            }
+            if (Ext.isGecko4) {
+                add('gecko4');
+            }
+            if (Ext.isGecko5) {
+                add('gecko5');
+            }
+        }
+        if (Ext.isOpera) {
+            add('opera');
+        }
+        if (Ext.isWebKit) {
+            add('webkit');
+        }
+        if (Ext.isSafari) {
+            add('safari');
+            if (Ext.isSafari2) {
+                add('safari2');
+            }
+            if (Ext.isSafari3) {
+                add('safari3');
+            }
+            if (Ext.isSafari4) {
+                add('safari4');
+            }
+            if (Ext.isSafari5) {
+                add('safari5');
+            }
+        }
+        if (Ext.isChrome) {
+            add('chrome');
+        }
+        if (Ext.isMac) {
+            add('mac');
+        }
+        if (Ext.isLinux) {
+            add('linux');
+        }
+        if (!Ext.supports.CSS3BorderRadius) {
+            add('nbr');
+        }
+        if (!Ext.supports.CSS3LinearGradient) {
+            add('nlg');
+        }
+        if (!Ext.scopeResetCSS) {
+            add('reset');
+        }
+
+        
+        if (html) {
+            if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
+                Ext.isBorderBox = false;
+            }
+            else {
+                Ext.isBorderBox = true;
+            }
+
+            htmlCls.push(baseCSSPrefix + (Ext.isBorderBox ? 'border-box' : 'strict'));
+            if (!Ext.isStrict) {
+                htmlCls.push(baseCSSPrefix + 'quirks');
+            }
+            Ext.fly(html, '_internal').addCls(htmlCls);
+        }
+
+        Ext.fly(bd, '_internal').addCls(cls);
+        return true;
+    };
+
+    Ext.onReady(initExtCss);
+})();
+
+
+Ext.define('Ext.EventObjectImpl', {
+    uses: ['Ext.util.Point'],
+
+    
+    BACKSPACE: 8,
+    
+    TAB: 9,
+    
+    NUM_CENTER: 12,
+    
+    ENTER: 13,
+    
+    RETURN: 13,
+    
+    SHIFT: 16,
+    
+    CTRL: 17,
+    
+    ALT: 18,
+    
+    PAUSE: 19,
+    
+    CAPS_LOCK: 20,
+    
+    ESC: 27,
+    
+    SPACE: 32,
+    
+    PAGE_UP: 33,
+    
+    PAGE_DOWN: 34,
+    
+    END: 35,
+    
+    HOME: 36,
+    
+    LEFT: 37,
+    
+    UP: 38,
+    
+    RIGHT: 39,
+    
+    DOWN: 40,
+    
+    PRINT_SCREEN: 44,
+    
+    INSERT: 45,
+    
+    DELETE: 46,
+    
+    ZERO: 48,
+    
+    ONE: 49,
+    
+    TWO: 50,
+    
+    THREE: 51,
+    
+    FOUR: 52,
+    
+    FIVE: 53,
+    
+    SIX: 54,
+    
+    SEVEN: 55,
+    
+    EIGHT: 56,
+    
+    NINE: 57,
+    
+    A: 65,
+    
+    B: 66,
+    
+    C: 67,
+    
+    D: 68,
+    
+    E: 69,
+    
+    F: 70,
+    
+    G: 71,
+    
+    H: 72,
+    
+    I: 73,
+    
+    J: 74,
+    
+    K: 75,
+    
+    L: 76,
+    
+    M: 77,
+    
+    N: 78,
+    
+    O: 79,
+    
+    P: 80,
+    
+    Q: 81,
+    
+    R: 82,
+    
+    S: 83,
+    
+    T: 84,
+    
+    U: 85,
+    
+    V: 86,
+    
+    W: 87,
+    
+    X: 88,
+    
+    Y: 89,
+    
+    Z: 90,
+    
+    CONTEXT_MENU: 93,
+    
+    NUM_ZERO: 96,
+    
+    NUM_ONE: 97,
+    
+    NUM_TWO: 98,
+    
+    NUM_THREE: 99,
+    
+    NUM_FOUR: 100,
+    
+    NUM_FIVE: 101,
+    
+    NUM_SIX: 102,
+    
+    NUM_SEVEN: 103,
+    
+    NUM_EIGHT: 104,
+    
+    NUM_NINE: 105,
+    
+    NUM_MULTIPLY: 106,
+    
+    NUM_PLUS: 107,
+    
+    NUM_MINUS: 109,
+    
+    NUM_PERIOD: 110,
+    
+    NUM_DIVISION: 111,
+    
+    F1: 112,
+    
+    F2: 113,
+    
+    F3: 114,
+    
+    F4: 115,
+    
+    F5: 116,
+    
+    F6: 117,
+    
+    F7: 118,
+    
+    F8: 119,
+    
+    F9: 120,
+    
+    F10: 121,
+    
+    F11: 122,
+    
+    F12: 123,
+    
+    WHEEL_SCALE: (function () {
+        var scale;
+
+        if (Ext.isGecko) {
+            
+            scale = 3;
+        } else if (Ext.isMac) {
+            
+            
+            
+
+            if (Ext.isSafari && Ext.webKitVersion >= 532.0) {
+                
+                
+                
+                
+                
+                
+                scale = 120;
+            } else {
+                
+                
+                scale = 12;
+            }
+
+            
+            
+            
+            
+            scale *= 3;
+        } else {
+            
+            scale = 120;
+        }
+
+        return scale;
+    })(),
+
+    
+    clickRe: /(dbl)?click/,
+    
+    safariKeys: {
+        3: 13, 
+        63234: 37, 
+        63235: 39, 
+        63232: 38, 
+        63233: 40, 
+        63276: 33, 
+        63277: 34, 
+        63272: 46, 
+        63273: 36, 
+        63275: 35 
+    },
+    
+    btnMap: Ext.isIE ? {
+        1: 0,
+        4: 1,
+        2: 2
+    } : {
+        0: 0,
+        1: 1,
+        2: 2
+    },
+
+    constructor: function(event, freezeEvent){
+        if (event) {
+            this.setEvent(event.browserEvent || event, freezeEvent);
+        }
+    },
+
+    setEvent: function(event, freezeEvent){
+        var me = this, button, options;
+
+        if (event == me || (event && event.browserEvent)) { 
+            return event;
+        }
+        me.browserEvent = event;
+        if (event) {
+            
+            button = event.button ? me.btnMap[event.button] : (event.which ? event.which - 1 : -1);
+            if (me.clickRe.test(event.type) && button == -1) {
+                button = 0;
+            }
+            options = {
+                type: event.type,
+                button: button,
+                shiftKey: event.shiftKey,
+                
+                ctrlKey: event.ctrlKey || event.metaKey || false,
+                altKey: event.altKey,
+                
+                keyCode: event.keyCode,
+                charCode: event.charCode,
+                
+                target: Ext.EventManager.getTarget(event),
+                relatedTarget: Ext.EventManager.getRelatedTarget(event),
+                currentTarget: event.currentTarget,
+                xy: (freezeEvent ? me.getXY() : null)
+            };
+        } else {
+            options = {
+                button: -1,
+                shiftKey: false,
+                ctrlKey: false,
+                altKey: false,
+                keyCode: 0,
+                charCode: 0,
+                target: null,
+                xy: [0, 0]
+            };
+        }
+        Ext.apply(me, options);
+        return me;
+    },
+
+    
+    stopEvent: function(){
+        this.stopPropagation();
+        this.preventDefault();
+    },
+
+    
+    preventDefault: function(){
+        if (this.browserEvent) {
+            Ext.EventManager.preventDefault(this.browserEvent);
+        }
+    },
+
+    
+    stopPropagation: function(){
+        var browserEvent = this.browserEvent;
+
+        if (browserEvent) {
+            if (browserEvent.type == 'mousedown') {
+                Ext.EventManager.stoppedMouseDownEvent.fire(this);
+            }
+            Ext.EventManager.stopPropagation(browserEvent);
+        }
+    },
+
+    
+    getCharCode: function(){
+        return this.charCode || this.keyCode;
+    },
+
+    
+    getKey: function(){
+        return this.normalizeKey(this.keyCode || this.charCode);
+    },
+
+    
+    normalizeKey: function(key){
+        
+        return Ext.isWebKit ? (this.safariKeys[key] || key) : key;
+    },
+
+    
+    getPageX: function(){
+        return this.getX();
+    },
+
+    
+    getPageY: function(){
+        return this.getY();
+    },
+
+    
+    getX: function() {
+        return this.getXY()[0];
+    },
+
+    
+    getY: function() {
+        return this.getXY()[1];
+    },
+
+    
+    getXY: function() {
+        if (!this.xy) {
+            
+            this.xy = Ext.EventManager.getPageXY(this.browserEvent);
+        }
+        return this.xy;
+    },
+
+    
+    getTarget : function(selector, maxDepth, returnEl){
+        if (selector) {
+            return Ext.fly(this.target).findParent(selector, maxDepth, returnEl);
+        }
+        return returnEl ? Ext.get(this.target) : this.target;
+    },
+
+    
+    getRelatedTarget : function(selector, maxDepth, returnEl){
+        if (selector) {
+            return Ext.fly(this.relatedTarget).findParent(selector, maxDepth, returnEl);
+        }
+        return returnEl ? Ext.get(this.relatedTarget) : this.relatedTarget;
+    },
+
+    
+    correctWheelDelta : function (delta) {
+        var scale = this.WHEEL_SCALE,
+            ret = Math.round(delta / scale);
+
+        if (!ret && delta) {
+            ret = (delta < 0) ? -1 : 1; 
+        }
+
+        return ret;
+    },
+
+    
+    getWheelDeltas : function () {
+        var me = this,
+            event = me.browserEvent,
+            dx = 0, dy = 0; 
+
+        if (Ext.isDefined(event.wheelDeltaX)) { 
+            dx = event.wheelDeltaX;
+            dy = event.wheelDeltaY;
+        } else if (event.wheelDelta) { 
+            dy = event.wheelDelta;
+        } else if (event.detail) { 
+            dy = -event.detail; 
+
+            
+            
+            if (dy > 100) {
+                dy = 3;
+            } else if (dy < -100) {
+                dy = -3;
+            }
+
+            
+            
+            if (Ext.isDefined(event.axis) && event.axis === event.HORIZONTAL_AXIS) {
+                dx = dy;
+                dy = 0;
+            }
+        }
+
+        return {
+            x: me.correctWheelDelta(dx),
+            y: me.correctWheelDelta(dy)
+        };
+    },
+
+    
+    getWheelDelta : function(){
+        var deltas = this.getWheelDeltas();
+
+        return deltas.y;
+    },
+
+    
+    within : function(el, related, allowEl){
+        if(el){
+            var t = related ? this.getRelatedTarget() : this.getTarget(),
+                result;
+
+            if (t) {
+                result = Ext.fly(el).contains(t);
+                if (!result && allowEl) {
+                    result = t == Ext.getDom(el);
+                }
+                return result;
+            }
+        }
+        return false;
+    },
+
+    
+    isNavKeyPress : function(){
+        var me = this,
+            k = this.normalizeKey(me.keyCode);
+
+       return (k >= 33 && k <= 40) ||  
+       k == me.RETURN ||
+       k == me.TAB ||
+       k == me.ESC;
+    },
+
+    
+    isSpecialKey : function(){
+        var k = this.normalizeKey(this.keyCode);
+        return (this.type == 'keypress' && this.ctrlKey) ||
+        this.isNavKeyPress() ||
+        (k == this.BACKSPACE) || 
+        (k >= 16 && k <= 20) || 
+        (k >= 44 && k <= 46);   
+    },
+
+    
+    getPoint : function(){
+        var xy = this.getXY();
+        return Ext.create('Ext.util.Point', xy[0], xy[1]);
+    },
+
+   
+    hasModifier : function(){
+        return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey;
+    },
+
+    
+    injectEvent: function () {
+        var API,
+            dispatchers = {}; 
+
+        
+
+        
+        
+
+        if (!Ext.isIE && document.createEvent) { 
+            API = {
+                createHtmlEvent: function (doc, type, bubbles, cancelable) {
+                    var event = doc.createEvent('HTMLEvents');
+
+                    event.initEvent(type, bubbles, cancelable);
+                    return event;
+                },
+
+                createMouseEvent: function (doc, type, bubbles, cancelable, detail,
+                                            clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
+                                            button, relatedTarget) {
+                    var event = doc.createEvent('MouseEvents'),
+                        view = doc.defaultView || window;
+
+                    if (event.initMouseEvent) {
+                        event.initMouseEvent(type, bubbles, cancelable, view, detail,
+                                    clientX, clientY, clientX, clientY, ctrlKey, altKey,
+                                    shiftKey, metaKey, button, relatedTarget);
+                    } else { 
+                        event = doc.createEvent('UIEvents');
+                        event.initEvent(type, bubbles, cancelable);
+                        event.view = view;
+                        event.detail = detail;
+                        event.screenX = clientX;
+                        event.screenY = clientY;
+                        event.clientX = clientX;
+                        event.clientY = clientY;
+                        event.ctrlKey = ctrlKey;
+                        event.altKey = altKey;
+                        event.metaKey = metaKey;
+                        event.shiftKey = shiftKey;
+                        event.button = button;
+                        event.relatedTarget = relatedTarget;
+                    }
+
+                    return event;
+                },
+
+                createUIEvent: function (doc, type, bubbles, cancelable, detail) {
+                    var event = doc.createEvent('UIEvents'),
+                        view = doc.defaultView || window;
+
+                    event.initUIEvent(type, bubbles, cancelable, view, detail);
+                    return event;
+                },
+
+                fireEvent: function (target, type, event) {
+                    target.dispatchEvent(event);
+                },
+
+                fixTarget: function (target) {
+                    
+                    if (target == window && !target.dispatchEvent) {
+                        return document;
+                    }
+
+                    return target;
+                }
+            };
+        } else if (document.createEventObject) { 
+            var crazyIEButtons = { 0: 1, 1: 4, 2: 2 };
+
+            API = {
+                createHtmlEvent: function (doc, type, bubbles, cancelable) {
+                    var event = doc.createEventObject();
+                    event.bubbles = bubbles;
+                    event.cancelable = cancelable;
+                    return event;
+                },
+
+                createMouseEvent: function (doc, type, bubbles, cancelable, detail,
+                                            clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
+                                            button, relatedTarget) {
+                    var event = doc.createEventObject();
+                    event.bubbles = bubbles;
+                    event.cancelable = cancelable;
+                    event.detail = detail;
+                    event.screenX = clientX;
+                    event.screenY = clientY;
+                    event.clientX = clientX;
+                    event.clientY = clientY;
+                    event.ctrlKey = ctrlKey;
+                    event.altKey = altKey;
+                    event.shiftKey = shiftKey;
+                    event.metaKey = metaKey;
+                    event.button = crazyIEButtons[button] || button;
+                    event.relatedTarget = relatedTarget; 
+                    return event;
+                },
+
+                createUIEvent: function (doc, type, bubbles, cancelable, detail) {
+                    var event = doc.createEventObject();
+                    event.bubbles = bubbles;
+                    event.cancelable = cancelable;
+                    return event;
+                },
+
+                fireEvent: function (target, type, event) {
+                    target.fireEvent('on' + type, event);
+                },
+
+                fixTarget: function (target) {
+                    if (target == document) {
+                        
+                        
+                        return document.documentElement;
+                    }
+
+                    return target;
+                }
+            };
+        }
+
+        
+        
+
+        Ext.Object.each({
+                load:   [false, false],
+                unload: [false, false],
+                select: [true, false],
+                change: [true, false],
+                submit: [true, true],
+                reset:  [true, false],
+                resize: [true, false],
+                scroll: [true, false]
+            },
+            function (name, value) {
+                var bubbles = value[0], cancelable = value[1];
+                dispatchers[name] = function (targetEl, srcEvent) {
+                    var e = API.createHtmlEvent(name, bubbles, cancelable);
+                    API.fireEvent(targetEl, name, e);
+                };
+            });
+
+        
+        
+
+        function createMouseEventDispatcher (type, detail) {
+            var cancelable = (type != 'mousemove');
+            return function (targetEl, srcEvent) {
+                var xy = srcEvent.getXY(),
+                    e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable,
+                                detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey,
+                                srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button,
+                                srcEvent.relatedTarget);
+                API.fireEvent(targetEl, type, e);
+            };
+        }
+
+        Ext.each(['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
+            function (eventName) {
+                dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);
+            });
+
+        
+        
+
+        Ext.Object.each({
+                focusin:  [true, false],
+                focusout: [true, false],
+                activate: [true, true],
+                focus:    [false, false],
+                blur:     [false, false]
+            },
+            function (name, value) {
+                var bubbles = value[0], cancelable = value[1];
+                dispatchers[name] = function (targetEl, srcEvent) {
+                    var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);
+                    API.fireEvent(targetEl, name, e);
+                };
+            });
+
+        
+        if (!API) {
+            
+
+            dispatchers = {}; 
+
+            API = {
+                fixTarget: function (t) {
+                    return t;
+                }
+            };
+        }
+
+        function cannotInject (target, srcEvent) {
+        }
+
+        return function (target) {
+            var me = this,
+                dispatcher = dispatchers[me.type] || cannotInject,
+                t = target ? (target.dom || target) : me.getTarget();
+
+            t = API.fixTarget(t);
+            dispatcher(t, me);
+        };
+    }() 
+
+}, function() {
+
+Ext.EventObject = new Ext.EventObjectImpl();
+
+});
+
+
+
+(function(){
+    var doc = document,
+        activeElement = null,
+        isCSS1 = doc.compatMode == "CSS1Compat",
+        ELEMENT = Ext.Element,
+        fly = function(el){
+            if (!_fly) {
+                _fly = new Ext.Element.Flyweight();
+            }
+            _fly.dom = el;
+            return _fly;
+        }, _fly;
+
+    
+    
+    
+    if (!('activeElement' in doc) && doc.addEventListener) {
+        doc.addEventListener('focus',
+            function (ev) {
+                if (ev && ev.target) {
+                    activeElement = (ev.target == doc) ? null : ev.target;
+                }
+            }, true);
+    }
+
+    
+    function makeSelectionRestoreFn (activeEl, start, end) {
+        return function () {
+            activeEl.selectionStart = start;
+            activeEl.selectionEnd = end;
+        };
+    }
+
+    Ext.apply(ELEMENT, {
+        isAncestor : function(p, c) {
+            var ret = false;
+
+            p = Ext.getDom(p);
+            c = Ext.getDom(c);
+            if (p && c) {
+                if (p.contains) {
+                    return p.contains(c);
+                } else if (p.compareDocumentPosition) {
+                    return !!(p.compareDocumentPosition(c) & 16);
+                } else {
+                    while ((c = c.parentNode)) {
+                        ret = c == p || ret;
+                    }
+                }
+            }
+            return ret;
+        },
+
+        
+        getActiveElement: function () {
+            return doc.activeElement || activeElement;
+        },
+
+        
+        getRightMarginFixCleaner: function (target) {
+            var supports = Ext.supports,
+                hasInputBug = supports.DisplayChangeInputSelectionBug,
+                hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug;
+
+            if (hasInputBug || hasTextAreaBug) {
+                var activeEl = doc.activeElement || activeElement, 
+                    tag = activeEl && activeEl.tagName,
+                    start,
+                    end;
+
+                if ((hasTextAreaBug && tag == 'TEXTAREA') ||
+                    (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) {
+                    if (ELEMENT.isAncestor(target, activeEl)) {
+                        start = activeEl.selectionStart;
+                        end = activeEl.selectionEnd;
+
+                        if (Ext.isNumber(start) && Ext.isNumber(end)) { 
+                            
+                            
+                            
+                            
+                            return makeSelectionRestoreFn(activeEl, start, end);
+                        }
+                    }
+                }
+            }
+
+            return Ext.emptyFn; 
+        },
+
+        getViewWidth : function(full) {
+            return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
+        },
+
+        getViewHeight : function(full) {
+            return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
+        },
+
+        getDocumentHeight: function() {
+            return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
+        },
+
+        getDocumentWidth: function() {
+            return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
+        },
+
+        getViewportHeight: function(){
+            return Ext.isIE ?
+                   (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
+                   self.innerHeight;
+        },
+
+        getViewportWidth : function() {
+            return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
+                   Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
+        },
+
+        getY : function(el) {
+            return ELEMENT.getXY(el)[1];
+        },
+
+        getX : function(el) {
+            return ELEMENT.getXY(el)[0];
+        },
+
+        getOffsetParent: function (el) {
+            el = Ext.getDom(el);
+            try {
+                
+                return el.offsetParent;
+            } catch (e) {
+                var body = document.body; 
+                return (el == body) ? null : body;
+            }
+        },
+
+        getXY : function(el) {
+            var p,
+                pe,
+                b,
+                bt,
+                bl,
+                dbd,
+                x = 0,
+                y = 0,
+                scroll,
+                hasAbsolute,
+                bd = (doc.body || doc.documentElement),
+                ret;
+
+            el = Ext.getDom(el);
+
+            if(el != bd){
+                hasAbsolute = fly(el).isStyle("position", "absolute");
+
+                if (el.getBoundingClientRect) {
+                    try {
+                        b = el.getBoundingClientRect();
+                        scroll = fly(document).getScroll();
+                        ret = [ Math.round(b.left + scroll.left), Math.round(b.top + scroll.top) ];
+                    } catch (e) {
+                        
+                    }
+                }
+
+                if (!ret) {
+                    for (p = el; p; p = ELEMENT.getOffsetParent(p)) {
+                        pe = fly(p);
+                        x += p.offsetLeft;
+                        y += p.offsetTop;
+
+                        hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
+
+                        if (Ext.isGecko) {
+                            y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
+                            x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
+
+                            if (p != el && !pe.isStyle('overflow','visible')) {
+                                x += bl;
+                                y += bt;
+                            }
+                        }
+                    }
+
+                    if (Ext.isSafari && hasAbsolute) {
+                        x -= bd.offsetLeft;
+                        y -= bd.offsetTop;
+                    }
+
+                    if (Ext.isGecko && !hasAbsolute) {
+                        dbd = fly(bd);
+                        x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
+                        y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
+                    }
+
+                    p = el.parentNode;
+                    while (p && p != bd) {
+                        if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
+                            x -= p.scrollLeft;
+                            y -= p.scrollTop;
+                        }
+                        p = p.parentNode;
+                    }
+                    ret = [x,y];
+                }
+            }
+            return ret || [0,0];
+        },
+
+        setXY : function(el, xy) {
+            (el = Ext.fly(el, '_setXY')).position();
+
+            var pts = el.translatePoints(xy),
+                style = el.dom.style,
+                pos;
+
+            for (pos in pts) {
+                if (!isNaN(pts[pos])) {
+                    style[pos] = pts[pos] + "px";
+                }
+            }
+        },
+
+        setX : function(el, x) {
+            ELEMENT.setXY(el, [x, false]);
+        },
+
+        setY : function(el, y) {
+            ELEMENT.setXY(el, [false, y]);
+        },
+
+        
+        serializeForm: function(form) {
+            var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
+                hasSubmit = false,
+                encoder = encodeURIComponent,
+                name,
+                data = '',
+                type,
+                hasValue;
+
+            Ext.each(fElements, function(element){
+                name = element.name;
+                type = element.type;
+
+                if (!element.disabled && name) {
+                    if (/select-(one|multiple)/i.test(type)) {
+                        Ext.each(element.options, function(opt){
+                            if (opt.selected) {
+                                hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified;
+                                data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text));
+                            }
+                        });
+                    } else if (!(/file|undefined|reset|button/i.test(type))) {
+                        if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) {
+                            data += encoder(name) + '=' + encoder(element.value) + '&';
+                            hasSubmit = /submit/i.test(type);
+                        }
+                    }
+                }
+            });
+            return data.substr(0, data.length - 1);
+        }
+    });
+})();
+
+
+
+Ext.Element.addMethods((function(){
+    var focusRe = /button|input|textarea|select|object/;
+    return {
+        
+        monitorMouseLeave: function(delay, handler, scope) {
+            var me = this,
+                timer,
+                listeners = {
+                    mouseleave: function(e) {
+                        timer = setTimeout(Ext.Function.bind(handler, scope||me, [e]), delay);
+                    },
+                    mouseenter: function() {
+                        clearTimeout(timer);
+                    },
+                    freezeEvent: true
+                };
+
+            me.on(listeners);
+            return listeners;
+        },
+
+        
+        swallowEvent : function(eventName, preventDefault) {
+            var me = this;
+            function fn(e) {
+                e.stopPropagation();
+                if (preventDefault) {
+                    e.preventDefault();
+                }
+            }
+
+            if (Ext.isArray(eventName)) {
+                Ext.each(eventName, function(e) {
+                     me.on(e, fn);
+                });
+                return me;
+            }
+            me.on(eventName, fn);
+            return me;
+        },
+
+        
+        relayEvent : function(eventName, observable) {
+            this.on(eventName, function(e) {
+                observable.fireEvent(eventName, e);
+            });
+        },
+
+        
+        clean : function(forceReclean) {
+            var me  = this,
+                dom = me.dom,
+                n   = dom.firstChild,
+                nx,
+                ni  = -1;
+    
+            if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
+                return me;
+            }
+
+            while (n) {
+                nx = n.nextSibling;
+                if (n.nodeType == 3) {
+                    
+                    if (!(/\S/.test(n.nodeValue))) {
+                        dom.removeChild(n);
+                    
+                    } else if (nx && nx.nodeType == 3) {
+                        n.appendData(Ext.String.trim(nx.data));
+                        dom.removeChild(nx);
+                        nx = n.nextSibling;
+                        n.nodeIndex = ++ni;
+                    }
+                } else {
+                    
+                    Ext.fly(n).clean();
+                    n.nodeIndex = ++ni;
+                }
+                n = nx;
+            }
+
+            Ext.Element.data(dom, 'isCleaned', true);
+            return me;
+        },
+
+        
+        load : function(options) {
+            this.getLoader().load(options);
+            return this;
+        },
+
+        
+        getLoader : function() {
+            var dom = this.dom,
+                data = Ext.Element.data,
+                loader = data(dom, 'loader');
+    
+            if (!loader) {
+                loader = Ext.create('Ext.ElementLoader', {
+                    target: this
+                });
+                data(dom, 'loader', loader);
+            }
+            return loader;
+        },
+
+        
+        update : function(html, loadScripts, callback) {
+            var me = this,
+                id,
+                dom,
+                interval;
+
+            if (!me.dom) {
+                return me;
+            }
+            html = html || '';
+            dom = me.dom;
+
+            if (loadScripts !== true) {
+                dom.innerHTML = html;
+                Ext.callback(callback, me);
+                return me;
+            }
+
+            id  = Ext.id();
+            html += '<span id="' + id + '"></span>';
+
+            interval = setInterval(function(){
+                if (!document.getElementById(id)) {
+                    return false;
+                }
+                clearInterval(interval);
+                var DOC    = document,
+                    hd     = DOC.getElementsByTagName("head")[0],
+                    re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
+                    srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
+                    typeRe = /\stype=([\'\"])(.*?)\1/i,
+                    match,
+                    attrs,
+                    srcMatch,
+                    typeMatch,
+                    el,
+                    s;
+
+                while ((match = re.exec(html))) {
+                    attrs = match[1];
+                    srcMatch = attrs ? attrs.match(srcRe) : false;
+                    if (srcMatch && srcMatch[2]) {
+                       s = DOC.createElement("script");
+                       s.src = srcMatch[2];
+                       typeMatch = attrs.match(typeRe);
+                       if (typeMatch && typeMatch[2]) {
+                           s.type = typeMatch[2];
+                       }
+                       hd.appendChild(s);
+                    } else if (match[2] && match[2].length > 0) {
+                        if (window.execScript) {
+                           window.execScript(match[2]);
+                        } else {
+                           window.eval(match[2]);
+                        }
+                    }
+                }
+
+                el = DOC.getElementById(id);
+                if (el) {
+                    Ext.removeNode(el);
+                }
+                Ext.callback(callback, me);
+            }, 20);
+            dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, '');
+            return me;
+        },
+
+        
+        removeAllListeners : function() {
+            this.removeAnchor();
+            Ext.EventManager.removeAll(this.dom);
+            return this;
+        },
+    
+        
+        getScopeParent: function(){
+            var parent = this.dom.parentNode;
+            return Ext.scopeResetCSS ? parent.parentNode : parent;
+        },
+
+        
+        createProxy : function(config, renderTo, matchBox) {
+            config = (typeof config == 'object') ? config : {tag : "div", cls: config};
+
+            var me = this,
+                proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
+                                   Ext.DomHelper.insertBefore(me.dom, config, true);
+
+            proxy.setVisibilityMode(Ext.Element.DISPLAY);
+            proxy.hide();
+            if (matchBox && me.setBox && me.getBox) { 
+               proxy.setBox(me.getBox());
+            }
+            return proxy;
+        },
+    
+        
+        focusable: function(){
+            var dom = this.dom,
+                nodeName = dom.nodeName.toLowerCase(),
+                canFocus = false,
+                hasTabIndex = !isNaN(dom.tabIndex);
+            
+            if (!dom.disabled) {
+                if (focusRe.test(nodeName)) {
+                    canFocus = true;
+                } else {
+                    canFocus = nodeName == 'a' ? dom.href || hasTabIndex : hasTabIndex;
+                }
+            }
+            return canFocus && this.isVisible(true);
+        }    
+    };
+})());
+Ext.Element.prototype.clearListeners = Ext.Element.prototype.removeAllListeners;
+
+
+Ext.Element.addMethods({
+    
+    getAnchorXY : function(anchor, local, s){
+        
+        
+        anchor = (anchor || "tl").toLowerCase();
+        s = s || {};
+
+        var me = this,
+            vp = me.dom == document.body || me.dom == document,
+            w = s.width || vp ? Ext.Element.getViewWidth() : me.getWidth(),
+            h = s.height || vp ? Ext.Element.getViewHeight() : me.getHeight(),
+            xy,
+            r = Math.round,
+            o = me.getXY(),
+            scroll = me.getScroll(),
+            extraX = vp ? scroll.left : !local ? o[0] : 0,
+            extraY = vp ? scroll.top : !local ? o[1] : 0,
+            hash = {
+                c  : [r(w * 0.5), r(h * 0.5)],
+                t  : [r(w * 0.5), 0],
+                l  : [0, r(h * 0.5)],
+                r  : [w, r(h * 0.5)],
+                b  : [r(w * 0.5), h],
+                tl : [0, 0],
+                bl : [0, h],
+                br : [w, h],
+                tr : [w, 0]
+            };
+
+        xy = hash[anchor];
+        return [xy[0] + extraX, xy[1] + extraY];
+    },
+
+    
+    anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
+        var me = this,
+            dom = me.dom,
+            scroll = !Ext.isEmpty(monitorScroll),
+            action = function(){
+                Ext.fly(dom).alignTo(el, alignment, offsets, animate);
+                Ext.callback(callback, Ext.fly(dom));
+            },
+            anchor = this.getAnchor();
+
+        
+        this.removeAnchor();
+        Ext.apply(anchor, {
+            fn: action,
+            scroll: scroll
+        });
+
+        Ext.EventManager.onWindowResize(action, null);
+
+        if(scroll){
+            Ext.EventManager.on(window, 'scroll', action, null,
+                {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
+        }
+        action.call(me); 
+        return me;
+    },
+
+    
+    removeAnchor : function(){
+        var me = this,
+            anchor = this.getAnchor();
+
+        if(anchor && anchor.fn){
+            Ext.EventManager.removeResizeListener(anchor.fn);
+            if(anchor.scroll){
+                Ext.EventManager.un(window, 'scroll', anchor.fn);
+            }
+            delete anchor.fn;
+        }
+        return me;
+    },
+
+    
+    getAnchor : function(){
+        var data = Ext.Element.data,
+            dom = this.dom;
+            if (!dom) {
+                return;
+            }
+            var anchor = data(dom, '_anchor');
+
+        if(!anchor){
+            anchor = data(dom, '_anchor', {});
+        }
+        return anchor;
+    },
+
+    getAlignVector: function(el, spec, offset) {
+        var me = this,
+            side = {t:"top", l:"left", r:"right", b: "bottom"},
+            thisRegion = me.getRegion(),
+            elRegion;
+
+        el = Ext.get(el);
+        if(!el || !el.dom){
+        }
+
+        elRegion = el.getRegion();
+    },
+
+    
+    getAlignToXY : function(el, p, o){
+        el = Ext.get(el);
+
+        if(!el || !el.dom){
+        }
+
+        o = o || [0,0];
+        p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();
+
+        var me = this,
+            d = me.dom,
+            a1,
+            a2,
+            x,
+            y,
+            
+            w,
+            h,
+            r,
+            dw = Ext.Element.getViewWidth() -10, 
+            dh = Ext.Element.getViewHeight()-10, 
+            p1y,
+            p1x,
+            p2y,
+            p2x,
+            swapY,
+            swapX,
+            doc = document,
+            docElement = doc.documentElement,
+            docBody = doc.body,
+            scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
+            scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
+            c = false, 
+            p1 = "",
+            p2 = "",
+            m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
+
+        if(!m){
+        }
+
+        p1 = m[1];
+        p2 = m[2];
+        c = !!m[3];
+
+        
+        
+        a1 = me.getAnchorXY(p1, true);
+        a2 = el.getAnchorXY(p2, false);
+
+        x = a2[0] - a1[0] + o[0];
+        y = a2[1] - a1[1] + o[1];
+
+        if(c){
+           w = me.getWidth();
+           h = me.getHeight();
+           r = el.getRegion();
+           
+           
+           
+           p1y = p1.charAt(0);
+           p1x = p1.charAt(p1.length-1);
+           p2y = p2.charAt(0);
+           p2x = p2.charAt(p2.length-1);
+           swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
+           swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
+
+
+           if (x + w > dw + scrollX) {
+                x = swapX ? r.left-w : dw+scrollX-w;
+           }
+           if (x < scrollX) {
+               x = swapX ? r.right : scrollX;
+           }
+           if (y + h > dh + scrollY) {
+                y = swapY ? r.top-h : dh+scrollY-h;
+            }
+           if (y < scrollY){
+               y = swapY ? r.bottom : scrollY;
+           }
+        }
+        return [x,y];
+    },
+
+    
+    alignTo : function(element, position, offsets, animate){
+        var me = this;
+        return me.setXY(me.getAlignToXY(element, position, offsets),
+                        me.anim && !!animate ? me.anim(animate) : false);
+    },
+
+    
+    adjustForConstraints : function(xy, parent) {
+        var vector = this.getConstrainVector(parent, xy);
+        if (vector) {
+            xy[0] += vector[0];
+            xy[1] += vector[1];
+        }
+        return xy;
+    },
+
+    
+    getConstrainVector: function(constrainTo, proposedPosition) {
+        if (!(constrainTo instanceof Ext.util.Region)) {
+            constrainTo = Ext.get(constrainTo).getViewRegion();
+        }
+        var thisRegion = this.getRegion(),
+            vector = [0, 0],
+            shadowSize = this.shadow && this.shadow.offset,
+            overflowed = false;
+
+        
+        if (proposedPosition) {
+            thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y);
+        }
+
+        
+        
+        if (shadowSize) {
+            constrainTo.adjust(0, -shadowSize, -shadowSize, shadowSize);
+        }
+
+        
+        if (thisRegion.right > constrainTo.right) {
+            overflowed = true;
+            vector[0] = (constrainTo.right - thisRegion.right);    
+        }
+        if (thisRegion.left + vector[0] < constrainTo.left) {
+            overflowed = true;
+            vector[0] = (constrainTo.left - thisRegion.left);      
+        }
+
+        
+        if (thisRegion.bottom > constrainTo.bottom) {
+            overflowed = true;
+            vector[1] = (constrainTo.bottom - thisRegion.bottom);  
+        }
+        if (thisRegion.top + vector[1] < constrainTo.top) {
+            overflowed = true;
+            vector[1] = (constrainTo.top - thisRegion.top);        
+        }
+        return overflowed ? vector : false;
+    },
+
+    
+    getCenterXY : function(){
+        return this.getAlignToXY(document, 'c-c');
+    },
+
+    
+    center : function(centerIn){
+        return this.alignTo(centerIn || document, 'c-c');
+    }
+});
+
+
+(function(){
+
+var ELEMENT = Ext.Element,
+    LEFT = "left",
+    RIGHT = "right",
+    TOP = "top",
+    BOTTOM = "bottom",
+    POSITION = "position",
+    STATIC = "static",
+    RELATIVE = "relative",
+    AUTO = "auto",
+    ZINDEX = "z-index";
+
+Ext.override(Ext.Element, {
+    
+    getX : function(){
+        return ELEMENT.getX(this.dom);
+    },
+
+    
+    getY : function(){
+        return ELEMENT.getY(this.dom);
+    },
+
+    
+    getXY : function(){
+        return ELEMENT.getXY(this.dom);
+    },
+
+    
+    getOffsetsTo : function(el){
+        var o = this.getXY(),
+            e = Ext.fly(el, '_internal').getXY();
+        return [o[0]-e[0],o[1]-e[1]];
+    },
+
+    
+    setX : function(x, animate){
+        return this.setXY([x, this.getY()], animate);
+    },
+
+    
+    setY : function(y, animate){
+        return this.setXY([this.getX(), y], animate);
+    },
+
+    
+    setLeft : function(left){
+        this.setStyle(LEFT, this.addUnits(left));
+        return this;
+    },
+
+    
+    setTop : function(top){
+        this.setStyle(TOP, this.addUnits(top));
+        return this;
+    },
+
+    
+    setRight : function(right){
+        this.setStyle(RIGHT, this.addUnits(right));
+        return this;
+    },
+
+    
+    setBottom : function(bottom){
+        this.setStyle(BOTTOM, this.addUnits(bottom));
+        return this;
+    },
+
+    
+    setXY: function(pos, animate) {
+        var me = this;
+        if (!animate || !me.anim) {
+            ELEMENT.setXY(me.dom, pos);
+        }
+        else {
+            if (!Ext.isObject(animate)) {
+                animate = {};
+            }
+            me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
+        }
+        return me;
+    },
+
+    
+    setLocation : function(x, y, animate){
+        return this.setXY([x, y], animate);
+    },
+
+    
+    moveTo : function(x, y, animate){
+        return this.setXY([x, y], animate);
+    },
+
+    
+    getLeft : function(local){
+        return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
+    },
+
+    
+    getRight : function(local){
+        var me = this;
+        return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
+    },
+
+    
+    getTop : function(local) {
+        return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
+    },
+
+    
+    getBottom : function(local){
+        var me = this;
+        return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
+    },
+
+    
+    position : function(pos, zIndex, x, y) {
+        var me = this;
+
+        if (!pos && me.isStyle(POSITION, STATIC)){
+            me.setStyle(POSITION, RELATIVE);
+        } else if(pos) {
+            me.setStyle(POSITION, pos);
+        }
+        if (zIndex){
+            me.setStyle(ZINDEX, zIndex);
+        }
+        if (x || y) {
+            me.setXY([x || false, y || false]);
+        }
+    },
+
+    
+    clearPositioning : function(value){
+        value = value || '';
+        this.setStyle({
+            left : value,
+            right : value,
+            top : value,
+            bottom : value,
+            "z-index" : "",
+            position : STATIC
+        });
+        return this;
+    },
+
+    
+    getPositioning : function(){
+        var l = this.getStyle(LEFT);
+        var t = this.getStyle(TOP);
+        return {
+            "position" : this.getStyle(POSITION),
+            "left" : l,
+            "right" : l ? "" : this.getStyle(RIGHT),
+            "top" : t,
+            "bottom" : t ? "" : this.getStyle(BOTTOM),
+            "z-index" : this.getStyle(ZINDEX)
+        };
+    },
+
+    
+    setPositioning : function(pc){
+        var me = this,
+            style = me.dom.style;
+
+        me.setStyle(pc);
+
+        if(pc.right == AUTO){
+            style.right = "";
+        }
+        if(pc.bottom == AUTO){
+            style.bottom = "";
+        }
+
+        return me;
+    },
+
+    
+    translatePoints: function(x, y) {
+        if (Ext.isArray(x)) {
+             y = x[1];
+             x = x[0];
+        }
+        var me = this,
+            relative = me.isStyle(POSITION, RELATIVE),
+            o = me.getXY(),
+            left = parseInt(me.getStyle(LEFT), 10),
+            top = parseInt(me.getStyle(TOP), 10);
+
+        if (!Ext.isNumber(left)) {
+            left = relative ? 0 : me.dom.offsetLeft;
+        }
+        if (!Ext.isNumber(top)) {
+            top = relative ? 0 : me.dom.offsetTop;
+        }
+        left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
+        top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
+        return {
+            left: left,
+            top: top
+        };
+    },
+
+    
+    setBox: function(box, adjust, animate) {
+        var me = this,
+            w = box.width,
+            h = box.height;
+        if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
+            w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+            h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+        }
+        me.setBounds(box.x, box.y, w, h, animate);
+        return me;
+    },
+
+    
+    getBox: function(contentBox, local) {
+        var me = this,
+            xy,
+            left,
+            top,
+            getBorderWidth = me.getBorderWidth,
+            getPadding = me.getPadding,
+            l, r, t, b, w, h, bx;
+        if (!local) {
+            xy = me.getXY();
+        } else {
+            left = parseInt(me.getStyle("left"), 10) || 0;
+            top = parseInt(me.getStyle("top"), 10) || 0;
+            xy = [left, top];
+        }
+        w = me.getWidth();
+        h = me.getHeight();
+        if (!contentBox) {
+            bx = {
+                x: xy[0],
+                y: xy[1],
+                0: xy[0],
+                1: xy[1],
+                width: w,
+                height: h
+            };
+        } else {
+            l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
+            r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
+            t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
+            b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
+            bx = {
+                x: xy[0] + l,
+                y: xy[1] + t,
+                0: xy[0] + l,
+                1: xy[1] + t,
+                width: w - (l + r),
+                height: h - (t + b)
+            };
+        }
+        bx.right = bx.x + bx.width;
+        bx.bottom = bx.y + bx.height;
+        return bx;
+    },
+
+    
+    move: function(direction, distance, animate) {
+        var me = this,
+            xy = me.getXY(),
+            x = xy[0],
+            y = xy[1],
+            left = [x - distance, y],
+            right = [x + distance, y],
+            top = [x, y - distance],
+            bottom = [x, y + distance],
+            hash = {
+                l: left,
+                left: left,
+                r: right,
+                right: right,
+                t: top,
+                top: top,
+                up: top,
+                b: bottom,
+                bottom: bottom,
+                down: bottom
+            };
+
+        direction = direction.toLowerCase();
+        me.moveTo(hash[direction][0], hash[direction][1], animate);
+    },
+
+    
+    setLeftTop: function(left, top) {
+        var me = this,
+            style = me.dom.style;
+        style.left = me.addUnits(left);
+        style.top = me.addUnits(top);
+        return me;
+    },
+
+    
+    getRegion: function() {
+        return this.getPageBox(true);
+    },
+
+    
+    getViewRegion: function() {
+        var me = this,
+            isBody = me.dom === document.body,
+            scroll, pos, top, left, width, height;
+
+        
+        if (isBody) {
+            scroll = me.getScroll();
+            left = scroll.left;
+            top = scroll.top;
+            width = Ext.Element.getViewportWidth();
+            height = Ext.Element.getViewportHeight();
+        }
+        else {
+            pos = me.getXY();
+            left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
+            top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
+            width = me.getWidth(true);
+            height = me.getHeight(true);
+        }
+
+        return Ext.create('Ext.util.Region', top, left + width, top + height, left);
+    },
+
+    
+    getPageBox : function(getRegion) {
+        var me = this,
+            el = me.dom,
+            isDoc = el === document.body,
+            w = isDoc ? Ext.Element.getViewWidth()  : el.offsetWidth,
+            h = isDoc ? Ext.Element.getViewHeight() : el.offsetHeight,
+            xy = me.getXY(),
+            t = xy[1],
+            r = xy[0] + w,
+            b = xy[1] + h,
+            l = xy[0];
+
+        if (getRegion) {
+            return Ext.create('Ext.util.Region', t, r, b, l);
+        }
+        else {
+            return {
+                left: l,
+                top: t,
+                width: w,
+                height: h,
+                right: r,
+                bottom: b
+            };
+        }
+    },
+
+    
+    setBounds: function(x, y, width, height, animate) {
+        var me = this;
+        if (!animate || !me.anim) {
+            me.setSize(width, height);
+            me.setLocation(x, y);
+        } else {
+            if (!Ext.isObject(animate)) {
+                animate = {};
+            }
+            me.animate(Ext.applyIf({
+                to: {
+                    x: x,
+                    y: y,
+                    width: me.adjustWidth(width),
+                    height: me.adjustHeight(height)
+                }
+            }, animate));
+        }
+        return me;
+    },
+
+    
+    setRegion: function(region, animate) {
+        return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);
+    }
+});
+})();
+
+
+Ext.override(Ext.Element, {
+    
+    isScrollable : function(){
+        var dom = this.dom;
+        return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
+    },
+
+    
+    getScroll : function() {
+        var d = this.dom, 
+            doc = document,
+            body = doc.body,
+            docElement = doc.documentElement,
+            l,
+            t,
+            ret;
+
+        if (d == doc || d == body) {
+            if (Ext.isIE && Ext.isStrict) {
+                l = docElement.scrollLeft; 
+                t = docElement.scrollTop;
+            } else {
+                l = window.pageXOffset;
+                t = window.pageYOffset;
+            }
+            ret = {
+                left: l || (body ? body.scrollLeft : 0), 
+                top : t || (body ? body.scrollTop : 0)
+            };
+        } else {
+            ret = {
+                left: d.scrollLeft, 
+                top : d.scrollTop
+            };
+        }
+        
+        return ret;
+    },
+    
+    
+    scrollTo : function(side, value, animate) {
+        
+        var top = /top/i.test(side),
+            me = this,
+            dom = me.dom,
+            obj = {},
+            prop;
+        if (!animate || !me.anim) {
+            
+            prop = 'scroll' + (top ? 'Top' : 'Left');
+            dom[prop] = value;
+        }
+        else {
+            if (!Ext.isObject(animate)) {
+                animate = {};
+            }
+            obj['scroll' + (top ? 'Top' : 'Left')] = value;
+            me.animate(Ext.applyIf({
+                to: obj
+            }, animate));
+        }
+        return me;
+    },
+
+    
+    scrollIntoView : function(container, hscroll) {
+        container = Ext.getDom(container) || Ext.getBody().dom;
+        var el = this.dom,
+            offsets = this.getOffsetsTo(container),
+            
+            left = offsets[0] + container.scrollLeft,
+            top = offsets[1] + container.scrollTop,
+            bottom = top + el.offsetHeight,
+            right = left + el.offsetWidth,
+            
+            ctClientHeight = container.clientHeight,
+            ctScrollTop = parseInt(container.scrollTop, 10),
+            ctScrollLeft = parseInt(container.scrollLeft, 10),
+            ctBottom = ctScrollTop + ctClientHeight,
+            ctRight = ctScrollLeft + container.clientWidth;
+
+        if (el.offsetHeight > ctClientHeight || top < ctScrollTop) {
+            container.scrollTop = top;
+        } else if (bottom > ctBottom) {
+            container.scrollTop = bottom - ctClientHeight;
+        }
+        
+        container.scrollTop = container.scrollTop;
+
+        if (hscroll !== false) {
+            if (el.offsetWidth > container.clientWidth || left < ctScrollLeft) {
+                container.scrollLeft = left;
+            }
+            else if (right > ctRight) {
+                container.scrollLeft = right - container.clientWidth;
+            }
+            container.scrollLeft = container.scrollLeft;
+        }
+        return this;
+    },
+
+    
+    scrollChildIntoView : function(child, hscroll) {
+        Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
+    },
+
+    
+     scroll : function(direction, distance, animate) {
+        if (!this.isScrollable()) {
+            return false;
+        }
+        var el = this.dom,
+            l = el.scrollLeft, t = el.scrollTop,
+            w = el.scrollWidth, h = el.scrollHeight,
+            cw = el.clientWidth, ch = el.clientHeight,
+            scrolled = false, v,
+            hash = {
+                l: Math.min(l + distance, w-cw),
+                r: v = Math.max(l - distance, 0),
+                t: Math.max(t - distance, 0),
+                b: Math.min(t + distance, h-ch)
+            };
+            hash.d = hash.b;
+            hash.u = hash.t;
+
+        direction = direction.substr(0, 1);
+        if ((v = hash[direction]) > -1) {
+            scrolled = true;
+            this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.anim(animate));
+        }
+        return scrolled;
+    }
+});
+
+Ext.Element.addMethods(
+    function() {
+        var VISIBILITY      = "visibility",
+            DISPLAY         = "display",
+            HIDDEN          = "hidden",
+            NONE            = "none",
+            XMASKED         = Ext.baseCSSPrefix + "masked",
+            XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
+            data            = Ext.Element.data;
+
+        return {
+            
+            isVisible : function(deep) {
+                var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
+                    p   = this.dom.parentNode;
+
+                if (deep !== true || !vis) {
+                    return vis;
+                }
+
+                while (p && !(/^body/i.test(p.tagName))) {
+                    if (!Ext.fly(p, '_isVisible').isVisible()) {
+                        return false;
+                    }
+                    p = p.parentNode;
+                }
+                return true;
+            },
+
+            
+            isDisplayed : function() {
+                return !this.isStyle(DISPLAY, NONE);
+            },
+
+            
+            enableDisplayMode : function(display) {
+                this.setVisibilityMode(Ext.Element.DISPLAY);
+
+                if (!Ext.isEmpty(display)) {
+                    data(this.dom, 'originalDisplay', display);
+                }
+
+                return this;
+            },
+
+            
+            mask : function(msg, msgCls) {
+                var me  = this,
+                    dom = me.dom,
+                    setExpression = dom.style.setExpression,
+                    dh  = Ext.DomHelper,
+                    EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
+                    el,
+                    mask;
+
+                if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
+                    me.addCls(XMASKEDRELATIVE);
+                }
+                el = data(dom, 'maskMsg');
+                if (el) {
+                    el.remove();
+                }
+                el = data(dom, 'mask');
+                if (el) {
+                    el.remove();
+                }
+
+                mask = dh.append(dom, {cls : Ext.baseCSSPrefix + "mask"}, true);
+                data(dom, 'mask', mask);
+
+                me.addCls(XMASKED);
+                mask.setDisplayed(true);
+
+                if (typeof msg == 'string') {
+                    var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
+                    data(dom, 'maskMsg', mm);
+                    mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
+                    mm.dom.firstChild.innerHTML = msg;
+                    mm.setDisplayed(true);
+                    mm.center(me);
+                }
+                
+                
+                
+                
+                
+                if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) {
+                    mask.dom.style.setExpression('width', 'this.parentNode.offsetWidth + "px"');
+                }
+
+                
+                
+                if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) {
+                    mask.dom.style.setExpression('height', 'this.parentNode.offsetHeight + "px"');
+                }
+                
+                else if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
+                    mask.setSize(undefined, me.getHeight());
+                }
+                return mask;
+            },
+
+            
+            unmask : function() {
+                var me      = this,
+                    dom     = me.dom,
+                    mask    = data(dom, 'mask'),
+                    maskMsg = data(dom, 'maskMsg');
+
+                if (mask) {
+                    
+                    if (mask.dom.style.clearExpression) {
+                        mask.dom.style.clearExpression('width');
+                        mask.dom.style.clearExpression('height');
+                    }
+                    if (maskMsg) {
+                        maskMsg.remove();
+                        data(dom, 'maskMsg', undefined);
+                    }
+
+                    mask.remove();
+                    data(dom, 'mask', undefined);
+                    me.removeCls([XMASKED, XMASKEDRELATIVE]);
+                }
+            },
+            
+            isMasked : function() {
+                var me = this,
+                    mask = data(me.dom, 'mask'),
+                    maskMsg = data(me.dom, 'maskMsg');
+
+                if (mask && mask.isVisible()) {
+                    if (maskMsg) {
+                        maskMsg.center(me);
+                    }
+                    return true;
+                }
+                return false;
+            },
+
+            
+            createShim : function() {
+                var el = document.createElement('iframe'),
+                    shim;
+
+                el.frameBorder = '0';
+                el.className = Ext.baseCSSPrefix + 'shim';
+                el.src = Ext.SSL_SECURE_URL;
+                shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
+                shim.autoBoxAdjust = false;
+                return shim;
+            }
+        };
+    }()
+);
+
+Ext.Element.addMethods({
+    
+    addKeyListener : function(key, fn, scope){
+        var config;
+        if(typeof key != 'object' || Ext.isArray(key)){
+            config = {
+                key: key,
+                fn: fn,
+                scope: scope
+            };
+        }else{
+            config = {
+                key : key.key,
+                shift : key.shift,
+                ctrl : key.ctrl,
+                alt : key.alt,
+                fn: fn,
+                scope: scope
+            };
+        }
+        return Ext.create('Ext.util.KeyMap', this, config);
+    },
+
+    
+    addKeyMap : function(config){
+        return Ext.create('Ext.util.KeyMap', this, config);
+    }
+});
+
+
+
+Ext.CompositeElementLite.importElementMethods();
+
+
+Ext.apply(Ext.CompositeElementLite.prototype, {
+    addElements : function(els, root){
+        if(!els){
+            return this;
+        }
+        if(typeof els == "string"){
+            els = Ext.Element.selectorFunction(els, root);
+        }
+        var yels = this.elements;
+        Ext.each(els, function(e) {
+            yels.push(Ext.get(e));
+        });
+        return this;
+    },
+
+    
+    first : function(){
+        return this.item(0);
+    },
+
+    
+    last : function(){
+        return this.item(this.getCount()-1);
+    },
+
+    
+    contains : function(el){
+        return this.indexOf(el) != -1;
+    },
+
+    
+    removeElement : function(keys, removeDom){
+        var me = this,
+            els = this.elements,
+            el;
+        Ext.each(keys, function(val){
+            if ((el = (els[val] || els[val = me.indexOf(val)]))) {
+                if(removeDom){
+                    if(el.dom){
+                        el.remove();
+                    }else{
+                        Ext.removeNode(el);
+                    }
+                }
+                Ext.Array.erase(els, val, 1);
+            }
+        });
+        return this;
+    }
+});
+
+
+Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
+
+    constructor : function(els, root){
+        this.elements = [];
+        this.add(els, root);
+    },
+
+    
+    getElement : function(el){
+        
+        return el;
+    },
+
+    
+    transformElement : function(el){
+        return Ext.get(el);
+    }
+});
+
+
+Ext.Element.select = function(selector, unique, root){
+    var els;
+    if(typeof selector == "string"){
+        els = Ext.Element.selectorFunction(selector, root);
+    }else if(selector.length !== undefined){
+        els = selector;
+    }else{
+    }
+    return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
+};
+
+
+Ext.select = Ext.Element.select;
+
+
+
+
+Ext.define('Ext.util.Observable', {
+
+    
+
+    requires: ['Ext.util.Event'],
+
+    statics: {
+        
+        releaseCapture: function(o) {
+            o.fireEvent = this.prototype.fireEvent;
+        },
+
+        
+        capture: function(o, fn, scope) {
+            o.fireEvent = Ext.Function.createInterceptor(o.fireEvent, fn, scope);
+        },
+
+        
+        observe: function(cls, listeners) {
+            if (cls) {
+                if (!cls.isObservable) {
+                    Ext.applyIf(cls, new this());
+                    this.capture(cls.prototype, cls.fireEvent, cls);
+                }
+                if (Ext.isObject(listeners)) {
+                    cls.on(listeners);
+                }
+                return cls;
+            }
+        }
+    },
+
+    
+
+    
+    
+    isObservable: true,
+
+    constructor: function(config) {
+        var me = this;
+
+        Ext.apply(me, config);
+        if (me.listeners) {
+            me.on(me.listeners);
+            delete me.listeners;
+        }
+        me.events = me.events || {};
+
+        if (me.bubbleEvents) {
+            me.enableBubble(me.bubbleEvents);
+        }
+    },
+
+    
+    eventOptionsRe : /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|vertical|horizontal|freezeEvent)$/,
+
+    
+    addManagedListener : function(item, ename, fn, scope, options) {
+        var me = this,
+            managedListeners = me.managedListeners = me.managedListeners || [],
+            config;
+
+        if (typeof ename !== 'string') {
+            options = ename;
+            for (ename in options) {
+                if (options.hasOwnProperty(ename)) {
+                    config = options[ename];
+                    if (!me.eventOptionsRe.test(ename)) {
+                        me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
+                    }
+                }
+            }
+        }
+        else {
+            managedListeners.push({
+                item: item,
+                ename: ename,
+                fn: fn,
+                scope: scope,
+                options: options
+            });
+
+            item.on(ename, fn, scope, options);
+        }
+    },
+
+    
+    removeManagedListener : function(item, ename, fn, scope) {
+        var me = this,
+            options,
+            config,
+            managedListeners,
+            length,
+            i;
+
+        if (typeof ename !== 'string') {
+            options = ename;
+            for (ename in options) {
+                if (options.hasOwnProperty(ename)) {
+                    config = options[ename];
+                    if (!me.eventOptionsRe.test(ename)) {
+                        me.removeManagedListener(item, ename, config.fn || config, config.scope || options.scope);
+                    }
+                }
+            }
+        }
+
+        managedListeners = me.managedListeners ? me.managedListeners.slice() : [];
+
+        for (i = 0, length = managedListeners.length; i < length; i++) {
+            me.removeManagedListenerItem(false, managedListeners[i], item, ename, fn, scope);
+        }
+    },
+
+    
+    fireEvent: function(eventName) {
+        var name = eventName.toLowerCase(),
+            events = this.events,
+            event = events && events[name],
+            bubbles = event && event.bubble;
+
+        return this.continueFireEvent(name, Ext.Array.slice(arguments, 1), bubbles);
+    },
+
+    
+    continueFireEvent: function(eventName, args, bubbles) {
+        var target = this,
+            queue, event,
+            ret = true;
+
+        do {
+            if (target.eventsSuspended === true) {
+                if ((queue = target.eventQueue)) {
+                    queue.push([eventName, args, bubbles]);
+                }
+                return ret;
+            } else {
+                event = target.events[eventName];
+                
+                
+                if (event && event != true) {
+                    if ((ret = event.fire.apply(event, args)) === false) {
+                        break;
+                    }
+                }
+            }
+        } while (bubbles && (target = target.getBubbleParent()));
+        return ret;
+    },
+
+    
+    getBubbleParent: function(){
+        var me = this, parent = me.getBubbleTarget && me.getBubbleTarget();
+        if (parent && parent.isObservable) {
+            return parent;
+        }
+        return null;
+    },
+
+    
+    addListener: function(ename, fn, scope, options) {
+        var me = this,
+            config,
+            event;
+
+        if (typeof ename !== 'string') {
+            options = ename;
+            for (ename in options) {
+                if (options.hasOwnProperty(ename)) {
+                    config = options[ename];
+                    if (!me.eventOptionsRe.test(ename)) {
+                        me.addListener(ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
+                    }
+                }
+            }
+        }
+        else {
+            ename = ename.toLowerCase();
+            me.events[ename] = me.events[ename] || true;
+            event = me.events[ename] || true;
+            if (Ext.isBoolean(event)) {
+                me.events[ename] = event = new Ext.util.Event(me, ename);
+            }
+            event.addListener(fn, scope, Ext.isObject(options) ? options : {});
+        }
+    },
+
+    
+    removeListener: function(ename, fn, scope) {
+        var me = this,
+            config,
+            event,
+            options;
+
+        if (typeof ename !== 'string') {
+            options = ename;
+            for (ename in options) {
+                if (options.hasOwnProperty(ename)) {
+                    config = options[ename];
+                    if (!me.eventOptionsRe.test(ename)) {
+                        me.removeListener(ename, config.fn || config, config.scope || options.scope);
+                    }
+                }
+            }
+        } else {
+            ename = ename.toLowerCase();
+            event = me.events[ename];
+            if (event && event.isEvent) {
+                event.removeListener(fn, scope);
+            }
+        }
+    },
+
+    
+    clearListeners: function() {
+        var events = this.events,
+            event,
+            key;
+
+        for (key in events) {
+            if (events.hasOwnProperty(key)) {
+                event = events[key];
+                if (event.isEvent) {
+                    event.clearListeners();
+                }
+            }
+        }
+
+        this.clearManagedListeners();
+    },
+
+
+    
+    clearManagedListeners : function() {
+        var managedListeners = this.managedListeners || [],
+            i = 0,
+            len = managedListeners.length;
+
+        for (; i < len; i++) {
+            this.removeManagedListenerItem(true, managedListeners[i]);
+        }
+
+        this.managedListeners = [];
+    },
+
+    
+    removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
+        if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
+            managedListener.item.un(managedListener.ename, managedListener.fn, managedListener.scope);
+            if (!isClear) {
+                Ext.Array.remove(this.managedListeners, managedListener);
+            }
+        }
+    },
+
+
+    
+    addEvents: function(o) {
+        var me = this,
+            args,
+            len,
+            i;
+
+            me.events = me.events || {};
+        if (Ext.isString(o)) {
+            args = arguments;
+            i = args.length;
+
+            while (i--) {
+                me.events[args[i]] = me.events[args[i]] || true;
+            }
+        } else {
+            Ext.applyIf(me.events, o);
+        }
+    },
+
+    
+    hasListener: function(ename) {
+        var event = this.events[ename.toLowerCase()];
+        return event && event.isEvent === true && event.listeners.length > 0;
+    },
+
+    
+    suspendEvents: function(queueSuspended) {
+        this.eventsSuspended = true;
+        if (queueSuspended && !this.eventQueue) {
+            this.eventQueue = [];
+        }
+    },
+
+    
+    resumeEvents: function() {
+        var me = this,
+            queued = me.eventQueue;
+
+        me.eventsSuspended = false;
+        delete me.eventQueue;
+
+        if (queued) {
+            Ext.each(queued, function(e) {
+                me.continueFireEvent.apply(me, e);
+            });
+        }
+    },
+
+    
+    relayEvents : function(origin, events, prefix) {
+        prefix = prefix || '';
+        var me = this,
+            len = events.length,
+            i = 0,
+            oldName,
+            newName;
+
+        for (; i < len; i++) {
+            oldName = events[i].substr(prefix.length);
+            newName = prefix + oldName;
+            me.events[newName] = me.events[newName] || true;
+            origin.on(oldName, me.createRelayer(newName));
+        }
+    },
+
+    
+    createRelayer: function(newName){
+        var me = this;
+        return function(){
+            return me.fireEvent.apply(me, [newName].concat(Array.prototype.slice.call(arguments, 0, -1)));
+        };
+    },
+
+    
+    enableBubble: function(events) {
+        var me = this;
+        if (!Ext.isEmpty(events)) {
+            events = Ext.isArray(events) ? events: Ext.Array.toArray(arguments);
+            Ext.each(events,
+            function(ename) {
+                ename = ename.toLowerCase();
+                var ce = me.events[ename] || true;
+                if (Ext.isBoolean(ce)) {
+                    ce = new Ext.util.Event(me, ename);
+                    me.events[ename] = ce;
+                }
+                ce.bubble = true;
+            });
+        }
+    }
+}, function() {
+
+    this.createAlias({
+        
+        on: 'addListener',
+        
+        un: 'removeListener',
+        
+        mon: 'addManagedListener',
+        
+        mun: 'removeManagedListener'
+    });
+
+    
+    this.observeClass = this.observe;
+
+    Ext.apply(Ext.util.Observable.prototype, function(){
+        
+        
+        
+        function getMethodEvent(method){
+            var e = (this.methodEvents = this.methodEvents || {})[method],
+                returnValue,
+                v,
+                cancel,
+                obj = this;
+
+            if (!e) {
+                this.methodEvents[method] = e = {};
+                e.originalFn = this[method];
+                e.methodName = method;
+                e.before = [];
+                e.after = [];
+
+                var makeCall = function(fn, scope, args){
+                    if((v = fn.apply(scope || obj, args)) !== undefined){
+                        if (typeof v == 'object') {
+                            if(v.returnValue !== undefined){
+                                returnValue = v.returnValue;
+                            }else{
+                                returnValue = v;
+                            }
+                            cancel = !!v.cancel;
+                        }
+                        else
+                            if (v === false) {
+                                cancel = true;
+                            }
+                            else {
+                                returnValue = v;
+                            }
+                    }
+                };
+
+                this[method] = function(){
+                    var args = Array.prototype.slice.call(arguments, 0),
+                        b, i, len;
+                    returnValue = v = undefined;
+                    cancel = false;
+
+                    for(i = 0, len = e.before.length; i < len; i++){
+                        b = e.before[i];
+                        makeCall(b.fn, b.scope, args);
+                        if (cancel) {
+                            return returnValue;
+                        }
+                    }
+
+                    if((v = e.originalFn.apply(obj, args)) !== undefined){
+                        returnValue = v;
+                    }
+
+                    for(i = 0, len = e.after.length; i < len; i++){
+                        b = e.after[i];
+                        makeCall(b.fn, b.scope, args);
+                        if (cancel) {
+                            return returnValue;
+                        }
+                    }
+                    return returnValue;
+                };
+            }
+            return e;
+        }
+
+        return {
+            
+            
+            
+            beforeMethod : function(method, fn, scope){
+                getMethodEvent.call(this, method).before.push({
+                    fn: fn,
+                    scope: scope
+                });
+            },
+
+            
+            afterMethod : function(method, fn, scope){
+                getMethodEvent.call(this, method).after.push({
+                    fn: fn,
+                    scope: scope
+                });
+            },
+
+            removeMethodListener: function(method, fn, scope){
+                var e = this.getMethodEvent(method),
+                    i, len;
+                for(i = 0, len = e.before.length; i < len; i++){
+                    if(e.before[i].fn == fn && e.before[i].scope == scope){
+                        Ext.Array.erase(e.before, i, 1);
+                        return;
+                    }
+                }
+                for(i = 0, len = e.after.length; i < len; i++){
+                    if(e.after[i].fn == fn && e.after[i].scope == scope){
+                        Ext.Array.erase(e.after, i, 1);
+                        return;
+                    }
+                }
+            },
+
+            toggleEventLogging: function(toggle) {
+                Ext.util.Observable[toggle ? 'capture' : 'releaseCapture'](this, function(en) {
+                    if (Ext.isDefined(Ext.global.console)) {
+                        Ext.global.console.log(en, arguments);
+                    }
+                });
+            }
+        };
+    }());
+});
+
+
+Ext.define('Ext.util.Animate', {
+
+    uses: ['Ext.fx.Manager', 'Ext.fx.Anim'],
+
+    
+    animate: function(animObj) {
+        var me = this;
+        if (Ext.fx.Manager.hasFxBlock(me.id)) {
+            return me;
+        }
+        Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(animObj)));
+        return this;
+    },
+
+    
+    anim: function(config) {
+        if (!Ext.isObject(config)) {
+            return (config) ? {} : false;
+        }
+
+        var me = this;
+
+        if (config.stopAnimation) {
+            me.stopAnimation();
+        }
+
+        Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
+
+        return Ext.apply({
+            target: me,
+            paused: true
+        }, config);
+    },
+
+    
+    stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'),
+
+    
+    stopAnimation: function() {
+        Ext.fx.Manager.stopAnimation(this.id);
+        return this;
+    },
+
+    
+    syncFx: function() {
+        Ext.fx.Manager.setFxDefaults(this.id, {
+            concurrent: true
+        });
+        return this;
+    },
+
+    
+    sequenceFx: function() {
+        Ext.fx.Manager.setFxDefaults(this.id, {
+            concurrent: false
+        });
+        return this;
+    },
+
+    
+    hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'),
+
+    
+    getActiveAnimation: function() {
+        return Ext.fx.Manager.getActiveAnimation(this.id);
+    }
+}, function(){
+    
+    Ext.applyIf(Ext.Element.prototype, this.prototype);
+    
+    Ext.CompositeElementLite.importElementMethods();
+});
+
+Ext.define('Ext.state.Provider', {
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+    
+    
+    prefix: 'ext-',
+    
+    constructor : function(config){
+        config = config || {};
+        var me = this;
+        Ext.apply(me, config);
+        
+        me.addEvents("statechange");
+        me.state = {};
+        me.mixins.observable.constructor.call(me);
+    },
+    
+    
+    get : function(name, defaultValue){
+        return typeof this.state[name] == "undefined" ?
+            defaultValue : this.state[name];
+    },
+
+    
+    clear : function(name){
+        var me = this;
+        delete me.state[name];
+        me.fireEvent("statechange", me, name, null);
+    },
+
+    
+    set : function(name, value){
+        var me = this;
+        me.state[name] = value;
+        me.fireEvent("statechange", me, name, value);
+    },
+
+    
+    decodeValue : function(value){
+
+        
+        
+        
+        
+        
+        
+        
+
+        var me = this,
+            re = /^(a|n|d|b|s|o|e)\:(.*)$/,
+            matches = re.exec(unescape(value)),
+            all,
+            type,
+            value,
+            keyValue;
+            
+        if(!matches || !matches[1]){
+            return; 
+        }
+        
+        type = matches[1];
+        value = matches[2];
+        switch (type) {
+            case 'e':
+                return null;
+            case 'n':
+                return parseFloat(value);
+            case 'd':
+                return new Date(Date.parse(value));
+            case 'b':
+                return (value == '1');
+            case 'a':
+                all = [];
+                if(value != ''){
+                    Ext.each(value.split('^'), function(val){
+                        all.push(me.decodeValue(val));
+                    }, me);
+                }
+                return all;
+           case 'o':
+                all = {};
+                if(value != ''){
+                    Ext.each(value.split('^'), function(val){
+                        keyValue = val.split('=');
+                        all[keyValue[0]] = me.decodeValue(keyValue[1]);
+                    }, me);
+                }
+                return all;
+           default:
+                return value;
+        }
+    },
+
+    
+    encodeValue : function(value){
+        var flat = '',
+            i = 0,
+            enc,
+            len,
+            key;
+            
+        if (value == null) {
+            return 'e:1';    
+        } else if(typeof value == 'number') {
+            enc = 'n:' + value;
+        } else if(typeof value == 'boolean') {
+            enc = 'b:' + (value ? '1' : '0');
+        } else if(Ext.isDate(value)) {
+            enc = 'd:' + value.toGMTString();
+        } else if(Ext.isArray(value)) {
+            for (len = value.length; i < len; i++) {
+                flat += this.encodeValue(value[i]);
+                if (i != len - 1) {
+                    flat += '^';
+                }
+            }
+            enc = 'a:' + flat;
+        } else if (typeof value == 'object') {
+            for (key in value) {
+                if (typeof value[key] != 'function' && value[key] !== undefined) {
+                    flat += key + '=' + this.encodeValue(value[key]) + '^';
+                }
+            }
+            enc = 'o:' + flat.substring(0, flat.length-1);
+        } else {
+            enc = 's:' + value;
+        }
+        return escape(enc);
+    }
+});
+
+Ext.define('Ext.ComponentQuery', {
+    singleton: true,
+    uses: ['Ext.ComponentManager']
+}, function() {
+
+    var cq = this,
+
+        
+        
+        filterFnPattern = [
+            'var r = [],',
+                'i = 0,',
+                'it = items,',
+                'l = it.length,',
+                'c;',
+            'for (; i < l; i++) {',
+                'c = it[i];',
+                'if (c.{0}) {',
+                   'r.push(c);',
+                '}',
+            '}',
+            'return r;'
+        ].join(''),
+
+        filterItems = function(items, operation) {
+            
+            
+            
+            return operation.method.apply(this, [ items ].concat(operation.args));
+        },
+
+        getItems = function(items, mode) {
+            var result = [],
+                i = 0,
+                length = items.length,
+                candidate,
+                deep = mode !== '>';
+                
+            for (; i < length; i++) {
+                candidate = items[i];
+                if (candidate.getRefItems) {
+                    result = result.concat(candidate.getRefItems(deep));
+                }
+            }
+            return result;
+        },
+
+        getAncestors = function(items) {
+            var result = [],
+                i = 0,
+                length = items.length,
+                candidate;
+            for (; i < length; i++) {
+                candidate = items[i];
+                while (!!(candidate = (candidate.ownerCt || candidate.floatParent))) {
+                    result.push(candidate);
+                }
+            }
+            return result;
+        },
+
+        
+        filterByXType = function(items, xtype, shallow) {
+            if (xtype === '*') {
+                return items.slice();
+            }
+            else {
+                var result = [],
+                    i = 0,
+                    length = items.length,
+                    candidate;
+                for (; i < length; i++) {
+                    candidate = items[i];
+                    if (candidate.isXType(xtype, shallow)) {
+                        result.push(candidate);
+                    }
+                }
+                return result;
+            }
+        },
+
+        
+        filterByClassName = function(items, className) {
+            var EA = Ext.Array,
+                result = [],
+                i = 0,
+                length = items.length,
+                candidate;
+            for (; i < length; i++) {
+                candidate = items[i];
+                if (candidate.el ? candidate.el.hasCls(className) : EA.contains(candidate.initCls(), className)) {
+                    result.push(candidate);
+                }
+            }
+            return result;
+        },
+
+        
+        filterByAttribute = function(items, property, operator, value) {
+            var result = [],
+                i = 0,
+                length = items.length,
+                candidate;
+            for (; i < length; i++) {
+                candidate = items[i];
+                if (!value ? !!candidate[property] : (String(candidate[property]) === value)) {
+                    result.push(candidate);
+                }
+            }
+            return result;
+        },
+
+        
+        filterById = function(items, id) {
+            var result = [],
+                i = 0,
+                length = items.length,
+                candidate;
+            for (; i < length; i++) {
+                candidate = items[i];
+                if (candidate.getItemId() === id) {
+                    result.push(candidate);
+                }
+            }
+            return result;
+        },
+
+        
+        filterByPseudo = function(items, name, value) {
+            return cq.pseudos[name](items, value);
+        },
+
+        
+        
+        modeRe = /^(\s?([>\^])\s?|\s|$)/,
+
+        
+        tokenRe = /^(#)?([\w\-]+|\*)(?:\((true|false)\))?/,
+
+        matchers = [{
+            
+            re: /^\.([\w\-]+)(?:\((true|false)\))?/,
+            method: filterByXType
+        },{
+            
+            re: /^(?:[\[](?:@)?([\w\-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]])/,
+            method: filterByAttribute
+        }, {
+            
+            re: /^#([\w\-]+)/,
+            method: filterById
+        }, {
+            
+            re: /^\:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/,
+            method: filterByPseudo
+        }, {
+            
+            re: /^(?:\{([^\}]+)\})/,
+            method: filterFnPattern
+        }];
+
+    
+    
+    cq.Query = Ext.extend(Object, {
+        constructor: function(cfg) {
+            cfg = cfg || {};
+            Ext.apply(this, cfg);
+        },
+
+        
+        
+        
+        
+        
+        
+        
+        
+        execute : function(root) {
+            var operations = this.operations,
+                i = 0,
+                length = operations.length,
+                operation,
+                workingItems;
+
+            
+            if (!root) {
+                workingItems = Ext.ComponentManager.all.getArray();
+            }
+            
+            else if (Ext.isArray(root)) {
+                workingItems = root;
+            }
+
+            
+            
+            for (; i < length; i++) {
+                operation = operations[i];
+
+                
+                
+                
+                
+                
+                
+                if (operation.mode === '^') {
+                    workingItems = getAncestors(workingItems || [root]);
+                }
+                else if (operation.mode) {
+                    workingItems = getItems(workingItems || [root], operation.mode);
+                }
+                else {
+                    workingItems = filterItems(workingItems || getItems([root]), operation);
+                }
+
+                
+                
+                if (i === length -1) {
+                    return workingItems;
+                }
+            }
+            return [];
+        },
+
+        is: function(component) {
+            var operations = this.operations,
+                components = Ext.isArray(component) ? component : [component],
+                originalLength = components.length,
+                lastOperation = operations[operations.length-1],
+                ln, i;
+
+            components = filterItems(components, lastOperation);
+            if (components.length === originalLength) {
+                if (operations.length > 1) {
+                    for (i = 0, ln = components.length; i < ln; i++) {
+                        if (Ext.Array.indexOf(this.execute(), components[i]) === -1) {
+                            return false;
+                        }
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+    });
+
+    Ext.apply(this, {
+
+        
+        cache: {},
+
+        
+        pseudos: {
+            not: function(components, selector){
+                var CQ = Ext.ComponentQuery,
+                    i = 0,
+                    length = components.length,
+                    results = [],
+                    index = -1,
+                    component;
+                
+                for(; i < length; ++i) {
+                    component = components[i];
+                    if (!CQ.is(component, selector)) {
+                        results[++index] = component;
+                    }
+                }
+                return results;
+            },
+            last: function(components) {
+                return components[components.length - 1];
+            }
+        },
+
+        
+        query: function(selector, root) {
+            var selectors = selector.split(','),
+                length = selectors.length,
+                i = 0,
+                results = [],
+                noDupResults = [], 
+                dupMatcher = {}, 
+                query, resultsLn, cmp;
+
+            for (; i < length; i++) {
+                selector = Ext.String.trim(selectors[i]);
+                query = this.cache[selector];
+                if (!query) {
+                    this.cache[selector] = query = this.parse(selector);
+                }
+                results = results.concat(query.execute(root));
+            }
+
+            
+            
+            if (length > 1) {
+                resultsLn = results.length;
+                for (i = 0; i < resultsLn; i++) {
+                    cmp = results[i];
+                    if (!dupMatcher[cmp.id]) {
+                        noDupResults.push(cmp);
+                        dupMatcher[cmp.id] = true;
+                    }
+                }
+                results = noDupResults;
+            }
+            return results;
+        },
+
+        
+        is: function(component, selector) {
+            if (!selector) {
+                return true;
+            }
+            var query = this.cache[selector];
+            if (!query) {
+                this.cache[selector] = query = this.parse(selector);
+            }
+            return query.is(component);
+        },
+
+        parse: function(selector) {
+            var operations = [],
+                length = matchers.length,
+                lastSelector,
+                tokenMatch,
+                matchedChar,
+                modeMatch,
+                selectorMatch,
+                i, matcher, method;
+
+            
+            
+            
+            while (selector && lastSelector !== selector) {
+                lastSelector = selector;
+
+                
+                tokenMatch = selector.match(tokenRe);
+
+                if (tokenMatch) {
+                    matchedChar = tokenMatch[1];
+
+                    
+                    if (matchedChar === '#') {
+                        operations.push({
+                            method: filterById,
+                            args: [Ext.String.trim(tokenMatch[2])]
+                        });
+                    }
+                    
+                    
+                    else if (matchedChar === '.') {
+                        operations.push({
+                            method: filterByClassName,
+                            args: [Ext.String.trim(tokenMatch[2])]
+                        });
+                    }
+                    
+                    
+                    else {
+                        operations.push({
+                            method: filterByXType,
+                            args: [Ext.String.trim(tokenMatch[2]), Boolean(tokenMatch[3])]
+                        });
+                    }
+
+                    
+                    selector = selector.replace(tokenMatch[0], '');
+                }
+
+                
+                
+                
+                while (!(modeMatch = selector.match(modeRe))) {
+                    
+                    
+                    for (i = 0; selector && i < length; i++) {
+                        matcher = matchers[i];
+                        selectorMatch = selector.match(matcher.re);
+                        method = matcher.method;
+
+                        
+                        
+                        
+                        if (selectorMatch) {
+                            operations.push({
+                                method: Ext.isString(matcher.method)
+                                    
+                                    
+                                    
+                                    ? Ext.functionFactory('items', Ext.String.format.apply(Ext.String, [method].concat(selectorMatch.slice(1))))
+                                    : matcher.method,
+                                args: selectorMatch.slice(1)
+                            });
+                            selector = selector.replace(selectorMatch[0], '');
+                            break; 
+                        }
+                    }
+                }
+
+                
+                
+                
+                
+                if (modeMatch[1]) { 
+                    operations.push({
+                        mode: modeMatch[2]||modeMatch[1]
+                    });
+                    selector = selector.replace(modeMatch[0], '');
+                }
+            }
+
+            
+            
+            return new cq.Query({
+                operations: operations
+            });
+        }
+    });
+});
+
+Ext.define('Ext.util.HashMap', {
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    
+
+    
+    constructor: function(config) {
+        config = config || {};
+        
+        var me = this,
+            keyFn = config.keyFn;
+
+        me.addEvents(
+            
+            'add',
+            
+            'clear',
+            
+            'remove',
+            
+            'replace'
+        );
+
+        me.mixins.observable.constructor.call(me, config);
+        me.clear(true);
+        
+        if (keyFn) {
+            me.getKey = keyFn;
+        }
+    },
+
+    
+    getCount: function() {
+        return this.length;
+    },
+
+    
+    getData: function(key, value) {
+        
+        if (value === undefined) {
+            value = key;
+            key = this.getKey(value);
+        }
+
+        return [key, value];
+    },
+
+    
+    getKey: function(o) {
+        return o.id;
+    },
+
+    
+    add: function(key, value) {
+        var me = this,
+            data;
+
+        if (arguments.length === 1) {
+            value = key;
+            key = me.getKey(value);
+        }
+
+        if (me.containsKey(key)) {
+            return me.replace(key, value);
+        }
+
+        data = me.getData(key, value);
+        key = data[0];
+        value = data[1];
+        me.map[key] = value;
+        ++me.length;
+        me.fireEvent('add', me, key, value);
+        return value;
+    },
+
+    
+    replace: function(key, value) {
+        var me = this,
+            map = me.map,
+            old;
+
+        if (!me.containsKey(key)) {
+            me.add(key, value);
+        }
+        old = map[key];
+        map[key] = value;
+        me.fireEvent('replace', me, key, value, old);
+        return value;
+    },
+
+    
+    remove: function(o) {
+        var key = this.findKey(o);
+        if (key !== undefined) {
+            return this.removeAtKey(key);
+        }
+        return false;
+    },
+
+    
+    removeAtKey: function(key) {
+        var me = this,
+            value;
+
+        if (me.containsKey(key)) {
+            value = me.map[key];
+            delete me.map[key];
+            --me.length;
+            me.fireEvent('remove', me, key, value);
+            return true;
+        }
+        return false;
+    },
+
+    
+    get: function(key) {
+        return this.map[key];
+    },
+
+    
+    clear: function( initial) {
+        var me = this;
+        me.map = {};
+        me.length = 0;
+        if (initial !== true) {
+            me.fireEvent('clear', me);
+        }
+        return me;
+    },
+
+    
+    containsKey: function(key) {
+        return this.map[key] !== undefined;
+    },
+
+    
+    contains: function(value) {
+        return this.containsKey(this.findKey(value));
+    },
+
+    
+    getKeys: function() {
+        return this.getArray(true);
+    },
+
+    
+    getValues: function() {
+        return this.getArray(false);
+    },
+
+    
+    getArray: function(isKey) {
+        var arr = [],
+            key,
+            map = this.map;
+        for (key in map) {
+            if (map.hasOwnProperty(key)) {
+                arr.push(isKey ? key: map[key]);
+            }
+        }
+        return arr;
+    },
+
+    
+    each: function(fn, scope) {
+        
+        var items = Ext.apply({}, this.map),
+            key,
+            length = this.length;
+
+        scope = scope || this;
+        for (key in items) {
+            if (items.hasOwnProperty(key)) {
+                if (fn.call(scope, key, items[key], length) === false) {
+                    break;
+                }
+            }
+        }
+        return this;
+    },
+
+    
+    clone: function() {
+        var hash = new this.self(),
+            map = this.map,
+            key;
+
+        hash.suspendEvents();
+        for (key in map) {
+            if (map.hasOwnProperty(key)) {
+                hash.add(key, map[key]);
+            }
+        }
+        hash.resumeEvents();
+        return hash;
+    },
+
+    
+    findKey: function(value) {
+        var key,
+            map = this.map;
+
+        for (key in map) {
+            if (map.hasOwnProperty(key) && map[key] === value) {
+                return key;
+            }
+        }
+        return undefined;
+    }
+});
+
+
+Ext.define('Ext.state.Manager', {
+    singleton: true,
+    requires: ['Ext.state.Provider'],
+    constructor: function() {
+        this.provider = Ext.create('Ext.state.Provider');
+    },
+    
+    
+    
+    setProvider : function(stateProvider){
+        this.provider = stateProvider;
+    },
+
+    
+    get : function(key, defaultValue){
+        return this.provider.get(key, defaultValue);
+    },
+
+    
+     set : function(key, value){
+        this.provider.set(key, value);
+    },
+
+    
+    clear : function(key){
+        this.provider.clear(key);
+    },
+
+    
+    getProvider : function(){
+        return this.provider;
+    }
+});
+
+Ext.define('Ext.state.Stateful', {
+
+    
+
+   mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: ['Ext.state.Manager'],
+
+    
+
+    
+    stateful: true,
+
+    
+
+    
+
+    
+    saveDelay: 100,
+
+    autoGenIdRe: /^((\w+-)|(ext-comp-))\d{4,}$/i,
+
+    constructor: function(config) {
+        var me = this;
+
+        config = config || {};
+        if (Ext.isDefined(config.stateful)) {
+            me.stateful = config.stateful;
+        }
+        if (Ext.isDefined(config.saveDelay)) {
+            me.saveDelay = config.saveDelay;
+        }
+        me.stateId = me.stateId || config.stateId;
+
+        if (!me.stateEvents) {
+            me.stateEvents = [];
+        }
+        if (config.stateEvents) {
+            me.stateEvents.concat(config.stateEvents);
+        }
+        this.addEvents(
+            
+            'beforestaterestore',
+
+            
+            'staterestore',
+
+            
+            'beforestatesave',
+
+            
+            'statesave'
+        );
+        me.mixins.observable.constructor.call(me);
+        if (me.stateful !== false) {
+            me.initStateEvents();
+            me.initState();
+        }
+    },
+
+    
+    initStateEvents: function() {
+        this.addStateEvents(this.stateEvents);
+    },
+
+    
+    addStateEvents: function(events){
+        if (!Ext.isArray(events)) {
+            events = [events];
+        }
+
+        var me = this,
+            i = 0,
+            len = events.length;
+
+        for (; i < len; ++i) {
+            me.on(events[i], me.onStateChange, me);
+        }
+    },
+
+    
+    onStateChange: function(){
+        var me = this,
+            delay = me.saveDelay;
+
+        if (delay > 0) {
+            if (!me.stateTask) {
+                me.stateTask = Ext.create('Ext.util.DelayedTask', me.saveState, me);
+            }
+            me.stateTask.delay(me.saveDelay);
+        } else {
+            me.saveState();
+        }
+    },
+
+    
+    saveState: function() {
+        var me = this,
+            id,
+            state;
+
+        if (me.stateful !== false) {
+            id = me.getStateId();
+            if (id) {
+                state = me.getState();
+                if (me.fireEvent('beforestatesave', me, state) !== false) {
+                    Ext.state.Manager.set(id, state);
+                    me.fireEvent('statesave', me, state);
+                }
+            }
+        }
+    },
+
+    
+    getState: function(){
+        return null;
+    },
+
+    
+    applyState: function(state) {
+        if (state) {
+            Ext.apply(this, state);
+        }
+    },
+
+    
+    getStateId: function() {
+        var me = this,
+            id = me.stateId;
+
+        if (!id) {
+            id = me.autoGenIdRe.test(String(me.id)) ? null : me.id;
+        }
+        return id;
+    },
+
+    
+    initState: function(){
+        var me = this,
+            id = me.getStateId(),
+            state;
+
+        if (me.stateful !== false) {
+            if (id) {
+                state = Ext.state.Manager.get(id);
+                if (state) {
+                    state = Ext.apply({}, state);
+                    if (me.fireEvent('beforestaterestore', me, state) !== false) {
+                        me.applyState(state);
+                        me.fireEvent('staterestore', me, state);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    savePropToState: function (propName, state, stateName) {
+        var me = this,
+            value = me[propName],
+            config = me.initialConfig;
+
+        if (me.hasOwnProperty(propName)) {
+            if (!config || config[propName] !== value) {
+                if (state) {
+                    state[stateName || propName] = value;
+                }
+                return true;
+            }
+        }
+        return false;
+    },
+
+    savePropsToState: function (propNames, state) {
+        var me = this;
+        Ext.each(propNames, function (propName) {
+            me.savePropToState(propName, state);
+        });
+        return state;
+    },
+
+    
+    destroy: function(){
+        var task = this.stateTask;
+        if (task) {
+            task.cancel();
+        }
+        this.clearListeners();
+
+    }
+
+});
+
+
+Ext.define('Ext.AbstractManager', {
+
+    
+
+    requires: ['Ext.util.HashMap'],
+
+    
+
+    typeName: 'type',
+
+    constructor: function(config) {
+        Ext.apply(this, config || {});
+
+        
+        this.all = Ext.create('Ext.util.HashMap');
+
+        this.types = {};
+    },
+
+    
+    get : function(id) {
+        return this.all.get(id);
+    },
+
+    
+    register: function(item) {
+        this.all.add(item);
+    },
+
+    
+    unregister: function(item) {
+        this.all.remove(item);
+    },
+
+    
+    registerType : function(type, cls) {
+        this.types[type] = cls;
+        cls[this.typeName] = type;
+    },
+
+    
+    isRegistered : function(type){
+        return this.types[type] !== undefined;
+    },
+
+    
+    create: function(config, defaultType) {
+        var type        = config[this.typeName] || config.type || defaultType,
+            Constructor = this.types[type];
+
+
+        return new Constructor(config);
+    },
+
+    
+    onAvailable : function(id, fn, scope){
+        var all = this.all,
+            item;
+        
+        if (all.containsKey(id)) {
+            item = all.get(id);
+            fn.call(scope || item, item);
+        } else {
+            all.on('add', function(map, key, item){
+                if (key == id) {
+                    fn.call(scope || item, item);
+                    all.un('add', fn, scope);
+                }
+            });
+        }
+    },
+    
+    
+    each: function(fn, scope){
+        this.all.each(fn, scope || this);    
+    },
+    
+    
+    getCount: function(){
+        return this.all.getCount();
+    }
+});
+
+
+Ext.define('Ext.ComponentManager', {
+    extend: 'Ext.AbstractManager',
+    alternateClassName: 'Ext.ComponentMgr',
+    
+    singleton: true,
+    
+    typeName: 'xtype',
+    
+    
+    create: function(component, defaultType){
+        if (component instanceof Ext.AbstractComponent) {
+            return component;
+        }
+        else if (Ext.isString(component)) {
+            return Ext.createByAlias('widget.' + component);
+        }
+        else {
+            var type = component.xtype || defaultType,
+                config = component;
+            
+            return Ext.createByAlias('widget.' + type, config);
+        }
+    },
+
+    registerType: function(type, cls) {
+        this.types[type] = cls;
+        cls[this.typeName] = type;
+        cls.prototype[this.typeName] = type;
+    }
+});
+
+Ext.define('Ext.AbstractComponent', {
+
+    
+    requires: [
+        'Ext.ComponentQuery',
+        'Ext.ComponentManager'
+    ],
+
+    mixins: {
+        observable: 'Ext.util.Observable',
+        animate: 'Ext.util.Animate',
+        state: 'Ext.state.Stateful'
+    },
+
+    
+    
+    uses: [
+        'Ext.PluginManager',
+        'Ext.ComponentManager',
+        'Ext.Element',
+        'Ext.DomHelper',
+        'Ext.XTemplate',
+        'Ext.ComponentQuery',
+        'Ext.ComponentLoader',
+        'Ext.EventManager',
+        'Ext.layout.Layout',
+        'Ext.layout.component.Auto',
+        'Ext.LoadMask',
+        'Ext.ZIndexManager'
+    ],
+
+    statics: {
+        AUTO_ID: 1000
+    },
+
+    
+
+    isComponent: true,
+
+    getAutoId: function() {
+        return ++Ext.AbstractComponent.AUTO_ID;
+    },
+
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    renderTpl: null,
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    tplWriteMode: 'overwrite',
+
+    
+    baseCls: Ext.baseCSSPrefix + 'component',
+
+    
+
+    
+
+    
+
+    
+    disabledCls: Ext.baseCSSPrefix + 'item-disabled',
+
+    
+    ui: 'default',
+
+    
+    uiCls: [],
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    hidden: false,
+
+    
+    disabled: false,
+
+    
+
+    
+    draggable: false,
+
+    
+    floating: false,
+
+    
+    hideMode: 'display',
+
+    
+
+    
+
+    
+    styleHtmlContent: false,
+
+    
+    styleHtmlCls: Ext.baseCSSPrefix + 'html',
+
+    
+    
+    
+    
+
+    
+
+    
+    autoShow: false,
+
+    
+    autoRender: false,
+
+    needsLayout: false,
+
+    
+    allowDomMove: true,
+
+    
+
+    
+    rendered: false,
+
+    
+    componentLayoutCounter: 0,
+
+    weight: 0,
+
+    trimRe: /^\s+|\s+$/g,
+    spacesRe: /\s+/,
+
+
+    
+    maskOnDisable: true,
+
+    
+    constructor : function(config) {
+        var me = this,
+            i, len;
+
+        config = config || {};
+        me.initialConfig = config;
+        Ext.apply(me, config);
+
+        me.addEvents(
+            
+            'beforeactivate',
+            
+            'activate',
+            
+            'beforedeactivate',
+            
+            'deactivate',
+            
+            'added',
+            
+            'disable',
+            
+            'enable',
+            
+            'beforeshow',
+            
+            'show',
+            
+            'beforehide',
+            
+            'hide',
+            
+            'removed',
+            
+            'beforerender',
+            
+            'render',
+            
+            'afterrender',
+            
+            'beforedestroy',
+            
+            'destroy',
+            
+            'resize',
+            
+            'move'
+        );
+
+        me.getId();
+
+        me.mons = [];
+        me.additionalCls = [];
+        me.renderData = me.renderData || {};
+        me.renderSelectors = me.renderSelectors || {};
+
+        if (me.plugins) {
+            me.plugins = [].concat(me.plugins);
+            me.constructPlugins();
+        }
+
+        me.initComponent();
+
+        
+        Ext.ComponentManager.register(me);
+
+        
+        me.mixins.observable.constructor.call(me);
+        me.mixins.state.constructor.call(me, config);
+
+        
+        this.addStateEvents('resize');
+
+        
+        if (me.plugins) {
+            me.plugins = [].concat(me.plugins);
+            for (i = 0, len = me.plugins.length; i < len; i++) {
+                me.plugins[i] = me.initPlugin(me.plugins[i]);
+            }
+        }
+
+        me.loader = me.getLoader();
+
+        if (me.renderTo) {
+            me.render(me.renderTo);
+            
+            
+            
+        }
+
+        if (me.autoShow) {
+            me.show();
+        }
+
+    },
+
+    initComponent: function () {
+        
+        
+        this.constructPlugins();
+    },
+
+    
+    getState: function() {
+        var me = this,
+            layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
+            state = {
+                collapsed: me.collapsed
+            },
+            width = me.width,
+            height = me.height,
+            cm = me.collapseMemento,
+            anchors;
+
+        
+        
+        if (me.collapsed && cm) {
+            if (Ext.isDefined(cm.data.width)) {
+                width = cm.width;
+            }
+            if (Ext.isDefined(cm.data.height)) {
+                height = cm.height;
+            }
+        }
+
+        
+        if (layout && me.flex) {
+            state.flex = me.flex;
+            if (layout.perpendicularPrefix) {
+                state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap]();
+            } else {
+            }
+        }
+        
+        else if (layout && me.anchor) {
+            state.anchor = me.anchor;
+            anchors = me.anchor.split(' ').concat(null);
+            if (!anchors[0]) {
+                if (me.width) {
+                    state.width = width;
+                }
+            }
+            if (!anchors[1]) {
+                if (me.height) {
+                    state.height = height;
+                }
+            }
+        }
+        
+        else {
+            if (me.width) {
+                state.width = width;
+            }
+            if (me.height) {
+                state.height = height;
+            }
+        }
+
+        
+        if (state.width == me.initialConfig.width) {
+            delete state.width;
+        }
+        if (state.height == me.initialConfig.height) {
+            delete state.height;
+        }
+
+        
+        if (layout && layout.align && (layout.align.indexOf('stretch') !== -1)) {
+            delete state[layout.perpendicularPrefix];
+        }
+        return state;
+    },
+
+    show: Ext.emptyFn,
+
+    animate: function(animObj) {
+        var me = this,
+            to;
+
+        animObj = animObj || {};
+        to = animObj.to || {};
+
+        if (Ext.fx.Manager.hasFxBlock(me.id)) {
+            return me;
+        }
+        
+        if (!animObj.dynamic && (to.height || to.width)) {
+            var curWidth = me.getWidth(),
+                w = curWidth,
+                curHeight = me.getHeight(),
+                h = curHeight,
+                needsResize = false;
+
+            if (to.height && to.height > curHeight) {
+                h = to.height;
+                needsResize = true;
+            }
+            if (to.width && to.width > curWidth) {
+                w = to.width;
+                needsResize = true;
+            }
+
+            
+            
+            
+            if (needsResize) {
+                var clearWidth = !Ext.isNumber(me.width),
+                    clearHeight = !Ext.isNumber(me.height);
+
+                me.componentLayout.childrenChanged = true;
+                me.setSize(w, h, me.ownerCt);
+                me.el.setSize(curWidth, curHeight);
+                if (clearWidth) {
+                    delete me.width;
+                }
+                if (clearHeight) {
+                    delete me.height;
+                }
+            }
+        }
+        return me.mixins.animate.animate.apply(me, arguments);
+    },
+
+    
+    findLayoutController: function() {
+        return this.findParentBy(function(c) {
+            
+            
+            return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
+        });
+    },
+
+    onShow : function() {
+        
+        var needsLayout = this.needsLayout;
+        if (Ext.isObject(needsLayout)) {
+            this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
+        }
+    },
+
+    constructPlugin: function(plugin) {
+        if (plugin.ptype && typeof plugin.init != 'function') {
+            plugin.cmp = this;
+            plugin = Ext.PluginManager.create(plugin);
+        }
+        else if (typeof plugin == 'string') {
+            plugin = Ext.PluginManager.create({
+                ptype: plugin,
+                cmp: this
+            });
+        }
+        return plugin;
+    },
+
+    
+    constructPlugins: function() {
+        var me = this,
+            plugins = me.plugins,
+            i, len;
+
+        if (plugins) {
+            for (i = 0, len = plugins.length; i < len; i++) {
+                
+                plugins[i] = me.constructPlugin(plugins[i]);
+            }
+        }
+    },
+
+    
+    initPlugin : function(plugin) {
+        plugin.init(this);
+
+        return plugin;
+    },
+
+    
+    doAutoRender: function() {
+        var me = this;
+        if (me.floating) {
+            me.render(document.body);
+        } else {
+            me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
+        }
+    },
+
+    
+    render : function(container, position) {
+        var me = this;
+
+        if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
+
+            
+            
+            me.rendering = true;
+
+            
+            
+            if (me.el) {
+                me.el = Ext.get(me.el);
+            }
+
+            
+            if (me.floating) {
+                me.onFloatRender();
+            }
+
+            container = me.initContainer(container);
+
+            me.onRender(container, position);
+
+            
+            
+            me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
+
+            if (me.overCls) {
+                me.el.hover(me.addOverCls, me.removeOverCls, me);
+            }
+
+            me.fireEvent('render', me);
+
+            me.initContent();
+
+            me.afterRender(container);
+            me.fireEvent('afterrender', me);
+
+            me.initEvents();
+
+            if (me.hidden) {
+                
+                
+                
+                me.el.hide();
+            }
+
+            if (me.disabled) {
+                
+                me.disable(true);
+            }
+
+            
+            delete me.rendering;
+        }
+        return me;
+    },
+
+    
+    onRender : function(container, position) {
+        var me = this,
+            el = me.el,
+            styles = me.initStyles(),
+            renderTpl, renderData, i;
+
+        position = me.getInsertPosition(position);
+
+        if (!el) {
+            if (position) {
+                el = Ext.DomHelper.insertBefore(position, me.getElConfig(), true);
+            }
+            else {
+                el = Ext.DomHelper.append(container, me.getElConfig(), true);
+            }
+        }
+        else if (me.allowDomMove !== false) {
+            if (position) {
+                container.dom.insertBefore(el.dom, position);
+            } else {
+                container.dom.appendChild(el.dom);
+            }
+        }
+
+        if (Ext.scopeResetCSS && !me.ownerCt) {
+            
+            if (el.dom == Ext.getBody().dom) {
+                el.parent().addCls(Ext.baseCSSPrefix + 'reset');
+            }
+            else {
+                
+                me.resetEl = el.wrap({
+                    cls: Ext.baseCSSPrefix + 'reset'
+                });
+            }
+        }
+
+        me.setUI(me.ui);
+
+        el.addCls(me.initCls());
+        el.setStyle(styles);
+
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+
+        me.el = el;
+
+        me.initFrame();
+
+        renderTpl = me.initRenderTpl();
+        if (renderTpl) {
+            renderData = me.initRenderData();
+            renderTpl.append(me.getTargetEl(), renderData);
+        }
+
+        me.applyRenderSelectors();
+
+        me.rendered = true;
+    },
+
+    
+    afterRender : function() {
+        var me = this,
+            pos,
+            xy;
+
+        me.getComponentLayout();
+
+        
+        
+        
+        if (me.collapsed || (!me.ownerCt || (me.height || me.width))) {
+            me.setSize(me.width, me.height);
+        } else {
+            
+            
+            
+            
+            me.renderChildren();
+        }
+
+        
+        
+        if (me.floating && (me.x === undefined || me.y === undefined)) {
+            if (me.floatParent) {
+                xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
+                pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
+            } else {
+                xy = me.el.getAlignToXY(me.container, 'c-c');
+                pos = me.container.translatePoints(xy[0], xy[1]);
+            }
+            me.x = me.x === undefined ? pos.left: me.x;
+            me.y = me.y === undefined ? pos.top: me.y;
+        }
+
+        if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
+            me.setPosition(me.x, me.y);
+        }
+
+        if (me.styleHtmlContent) {
+            me.getTargetEl().addCls(me.styleHtmlCls);
+        }
+    },
+
+    
+    registerFloatingItem: function(cmp) {
+        var me = this;
+        if (!me.floatingItems) {
+            me.floatingItems = Ext.create('Ext.ZIndexManager', me);
+        }
+        me.floatingItems.register(cmp);
+    },
+
+    renderChildren: function () {
+        var me = this,
+            layout = me.getComponentLayout();
+
+        me.suspendLayout = true;
+        layout.renderChildren();
+        delete me.suspendLayout;
+    },
+
+    frameCls: Ext.baseCSSPrefix + 'frame',
+
+    frameIdRegex: /[-]frame\d+[TMB][LCR]$/,
+
+    frameElementCls: {
+        tl: [],
+        tc: [],
+        tr: [],
+        ml: [],
+        mc: [],
+        mr: [],
+        bl: [],
+        bc: [],
+        br: []
+    },
+
+    frameTpl: [
+        '<tpl if="top">',
+            '<tpl if="left"><div id="{fgid}TL" class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
+                '<tpl if="right"><div id="{fgid}TR" class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
+                    '<div id="{fgid}TC" class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></div>',
+                '<tpl if="right"></div></tpl>',
+            '<tpl if="left"></div></tpl>',
+        '</tpl>',
+        '<tpl if="left"><div id="{fgid}ML" class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></tpl>',
+            '<tpl if="right"><div id="{fgid}MR" class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
+                '<div id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" role="presentation"></div>',
+            '<tpl if="right"></div></tpl>',
+        '<tpl if="left"></div></tpl>',
+        '<tpl if="bottom">',
+            '<tpl if="left"><div id="{fgid}BL" class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
+                '<tpl if="right"><div id="{fgid}BR" class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-right: {frameWidth}px" role="presentation"></tpl>',
+                    '<div id="{fgid}BC" class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></div>',
+                '<tpl if="right"></div></tpl>',
+            '<tpl if="left"></div></tpl>',
+        '</tpl>'
+    ],
+
+    frameTableTpl: [
+        '<table><tbody>',
+            '<tpl if="top">',
+                '<tr>',
+                    '<tpl if="left"><td id="{fgid}TL" class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left:{frameWidth}px" role="presentation"></td></tpl>',
+                    '<td id="{fgid}TC" class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></td>',
+                    '<tpl if="right"><td id="{fgid}TR" class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
+                '</tr>',
+            '</tpl>',
+            '<tr>',
+                '<tpl if="left"><td id="{fgid}ML" class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
+                '<td id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" style="background-position: 0 0;" role="presentation"></td>',
+                '<tpl if="right"><td id="{fgid}MR" class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
+            '</tr>',
+            '<tpl if="bottom">',
+                '<tr>',
+                    '<tpl if="left"><td id="{fgid}BL" class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
+                    '<td id="{fgid}BC" class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></td>',
+                    '<tpl if="right"><td id="{fgid}BR" class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
+                '</tr>',
+            '</tpl>',
+        '</tbody></table>'
+    ],
+
+    
+    initFrame : function() {
+        if (Ext.supports.CSS3BorderRadius) {
+            return false;
+        }
+
+        var me = this,
+            frameInfo = me.getFrameInfo(),
+            frameWidth = frameInfo.width,
+            frameTpl = me.getFrameTpl(frameInfo.table),
+            frameGenId;
+
+        if (me.frame) {
+            
+            
+            me.frameGenId = frameGenId = (me.frameGenId || 0) + 1;
+            frameGenId = me.id + '-frame' + frameGenId;
+
+            
+            frameTpl.insertFirst(me.el, Ext.apply({}, {
+                fgid:       frameGenId,
+                ui:         me.ui,
+                uiCls:      me.uiCls,
+                frameCls:   me.frameCls,
+                baseCls:    me.baseCls,
+                frameWidth: frameWidth,
+                top:        !!frameInfo.top,
+                left:       !!frameInfo.left,
+                right:      !!frameInfo.right,
+                bottom:     !!frameInfo.bottom
+            }, me.getFramePositions(frameInfo)));
+
+            
+            me.frameBody = me.el.down('.' + me.frameCls + '-mc');
+
+            
+            me.removeChildEls(function (c) {
+                return c.id && me.frameIdRegex.test(c.id);
+            });
+
+            
+            Ext.each(['TL','TC','TR','ML','MC','MR','BL','BC','BR'], function (suffix) {
+                me.childEls.push({ name: 'frame' + suffix, id: frameGenId + suffix });
+            });
+        }
+    },
+
+    updateFrame: function() {
+        if (Ext.supports.CSS3BorderRadius) {
+            return false;
+        }
+
+        var me = this,
+            wasTable = this.frameSize && this.frameSize.table,
+            oldFrameTL = this.frameTL,
+            oldFrameBL = this.frameBL,
+            oldFrameML = this.frameML,
+            oldFrameMC = this.frameMC,
+            newMCClassName;
+
+        this.initFrame();
+
+        if (oldFrameMC) {
+            if (me.frame) {
+                
+                delete me.frameTL;
+                delete me.frameTC;
+                delete me.frameTR;
+                delete me.frameML;
+                delete me.frameMC;
+                delete me.frameMR;
+                delete me.frameBL;
+                delete me.frameBC;
+                delete me.frameBR;
+                this.applyRenderSelectors();
+
+                
+                newMCClassName = this.frameMC.dom.className;
+
+                
+                oldFrameMC.insertAfter(this.frameMC);
+                this.frameMC.remove();
+
+                
+                this.frameBody = this.frameMC = oldFrameMC;
+
+                
+                oldFrameMC.dom.className = newMCClassName;
+
+                
+                if (wasTable) {
+                    me.el.query('> table')[1].remove();
+                }
+                else {
+                    if (oldFrameTL) {
+                        oldFrameTL.remove();
+                    }
+                    if (oldFrameBL) {
+                        oldFrameBL.remove();
+                    }
+                    oldFrameML.remove();
+                }
+            }
+            else {
+                
+
+            }
+        }
+        else if (me.frame) {
+            this.applyRenderSelectors();
+        }
+    },
+
+    getFrameInfo: function() {
+        if (Ext.supports.CSS3BorderRadius) {
+            return false;
+        }
+
+        var me = this,
+            left = me.el.getStyle('background-position-x'),
+            top = me.el.getStyle('background-position-y'),
+            info, frameInfo = false, max;
+
+        
+        
+        if (!left && !top) {
+            info = me.el.getStyle('background-position').split(' ');
+            left = info[0];
+            top = info[1];
+        }
+
+        
+        
+        
+        if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
+            max = Math.max;
+
+            frameInfo = {
+                
+                table: left.substr(0, 3) == '110',
+
+                
+                vertical: top.substr(0, 3) == '110',
+
+                
+                top:    max(left.substr(3, 2), left.substr(5, 2)),
+                right:  max(left.substr(5, 2), top.substr(3, 2)),
+                bottom: max(top.substr(3, 2), top.substr(5, 2)),
+                left:   max(top.substr(5, 2), left.substr(3, 2))
+            };
+
+            frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
+
+            
+            me.el.setStyle('background-image', 'none');
+        }
+
+        
+        
+        if (me.frame === true && !frameInfo) {
+        }
+
+        me.frame = me.frame || !!frameInfo;
+        me.frameSize = frameInfo || false;
+
+        return frameInfo;
+    },
+
+    getFramePositions: function(frameInfo) {
+        var me = this,
+            frameWidth = frameInfo.width,
+            dock = me.dock,
+            positions, tc, bc, ml, mr;
+
+        if (frameInfo.vertical) {
+            tc = '0 -' + (frameWidth * 0) + 'px';
+            bc = '0 -' + (frameWidth * 1) + 'px';
+
+            if (dock && dock == "right") {
+                tc = 'right -' + (frameWidth * 0) + 'px';
+                bc = 'right -' + (frameWidth * 1) + 'px';
+            }
+
+            positions = {
+                tl: '0 -' + (frameWidth * 0) + 'px',
+                tr: '0 -' + (frameWidth * 1) + 'px',
+                bl: '0 -' + (frameWidth * 2) + 'px',
+                br: '0 -' + (frameWidth * 3) + 'px',
+
+                ml: '-' + (frameWidth * 1) + 'px 0',
+                mr: 'right 0',
+
+                tc: tc,
+                bc: bc
+            };
+        } else {
+            ml = '-' + (frameWidth * 0) + 'px 0';
+            mr = 'right 0';
+
+            if (dock && dock == "bottom") {
+                ml = 'left bottom';
+                mr = 'right bottom';
+            }
+
+            positions = {
+                tl: '0 -' + (frameWidth * 2) + 'px',
+                tr: 'right -' + (frameWidth * 3) + 'px',
+                bl: '0 -' + (frameWidth * 4) + 'px',
+                br: 'right -' + (frameWidth * 5) + 'px',
+
+                ml: ml,
+                mr: mr,
+
+                tc: '0 -' + (frameWidth * 0) + 'px',
+                bc: '0 -' + (frameWidth * 1) + 'px'
+            };
+        }
+
+        return positions;
+    },
+
+    
+    getFrameTpl : function(table) {
+        return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
+    },
+
+    
+    initCls: function() {
+        var me = this,
+            cls = [];
+
+        cls.push(me.baseCls);
+
+        if (Ext.isDefined(me.cmpCls)) {
+            if (Ext.isDefined(Ext.global.console)) {
+                Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
+            }
+            me.componentCls = me.cmpCls;
+            delete me.cmpCls;
+        }
+
+        if (me.componentCls) {
+            cls.push(me.componentCls);
+        } else {
+            me.componentCls = me.baseCls;
+        }
+        if (me.cls) {
+            cls.push(me.cls);
+            delete me.cls;
+        }
+
+        return cls.concat(me.additionalCls);
+    },
+
+    
+    setUI: function(ui) {
+        var me = this,
+            oldUICls = Ext.Array.clone(me.uiCls),
+            newUICls = [],
+            classes = [],
+            cls,
+            i;
+
+        
+        for (i = 0; i < oldUICls.length; i++) {
+            cls = oldUICls[i];
+
+            classes = classes.concat(me.removeClsWithUI(cls, true));
+            newUICls.push(cls);
+        }
+
+        if (classes.length) {
+            me.removeCls(classes);
+        }
+
+        
+        me.removeUIFromElement();
+
+        
+        me.ui = ui;
+
+        
+        me.addUIToElement();
+
+        
+        classes = [];
+        for (i = 0; i < newUICls.length; i++) {
+            cls = newUICls[i];
+            classes = classes.concat(me.addClsWithUI(cls, true));
+        }
+
+        if (classes.length) {
+            me.addCls(classes);
+        }
+    },
+
+    
+    addClsWithUI: function(cls, skip) {
+        var me = this,
+            classes = [],
+            i;
+
+        if (!Ext.isArray(cls)) {
+            cls = [cls];
+        }
+
+        for (i = 0; i < cls.length; i++) {
+            if (cls[i] && !me.hasUICls(cls[i])) {
+                me.uiCls = Ext.Array.clone(me.uiCls);
+                me.uiCls.push(cls[i]);
+
+                classes = classes.concat(me.addUIClsToElement(cls[i]));
+            }
+        }
+
+        if (skip !== true) {
+            me.addCls(classes);
+        }
+
+        return classes;
+    },
+
+    
+    removeClsWithUI: function(cls, skip) {
+        var me = this,
+            classes = [],
+            i;
+
+        if (!Ext.isArray(cls)) {
+            cls = [cls];
+        }
+
+        for (i = 0; i < cls.length; i++) {
+            if (cls[i] && me.hasUICls(cls[i])) {
+                me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
+
+                classes = classes.concat(me.removeUIClsFromElement(cls[i]));
+            }
+        }
+
+        if (skip !== true) {
+            me.removeCls(classes);
+        }
+
+        return classes;
+    },
+
+    
+    hasUICls: function(cls) {
+        var me = this,
+            uiCls = me.uiCls || [];
+
+        return Ext.Array.contains(uiCls, cls);
+    },
+
+    
+    addUIClsToElement: function(cls, force) {
+        var me = this,
+            result = [],
+            frameElementCls = me.frameElementCls;
+
+        result.push(Ext.baseCSSPrefix + cls);
+        result.push(me.baseCls + '-' + cls);
+        result.push(me.baseCls + '-' + me.ui + '-' + cls);
+
+        if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
+            
+            var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
+                classes, i, j, el;
+
+            
+            for (i = 0; i < els.length; i++) {
+                el = me['frame' + els[i].toUpperCase()];
+                classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]];
+                if (el && el.dom) {
+                    el.addCls(classes);
+                } else {
+                    for (j = 0; j < classes.length; j++) {
+                        if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) {
+                            frameElementCls[els[i]].push(classes[j]);
+                        }
+                    }
+                }
+            }
+        }
+
+        me.frameElementCls = frameElementCls;
+
+        return result;
+    },
+
+    
+    removeUIClsFromElement: function(cls, force) {
+        var me = this,
+            result = [],
+            frameElementCls = me.frameElementCls;
+
+        result.push(Ext.baseCSSPrefix + cls);
+        result.push(me.baseCls + '-' + cls);
+        result.push(me.baseCls + '-' + me.ui + '-' + cls);
+
+        if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
+            
+            var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
+                i, el;
+            cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i];
+            
+            for (i = 0; i < els.length; i++) {
+                el = me['frame' + els[i].toUpperCase()];
+                if (el && el.dom) {
+                    el.removeCls(cls);
+                } else {
+                    Ext.Array.remove(frameElementCls[els[i]], cls);
+                }
+            }
+        }
+
+        me.frameElementCls = frameElementCls;
+
+        return result;
+    },
+
+    
+    addUIToElement: function(force) {
+        var me = this,
+            frameElementCls = me.frameElementCls;
+
+        me.addCls(me.baseCls + '-' + me.ui);
+
+        if (me.frame && !Ext.supports.CSS3BorderRadius) {
+            
+            var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
+                i, el, cls;
+
+            
+            for (i = 0; i < els.length; i++) {
+                el = me['frame' + els[i].toUpperCase()];
+                cls = me.baseCls + '-' + me.ui + '-' + els[i];
+                if (el) {
+                    el.addCls(cls);
+                } else {
+                    if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
+                        frameElementCls[els[i]].push(cls);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    removeUIFromElement: function() {
+        var me = this,
+            frameElementCls = me.frameElementCls;
+
+        me.removeCls(me.baseCls + '-' + me.ui);
+
+        if (me.frame && !Ext.supports.CSS3BorderRadius) {
+            
+            var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
+                i, j, el, cls;
+
+            
+            for (i = 0; i < els.length; i++) {
+                el = me['frame' + els[i].toUpperCase()];
+                cls = me.baseCls + '-' + me.ui + '-' + els[i];
+
+                if (el) {
+                    el.removeCls(cls);
+                } else {
+                    Ext.Array.remove(frameElementCls[els[i]], cls);
+                }
+            }
+        }
+    },
+
+    getElConfig : function() {
+        if (Ext.isString(this.autoEl)) {
+            this.autoEl = {
+                tag: this.autoEl
+            };
+        }
+
+        var result = this.autoEl || {tag: 'div'};
+        result.id = this.id;
+        return result;
+    },
+
+    
+    getInsertPosition: function(position) {
+        
+        if (position !== undefined) {
+            if (Ext.isNumber(position)) {
+                position = this.container.dom.childNodes[position];
+            }
+            else {
+                position = Ext.getDom(position);
+            }
+        }
+
+        return position;
+    },
+
+    
+    initContainer: function(container) {
+        var me = this;
+
+        
+        
+        
+        if (!container && me.el) {
+            container = me.el.dom.parentNode;
+            me.allowDomMove = false;
+        }
+
+        me.container = Ext.get(container);
+
+        if (me.ctCls) {
+            me.container.addCls(me.ctCls);
+        }
+
+        return me.container;
+    },
+
+    
+    initRenderData: function() {
+        var me = this;
+
+        return Ext.applyIf(me.renderData, {
+            id: me.id,
+            ui: me.ui,
+            uiCls: me.uiCls,
+            baseCls: me.baseCls,
+            componentCls: me.componentCls,
+            frame: me.frame
+        });
+    },
+
+    
+    getTpl: function(name) {
+        var me = this,
+            prototype = me.self.prototype,
+            ownerPrototype,
+            tpl;
+
+        if (me.hasOwnProperty(name)) {
+            tpl = me[name];
+            if (tpl && !(tpl instanceof Ext.XTemplate)) {
+                me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
+            }
+
+            return me[name];
+        }
+
+        if (!(prototype[name] instanceof Ext.XTemplate)) {
+            ownerPrototype = prototype;
+
+            do {
+                if (ownerPrototype.hasOwnProperty(name)) {
+                    tpl = ownerPrototype[name];
+                    if (tpl && !(tpl instanceof Ext.XTemplate)) {
+                        ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
+                        break;
+                    }
+                }
+
+                ownerPrototype = ownerPrototype.superclass;
+            } while (ownerPrototype);
+        }
+
+        return prototype[name];
+    },
+
+    
+    initRenderTpl: function() {
+        return this.getTpl('renderTpl');
+    },
+
+    
+    initStyles: function() {
+        var style = {},
+            me = this,
+            Element = Ext.Element;
+
+        if (Ext.isString(me.style)) {
+            style = Element.parseStyles(me.style);
+        } else {
+            style = Ext.apply({}, me.style);
+        }
+
+        
+        
+        if (me.padding !== undefined) {
+            style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
+        }
+
+        if (me.margin !== undefined) {
+            style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
+        }
+
+        delete me.style;
+        return style;
+    },
+
+    
+    initContent: function() {
+        var me = this,
+            target = me.getTargetEl(),
+            contentEl,
+            pre;
+
+        if (me.html) {
+            target.update(Ext.DomHelper.markup(me.html));
+            delete me.html;
+        }
+
+        if (me.contentEl) {
+            contentEl = Ext.get(me.contentEl);
+            pre = Ext.baseCSSPrefix;
+            contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
+            target.appendChild(contentEl.dom);
+        }
+
+        if (me.tpl) {
+            
+            if (!me.tpl.isTemplate) {
+                me.tpl = Ext.create('Ext.XTemplate', me.tpl);
+            }
+
+            if (me.data) {
+                me.tpl[me.tplWriteMode](target, me.data);
+                delete me.data;
+            }
+        }
+    },
+
+    
+    initEvents : function() {
+        var me = this,
+            afterRenderEvents = me.afterRenderEvents,
+            el,
+            property,
+            fn = function(listeners){
+                me.mon(el, listeners);
+            };
+        if (afterRenderEvents) {
+            for (property in afterRenderEvents) {
+                if (afterRenderEvents.hasOwnProperty(property)) {
+                    el = me[property];
+                    if (el && el.on) {
+                        Ext.each(afterRenderEvents[property], fn);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    addChildEls: function () {
+        var me = this,
+            childEls = me.childEls || (me.childEls = []);
+
+        childEls.push.apply(childEls, arguments);
+    },
+
+    
+    removeChildEls: function (testFn) {
+        var me = this,
+            old = me.childEls,
+            keepers = (me.childEls = []),
+            n, i, cel;
+
+        for (i = 0, n = old.length; i < n; ++i) {
+            cel = old[i];
+            if (!testFn(cel)) {
+                keepers.push(cel);
+            }
+        }
+    },
+
+    
+    applyRenderSelectors: function() {
+        var me = this,
+            childEls = me.childEls,
+            selectors = me.renderSelectors,
+            el = me.el,
+            dom = el.dom,
+            baseId, childName, childId, i, selector;
+
+        if (childEls) {
+            baseId = me.id + '-';
+            for (i = childEls.length; i--; ) {
+                childName = childId = childEls[i];
+                if (typeof(childName) != 'string') {
+                    childId = childName.id || (baseId + childName.itemId);
+                    childName = childName.name;
+                } else {
+                    childId = baseId + childId;
+                }
+
+                
+                
+                me[childName] = el.getById(childId);
+            }
+        }
+
+        
+        
+        
+        if (selectors) {
+            for (selector in selectors) {
+                if (selectors.hasOwnProperty(selector) && selectors[selector]) {
+                    me[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], dom));
+                }
+            }
+        }
+    },
+
+    
+    is: function(selector) {
+        return Ext.ComponentQuery.is(this, selector);
+    },
+
+    
+    up: function(selector) {
+        var result = this.ownerCt;
+        if (selector) {
+            for (; result; result = result.ownerCt) {
+                if (Ext.ComponentQuery.is(result, selector)) {
+                    return result;
+                }
+            }
+        }
+        return result;
+    },
+
+    
+    nextSibling: function(selector) {
+        var o = this.ownerCt, it, last, idx, c;
+        if (o) {
+            it = o.items;
+            idx = it.indexOf(this) + 1;
+            if (idx) {
+                if (selector) {
+                    for (last = it.getCount(); idx < last; idx++) {
+                        if ((c = it.getAt(idx)).is(selector)) {
+                            return c;
+                        }
+                    }
+                } else {
+                    if (idx < it.getCount()) {
+                        return it.getAt(idx);
+                    }
+                }
+            }
+        }
+        return null;
+    },
+
+    
+    previousSibling: function(selector) {
+        var o = this.ownerCt, it, idx, c;
+        if (o) {
+            it = o.items;
+            idx = it.indexOf(this);
+            if (idx != -1) {
+                if (selector) {
+                    for (--idx; idx >= 0; idx--) {
+                        if ((c = it.getAt(idx)).is(selector)) {
+                            return c;
+                        }
+                    }
+                } else {
+                    if (idx) {
+                        return it.getAt(--idx);
+                    }
+                }
+            }
+        }
+        return null;
+    },
+
+    
+    previousNode: function(selector, includeSelf) {
+        var node = this,
+            result,
+            it, len, i;
+
+        
+        if (includeSelf && node.is(selector)) {
+            return node;
+        }
+
+        result = this.prev(selector);
+        if (result) {
+            return result;
+        }
+
+        if (node.ownerCt) {
+            for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
+                if (it[i].query) {
+                    result = it[i].query(selector);
+                    result = result[result.length - 1];
+                    if (result) {
+                        return result;
+                    }
+                }
+            }
+            return node.ownerCt.previousNode(selector, true);
+        }
+    },
+
+    
+    nextNode: function(selector, includeSelf) {
+        var node = this,
+            result,
+            it, len, i;
+
+        
+        if (includeSelf && node.is(selector)) {
+            return node;
+        }
+
+        result = this.next(selector);
+        if (result) {
+            return result;
+        }
+
+        if (node.ownerCt) {
+            for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
+                if (it[i].down) {
+                    result = it[i].down(selector);
+                    if (result) {
+                        return result;
+                    }
+                }
+            }
+            return node.ownerCt.nextNode(selector);
+        }
+    },
+
+    
+    getId : function() {
+        return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
+    },
+
+    getItemId : function() {
+        return this.itemId || this.id;
+    },
+
+    
+    getEl : function() {
+        return this.el;
+    },
+
+    
+    getTargetEl: function() {
+        return this.frameBody || this.el;
+    },
+
+    
+    isXType: function(xtype, shallow) {
+        
+        if (Ext.isFunction(xtype)) {
+            xtype = xtype.xtype;
+            
+        } else if (Ext.isObject(xtype)) {
+            xtype = xtype.statics().xtype;
+            
+        }
+
+        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
+    },
+
+    
+    getXTypes: function() {
+        var self = this.self,
+            xtypes, parentPrototype, parentXtypes;
+
+        if (!self.xtypes) {
+            xtypes = [];
+            parentPrototype = this;
+
+            while (parentPrototype) {
+                parentXtypes = parentPrototype.xtypes;
+
+                if (parentXtypes !== undefined) {
+                    xtypes.unshift.apply(xtypes, parentXtypes);
+                }
+
+                parentPrototype = parentPrototype.superclass;
+            }
+
+            self.xtypeChain = xtypes;
+            self.xtypes = xtypes.join('/');
+        }
+
+        return self.xtypes;
+    },
+
+    
+    update : function(htmlOrData, loadScripts, cb) {
+        var me = this;
+
+        if (me.tpl && !Ext.isString(htmlOrData)) {
+            me.data = htmlOrData;
+            if (me.rendered) {
+                me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
+            }
+        } else {
+            me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
+            if (me.rendered) {
+                me.getTargetEl().update(me.html, loadScripts, cb);
+            }
+        }
+
+        if (me.rendered) {
+            me.doComponentLayout();
+        }
+    },
+
+    
+    setVisible : function(visible) {
+        return this[visible ? 'show': 'hide']();
+    },
+
+    
+    isVisible: function(deep) {
+        var me = this,
+            child = me,
+            visible = !me.hidden,
+            ancestor = me.ownerCt;
+
+        
+        me.hiddenAncestor = false;
+        if (me.destroyed) {
+            return false;
+        }
+
+        if (deep && visible && me.rendered && ancestor) {
+            while (ancestor) {
+                
+                
+                
+                
+                if (ancestor.hidden || (ancestor.collapsed &&
+                        !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
+                    
+                    me.hiddenAncestor = ancestor;
+                    visible = false;
+                    break;
+                }
+                child = ancestor;
+                ancestor = ancestor.ownerCt;
+            }
+        }
+        return visible;
+    },
+
+    
+    enable: function(silent) {
+        var me = this;
+
+        if (me.rendered) {
+            me.el.removeCls(me.disabledCls);
+            me.el.dom.disabled = false;
+            me.onEnable();
+        }
+
+        me.disabled = false;
+
+        if (silent !== true) {
+            me.fireEvent('enable', me);
+        }
+
+        return me;
+    },
+
+    
+    disable: function(silent) {
+        var me = this;
+
+        if (me.rendered) {
+            me.el.addCls(me.disabledCls);
+            me.el.dom.disabled = true;
+            me.onDisable();
+        }
+
+        me.disabled = true;
+
+        if (silent !== true) {
+            me.fireEvent('disable', me);
+        }
+
+        return me;
+    },
+
+    
+    onEnable: function() {
+        if (this.maskOnDisable) {
+            this.el.unmask();
+        }
+    },
+
+    
+    onDisable : function() {
+        if (this.maskOnDisable) {
+            this.el.mask();
+        }
+    },
+
+    
+    isDisabled : function() {
+        return this.disabled;
+    },
+
+    
+    setDisabled : function(disabled) {
+        return this[disabled ? 'disable': 'enable']();
+    },
+
+    
+    isHidden : function() {
+        return this.hidden;
+    },
+
+    
+    addCls : function(className) {
+        var me = this;
+        if (!className) {
+            return me;
+        }
+        if (!Ext.isArray(className)){
+            className = className.replace(me.trimRe, '').split(me.spacesRe);
+        }
+        if (me.rendered) {
+            me.el.addCls(className);
+        }
+        else {
+            me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
+        }
+        return me;
+    },
+
+    
+    addClass : function() {
+        return this.addCls.apply(this, arguments);
+    },
+
+    
+    removeCls : function(className) {
+        var me = this;
+
+        if (!className) {
+            return me;
+        }
+        if (!Ext.isArray(className)){
+            className = className.replace(me.trimRe, '').split(me.spacesRe);
+        }
+        if (me.rendered) {
+            me.el.removeCls(className);
+        }
+        else if (me.additionalCls.length) {
+            Ext.each(className, function(cls) {
+                Ext.Array.remove(me.additionalCls, cls);
+            });
+        }
+        return me;
+    },
+
+
+    addOverCls: function() {
+        var me = this;
+        if (!me.disabled) {
+            me.el.addCls(me.overCls);
+        }
+    },
+
+    removeOverCls: function() {
+        this.el.removeCls(this.overCls);
+    },
+
+    addListener : function(element, listeners, scope, options) {
+        var me = this,
+            fn,
+            option;
+
+        if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
+            if (options.element) {
+                fn = listeners;
+
+                listeners = {};
+                listeners[element] = fn;
+                element = options.element;
+                if (scope) {
+                    listeners.scope = scope;
+                }
+
+                for (option in options) {
+                    if (options.hasOwnProperty(option)) {
+                        if (me.eventOptionsRe.test(option)) {
+                            listeners[option] = options[option];
+                        }
+                    }
+                }
+            }
+
+            
+            
+            if (me[element] && me[element].on) {
+                me.mon(me[element], listeners);
+            } else {
+                me.afterRenderEvents = me.afterRenderEvents || {};
+                if (!me.afterRenderEvents[element]) {
+                    me.afterRenderEvents[element] = [];
+                }
+                me.afterRenderEvents[element].push(listeners);
+            }
+        }
+
+        return me.mixins.observable.addListener.apply(me, arguments);
+    },
+
+    
+    removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
+        var me = this,
+            element = managedListener.options ? managedListener.options.element : null;
+
+        if (element) {
+            element = me[element];
+            if (element && element.un) {
+                if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
+                    element.un(managedListener.ename, managedListener.fn, managedListener.scope);
+                    if (!isClear) {
+                        Ext.Array.remove(me.managedListeners, managedListener);
+                    }
+                }
+            }
+        } else {
+            return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
+        }
+    },
+
+    
+    getBubbleTarget : function() {
+        return this.ownerCt;
+    },
+
+    
+    isFloating : function() {
+        return this.floating;
+    },
+
+    
+    isDraggable : function() {
+        return !!this.draggable;
+    },
+
+    
+    isDroppable : function() {
+        return !!this.droppable;
+    },
+
+    
+    onAdded : function(container, pos) {
+        this.ownerCt = container;
+        this.fireEvent('added', this, container, pos);
+    },
+
+    
+    onRemoved : function() {
+        var me = this;
+
+        me.fireEvent('removed', me, me.ownerCt);
+        delete me.ownerCt;
+    },
+
+    
+    beforeDestroy : Ext.emptyFn,
+    
+    
+    onResize : Ext.emptyFn,
+
+    
+    setSize : function(width, height) {
+        var me = this,
+            layoutCollection;
+
+        
+        if (Ext.isObject(width)) {
+            height = width.height;
+            width  = width.width;
+        }
+
+        
+        if (Ext.isNumber(width)) {
+            width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
+        }
+        if (Ext.isNumber(height)) {
+            height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
+        }
+
+        if (!me.rendered || !me.isVisible()) {
+            
+            if (me.hiddenAncestor) {
+                layoutCollection = me.hiddenAncestor.layoutOnShow;
+                layoutCollection.remove(me);
+                layoutCollection.add(me);
+            }
+            me.needsLayout = {
+                width: width,
+                height: height,
+                isSetSize: true
+            };
+            if (!me.rendered) {
+                me.width  = (width !== undefined) ? width : me.width;
+                me.height = (height !== undefined) ? height : me.height;
+            }
+            return me;
+        }
+        me.doComponentLayout(width, height, true);
+
+        return me;
+    },
+
+    isFixedWidth: function() {
+        var me = this,
+            layoutManagedWidth = me.layoutManagedWidth;
+
+        if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
+            return true;
+        }
+        if (layoutManagedWidth == 2) {
+            return false;
+        }
+        return (me.ownerCt && me.ownerCt.isFixedWidth());
+    },
+
+    isFixedHeight: function() {
+        var me = this,
+            layoutManagedHeight = me.layoutManagedHeight;
+
+        if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
+            return true;
+        }
+        if (layoutManagedHeight == 2) {
+            return false;
+        }
+        return (me.ownerCt && me.ownerCt.isFixedHeight());
+    },
+
+    setCalculatedSize : function(width, height, callingContainer) {
+        var me = this,
+            layoutCollection;
+
+        
+        if (Ext.isObject(width)) {
+            callingContainer = width.ownerCt;
+            height = width.height;
+            width  = width.width;
+        }
+
+        
+        if (Ext.isNumber(width)) {
+            width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
+        }
+        if (Ext.isNumber(height)) {
+            height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
+        }
+
+        if (!me.rendered || !me.isVisible()) {
+            
+            if (me.hiddenAncestor) {
+                layoutCollection = me.hiddenAncestor.layoutOnShow;
+                layoutCollection.remove(me);
+                layoutCollection.add(me);
+            }
+            me.needsLayout = {
+                width: width,
+                height: height,
+                isSetSize: false,
+                ownerCt: callingContainer
+            };
+            return me;
+        }
+        me.doComponentLayout(width, height, false, callingContainer);
+
+        return me;
+    },
+
+    
+    doComponentLayout : function(width, height, isSetSize, callingContainer) {
+        var me = this,
+            componentLayout = me.getComponentLayout(),
+            lastComponentSize = componentLayout.lastComponentSize || {
+                width: undefined,
+                height: undefined
+            };
+
+        
+        
+        
+        if (me.rendered && componentLayout) {
+            
+            if (!Ext.isDefined(width)) {
+                if (me.isFixedWidth()) {
+                    width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width;
+                }
+            }
+            
+            if (!Ext.isDefined(height)) {
+                if (me.isFixedHeight()) {
+                    height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height;
+                }
+            }
+
+            if (isSetSize) {
+                me.width = width;
+                me.height = height;
+            }
+
+            componentLayout.layout(width, height, isSetSize, callingContainer);
+        }
+
+        return me;
+    },
+
+    
+    forceComponentLayout: function () {
+        this.doComponentLayout();
+    },
+
+    
+    setComponentLayout : function(layout) {
+        var currentLayout = this.componentLayout;
+        if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
+            currentLayout.setOwner(null);
+        }
+        this.componentLayout = layout;
+        layout.setOwner(this);
+    },
+
+    getComponentLayout : function() {
+        var me = this;
+
+        if (!me.componentLayout || !me.componentLayout.isLayout) {
+            me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
+        }
+        return me.componentLayout;
+    },
+
+    
+    afterComponentLayout: function(width, height, isSetSize, callingContainer) {
+        var me = this,
+            layout = me.componentLayout,
+            oldSize = me.preLayoutSize;
+
+        ++me.componentLayoutCounter;
+        if (!oldSize || ((width !== oldSize.width) || (height !== oldSize.height))) {
+            me.fireEvent('resize', me, width, height);
+        }
+    },
+
+    
+    beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
+        this.preLayoutSize = this.componentLayout.lastComponentSize;
+        return true;
+    },
+
+    
+    setPosition : function(x, y) {
+        var me = this;
+
+        if (Ext.isObject(x)) {
+            y = x.y;
+            x = x.x;
+        }
+
+        if (!me.rendered) {
+            return me;
+        }
+
+        if (x !== undefined || y !== undefined) {
+            me.el.setBox(x, y);
+            me.onPosition(x, y);
+            me.fireEvent('move', me, x, y);
+        }
+        return me;
+    },
+
+    
+    onPosition: Ext.emptyFn,
+
+    
+    setWidth : function(width) {
+        return this.setSize(width);
+    },
+
+    
+    setHeight : function(height) {
+        return this.setSize(undefined, height);
+    },
+
+    
+    getSize : function() {
+        return this.el.getSize();
+    },
+
+    
+    getWidth : function() {
+        return this.el.getWidth();
+    },
+
+    
+    getHeight : function() {
+        return this.el.getHeight();
+    },
+
+    
+    getLoader: function(){
+        var me = this,
+            autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
+            loader = me.loader || autoLoad;
+
+        if (loader) {
+            if (!loader.isLoader) {
+                me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
+                    target: me,
+                    autoLoad: autoLoad
+                }, loader));
+            } else {
+                loader.setTarget(me);
+            }
+            return me.loader;
+
+        }
+        return null;
+    },
+
+    
+    setLoading : function(load, targetEl) {
+        var me = this,
+            config;
+
+        if (me.rendered) {
+            if (load !== false && !me.collapsed) {
+                if (Ext.isObject(load)) {
+                    config = load;
+                }
+                else if (Ext.isString(load)) {
+                    config = {msg: load};
+                }
+                else {
+                    config = {};
+                }
+                me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
+                me.loadMask.show();
+            } else if (me.loadMask) {
+                Ext.destroy(me.loadMask);
+                me.loadMask = null;
+            }
+        }
+
+        return me.loadMask;
+    },
+
+    
+    setDocked : function(dock, layoutParent) {
+        var me = this;
+
+        me.dock = dock;
+        if (layoutParent && me.ownerCt && me.rendered) {
+            me.ownerCt.doComponentLayout();
+        }
+        return me;
+    },
+
+    onDestroy : function() {
+        var me = this;
+
+        if (me.monitorResize && Ext.EventManager.resizeEvent) {
+            Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
+        }
+        
+        Ext.destroy(
+            me.componentLayout,
+            me.loadMask,
+            me.floatingItems
+        );
+    },
+
+    
+    cleanElementRefs: function(){
+        var me = this,
+            i = 0,
+            childEls = me.childEls,
+            selectors = me.renderSelectors,
+            selector,
+            name,
+            len;
+
+        if (me.rendered) {
+            if (childEls) {
+                for (len = childEls.length; i < len; ++i) {
+                    name = childEls[i];
+                    if (typeof(name) != 'string') {
+                        name = name.name;
+                    }
+                    delete me[name];
+                }
+            }
+
+            if (selectors) {
+                for (selector in selectors) {
+                    if (selectors.hasOwnProperty(selector)) {
+                        delete me[selector];
+                    }
+                }
+            }
+        }
+        delete me.rendered;
+        delete me.el;
+        delete me.frameBody;
+    },
+
+    
+    destroy : function() {
+        var me = this;
+
+        if (!me.isDestroyed) {
+            if (me.fireEvent('beforedestroy', me) !== false) {
+                me.destroying = true;
+                me.beforeDestroy();
+
+                if (me.floating) {
+                    delete me.floatParent;
+                    
+                    
+                    if (me.zIndexManager) {
+                        me.zIndexManager.unregister(me);
+                    }
+                } else if (me.ownerCt && me.ownerCt.remove) {
+                    me.ownerCt.remove(me, false);
+                }
+
+                me.onDestroy();
+
+                
+                Ext.destroy(me.plugins);
+
+                if (me.rendered) {
+                    me.el.remove();
+                }
+
+                me.fireEvent('destroy', me);
+                Ext.ComponentManager.unregister(me);
+
+                me.mixins.state.destroy.call(me);
+
+                me.clearListeners();
+                
+                me.cleanElementRefs();
+                me.destroying = false;
+                me.isDestroyed = true;
+            }
+        }
+    },
+
+    
+    getPlugin: function(pluginId) {
+        var i = 0,
+            plugins = this.plugins,
+            ln = plugins.length;
+        for (; i < ln; i++) {
+            if (plugins[i].pluginId === pluginId) {
+                return plugins[i];
+            }
+        }
+    },
+
+    
+    isDescendantOf: function(container) {
+        return !!this.findParentBy(function(p){
+            return p === container;
+        });
+    }
+}, function() {
+    this.createAlias({
+        on: 'addListener',
+        prev: 'previousSibling',
+        next: 'nextSibling'
+    });
+});
+
+
+Ext.define('Ext.AbstractPlugin', {
+    disabled: false,
+
+    constructor: function(config) {
+        Ext.apply(this, config);
+    },
+
+    getCmp: function() {
+        return this.cmp;
+    },
+
+    
+    init: Ext.emptyFn,
+
+    
+    destroy: Ext.emptyFn,
+
+    
+    enable: function() {
+        this.disabled = false;
+    },
+
+    
+    disable: function() {
+        this.disabled = true;
+    }
+});
+
+Ext.define('Ext.data.Connection', {
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    statics: {
+        requestId: 0
+    },
+
+    url: null,
+    async: true,
+    method: null,
+    username: '',
+    password: '',
+
+    
+    disableCaching: true,
+
+    
+    withCredentials: false,
+
+    
+    cors: false,
+
+    
+    disableCachingParam: '_dc',
+
+    
+    timeout : 30000,
+
+    
+
+    useDefaultHeader : true,
+    defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',
+    useDefaultXhrHeader : true,
+    defaultXhrHeader : 'XMLHttpRequest',
+
+    constructor : function(config) {
+        config = config || {};
+        Ext.apply(this, config);
+
+        this.addEvents(
+            
+            'beforerequest',
+            
+            'requestcomplete',
+            
+            'requestexception'
+        );
+        this.requests = {};
+        this.mixins.observable.constructor.call(this);
+    },
+
+    
+    request : function(options) {
+        options = options || {};
+        var me = this,
+            scope = options.scope || window,
+            username = options.username || me.username,
+            password = options.password || me.password || '',
+            async,
+            requestOptions,
+            request,
+            headers,
+            xhr;
+
+        if (me.fireEvent('beforerequest', me, options) !== false) {
+
+            requestOptions = me.setOptions(options, scope);
+
+            if (this.isFormUpload(options) === true) {
+                this.upload(options.form, requestOptions.url, requestOptions.data, options);
+                return null;
+            }
+
+            
+            if (options.autoAbort === true || me.autoAbort) {
+                me.abort();
+            }
+
+            
+
+            if ((options.cors === true || me.cors === true) && Ext.isIe && Ext.ieVersion >= 8) {
+                xhr = new XDomainRequest();
+            } else {
+                xhr = this.getXhrInstance();
+            }
+
+            async = options.async !== false ? (options.async || me.async) : false;
+
+            
+            if (username) {
+                xhr.open(requestOptions.method, requestOptions.url, async, username, password);
+            } else {
+                xhr.open(requestOptions.method, requestOptions.url, async);
+            }
+
+            if (options.withCredentials === true || me.withCredentials === true) {
+                xhr.withCredentials = true;
+            }
+
+            headers = me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params);
+
+            
+            request = {
+                id: ++Ext.data.Connection.requestId,
+                xhr: xhr,
+                headers: headers,
+                options: options,
+                async: async,
+                timeout: setTimeout(function() {
+                    request.timedout = true;
+                    me.abort(request);
+                }, options.timeout || me.timeout)
+            };
+            me.requests[request.id] = request;
+            me.latestId = request.id;
+            
+            if (async) {
+                xhr.onreadystatechange = Ext.Function.bind(me.onStateChange, me, [request]);
+            }
+
+            
+            xhr.send(requestOptions.data);
+            if (!async) {
+                return this.onComplete(request);
+            }
+            return request;
+        } else {
+            Ext.callback(options.callback, options.scope, [options, undefined, undefined]);
+            return null;
+        }
+    },
+
+    
+    upload: function(form, url, params, options) {
+        form = Ext.getDom(form);
+        options = options || {};
+
+        var id = Ext.id(),
+                frame = document.createElement('iframe'),
+                hiddens = [],
+                encoding = 'multipart/form-data',
+                buf = {
+                    target: form.target,
+                    method: form.method,
+                    encoding: form.encoding,
+                    enctype: form.enctype,
+                    action: form.action
+                }, hiddenItem;
+
+        
+        Ext.fly(frame).set({
+            id: id,
+            name: id,
+            cls: Ext.baseCSSPrefix + 'hide-display',
+            src: Ext.SSL_SECURE_URL
+        });
+
+        document.body.appendChild(frame);
+
+        
+        if (document.frames) {
+           document.frames[id].name = id;
+        }
+
+        Ext.fly(form).set({
+            target: id,
+            method: 'POST',
+            enctype: encoding,
+            encoding: encoding,
+            action: url || buf.action
+        });
+
+        
+        if (params) {
+            Ext.iterate(Ext.Object.fromQueryString(params), function(name, value){
+                hiddenItem = document.createElement('input');
+                Ext.fly(hiddenItem).set({
+                    type: 'hidden',
+                    value: value,
+                    name: name
+                });
+                form.appendChild(hiddenItem);
+                hiddens.push(hiddenItem);
+            });
+        }
+
+        Ext.fly(frame).on('load', Ext.Function.bind(this.onUploadComplete, this, [frame, options]), null, {single: true});
+        form.submit();
+
+        Ext.fly(form).set(buf);
+        Ext.each(hiddens, function(h) {
+            Ext.removeNode(h);
+        });
+    },
+
+    
+    onUploadComplete: function(frame, options) {
+        var me = this,
+            
+            response = {
+                responseText: '',
+                responseXML: null
+            }, doc, firstChild;
+
+        try {
+            doc = frame.contentWindow.document || frame.contentDocument || window.frames[frame.id].document;
+            if (doc) {
+                if (doc.body) {
+                    if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) { 
+                        response.responseText = firstChild.value;
+                    } else {
+                        response.responseText = doc.body.innerHTML;
+                    }
+                }
+                
+                response.responseXML = doc.XMLDocument || doc;
+            }
+        } catch (e) {
+        }
+
+        me.fireEvent('requestcomplete', me, response, options);
+
+        Ext.callback(options.success, options.scope, [response, options]);
+        Ext.callback(options.callback, options.scope, [options, true, response]);
+
+        setTimeout(function(){
+            Ext.removeNode(frame);
+        }, 100);
+    },
+
+    
+    isFormUpload: function(options){
+        var form = this.getForm(options);
+        if (form) {
+            return (options.isUpload || (/multipart\/form-data/i).test(form.getAttribute('enctype')));
+        }
+        return false;
+    },
+
+    
+    getForm: function(options){
+        return Ext.getDom(options.form) || null;
+    },
+
+    
+    setOptions: function(options, scope){
+        var me =  this,
+            params = options.params || {},
+            extraParams = me.extraParams,
+            urlParams = options.urlParams,
+            url = options.url || me.url,
+            jsonData = options.jsonData,
+            method,
+            disableCache,
+            data;
+
+
+        
+        if (Ext.isFunction(params)) {
+            params = params.call(scope, options);
+        }
+
+        
+        if (Ext.isFunction(url)) {
+            url = url.call(scope, options);
+        }
+
+        url = this.setupUrl(options, url);
+
+
+        
+        data = options.rawData || options.xmlData || jsonData || null;
+        if (jsonData && !Ext.isPrimitive(jsonData)) {
+            data = Ext.encode(data);
+        }
+
+        
+        if (Ext.isObject(params)) {
+            params = Ext.Object.toQueryString(params);
+        }
+
+        if (Ext.isObject(extraParams)) {
+            extraParams = Ext.Object.toQueryString(extraParams);
+        }
+
+        params = params + ((extraParams) ? ((params) ? '&' : '') + extraParams : '');
+
+        urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams;
+
+        params = this.setupParams(options, params);
+
+        
+        method = (options.method || me.method || ((params || data) ? 'POST' : 'GET')).toUpperCase();
+        this.setupMethod(options, method);
+
+
+        disableCache = options.disableCaching !== false ? (options.disableCaching || me.disableCaching) : false;
+        
+        if (method === 'GET' && disableCache) {
+            url = Ext.urlAppend(url, (options.disableCachingParam || me.disableCachingParam) + '=' + (new Date().getTime()));
+        }
+
+        
+        if ((method == 'GET' || data) && params) {
+            url = Ext.urlAppend(url, params);
+            params = null;
+        }
+
+        
+        if (urlParams) {
+            url = Ext.urlAppend(url, urlParams);
+        }
+
+        return {
+            url: url,
+            method: method,
+            data: data || params || null
+        };
+    },
+
+    
+    setupUrl: function(options, url){
+        var form = this.getForm(options);
+        if (form) {
+            url = url || form.action;
+        }
+        return url;
+    },
+
+
+    
+    setupParams: function(options, params) {
+        var form = this.getForm(options),
+            serializedForm;
+        if (form && !this.isFormUpload(options)) {
+            serializedForm = Ext.Element.serializeForm(form);
+            params = params ? (params + '&' + serializedForm) : serializedForm;
+        }
+        return params;
+    },
+
+    
+    setupMethod: function(options, method){
+        if (this.isFormUpload(options)) {
+            return 'POST';
+        }
+        return method;
+    },
+
+    
+    setupHeaders: function(xhr, options, data, params){
+        var me = this,
+            headers = Ext.apply({}, options.headers || {}, me.defaultHeaders || {}),
+            contentType = me.defaultPostHeader,
+            jsonData = options.jsonData,
+            xmlData = options.xmlData,
+            key,
+            header;
+
+        if (!headers['Content-Type'] && (data || params)) {
+            if (data) {
+                if (options.rawData) {
+                    contentType = 'text/plain';
+                } else {
+                    if (xmlData && Ext.isDefined(xmlData)) {
+                        contentType = 'text/xml';
+                    } else if (jsonData && Ext.isDefined(jsonData)) {
+                        contentType = 'application/json';
+                    }
+                }
+            }
+            headers['Content-Type'] = contentType;
+        }
+
+        if (me.useDefaultXhrHeader && !headers['X-Requested-With']) {
+            headers['X-Requested-With'] = me.defaultXhrHeader;
+        }
+        
+        try{
+            for (key in headers) {
+                if (headers.hasOwnProperty(key)) {
+                    header = headers[key];
+                    xhr.setRequestHeader(key, header);
+                }
+
+            }
+        } catch(e) {
+            me.fireEvent('exception', key, header);
+        }
+        return headers;
+    },
+
+    
+    getXhrInstance: (function(){
+        var options = [function(){
+            return new XMLHttpRequest();
+        }, function(){
+            return new ActiveXObject('MSXML2.XMLHTTP.3.0');
+        }, function(){
+            return new ActiveXObject('MSXML2.XMLHTTP');
+        }, function(){
+            return new ActiveXObject('Microsoft.XMLHTTP');
+        }], i = 0,
+            len = options.length,
+            xhr;
+
+        for(; i < len; ++i) {
+            try{
+                xhr = options[i];
+                xhr();
+                break;
+            }catch(e){}
+        }
+        return xhr;
+    })(),
+
+    
+    isLoading : function(request) {
+        if (!request) {
+            request = this.getLatest();
+        }
+        if (!(request && request.xhr)) {
+            return false;
+        }
+        
+        var state = request.xhr.readyState;
+        return !(state === 0 || state == 4);
+    },
+
+    
+    abort : function(request) {
+        var me = this;
+        
+        if (!request) {
+            request = me.getLatest();
+        }
+
+        if (request && me.isLoading(request)) {
+            
+            request.xhr.onreadystatechange = null;
+            request.xhr.abort();
+            me.clearTimeout(request);
+            if (!request.timedout) {
+                request.aborted = true;
+            }
+            me.onComplete(request);
+            me.cleanup(request);
+        }
+    },
+    
+    
+    abortAll: function(){
+        var requests = this.requests,
+            id;
+        
+        for (id in requests) {
+            if (requests.hasOwnProperty(id)) {
+                this.abort(requests[id]);
+            }
+        }
+    },
+    
+    
+    getLatest: function(){
+        var id = this.latestId,
+            request;
+            
+        if (id) {
+            request = this.requests[id];
+        }
+        return request || null;
+    },
+
+    
+    onStateChange : function(request) {
+        if (request.xhr.readyState == 4) {
+            this.clearTimeout(request);
+            this.onComplete(request);
+            this.cleanup(request);
+        }
+    },
+
+    
+    clearTimeout: function(request){
+        clearTimeout(request.timeout);
+        delete request.timeout;
+    },
+
+    
+    cleanup: function(request){
+        request.xhr = null;
+        delete request.xhr;
+    },
+
+    
+    onComplete : function(request) {
+        var me = this,
+            options = request.options,
+            result,
+            success,
+            response;
+
+        try {
+            result = me.parseStatus(request.xhr.status);
+        } catch (e) {
+            
+            result = {
+                success : false,
+                isException : false
+            };
+        }
+        success = result.success;
+
+        if (success) {
+            response = me.createResponse(request);
+            me.fireEvent('requestcomplete', me, response, options);
+            Ext.callback(options.success, options.scope, [response, options]);
+        } else {
+            if (result.isException || request.aborted || request.timedout) {
+                response = me.createException(request);
+            } else {
+                response = me.createResponse(request);
+            }
+            me.fireEvent('requestexception', me, response, options);
+            Ext.callback(options.failure, options.scope, [response, options]);
+        }
+        Ext.callback(options.callback, options.scope, [options, success, response]);
+        delete me.requests[request.id];
+        return response;
+    },
+
+    
+    parseStatus: function(status) {
+        
+        status = status == 1223 ? 204 : status;
+
+        var success = (status >= 200 && status < 300) || status == 304,
+            isException = false;
+
+        if (!success) {
+            switch (status) {
+                case 12002:
+                case 12029:
+                case 12030:
+                case 12031:
+                case 12152:
+                case 13030:
+                    isException = true;
+                    break;
+            }
+        }
+        return {
+            success: success,
+            isException: isException
+        };
+    },
+
+    
+    createResponse : function(request) {
+        var xhr = request.xhr,
+            headers = {},
+            lines = xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'),
+            count = lines.length,
+            line, index, key, value, response;
+
+        while (count--) {
+            line = lines[count];
+            index = line.indexOf(':');
+            if(index >= 0) {
+                key = line.substr(0, index).toLowerCase();
+                if (line.charAt(index + 1) == ' ') {
+                    ++index;
+                }
+                headers[key] = line.substr(index + 1);
+            }
+        }
+
+        request.xhr = null;
+        delete request.xhr;
+
+        response = {
+            request: request,
+            requestId : request.id,
+            status : xhr.status,
+            statusText : xhr.statusText,
+            getResponseHeader : function(header){ return headers[header.toLowerCase()]; },
+            getAllResponseHeaders : function(){ return headers; },
+            responseText : xhr.responseText,
+            responseXML : xhr.responseXML
+        };
+
+        
+        
+        xhr = null;
+        return response;
+    },
+
+    
+    createException : function(request) {
+        return {
+            request : request,
+            requestId : request.id,
+            status : request.aborted ? -1 : 0,
+            statusText : request.aborted ? 'transaction aborted' : 'communication failure',
+            aborted: request.aborted,
+            timedout: request.timedout
+        };
+    }
+});
+
+
+Ext.define('Ext.Ajax', {
+    extend: 'Ext.data.Connection',
+    singleton: true,
+
+    
+    
+    
+    
+    
+    
+
+    
+
+    
+    
+    
+    
+    
+    
+
+    
+    autoAbort : false
+});
+
+Ext.define('Ext.ElementLoader', {
+
+    
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    uses: [
+        'Ext.data.Connection',
+        'Ext.Ajax'
+    ],
+
+    statics: {
+        Renderer: {
+            Html: function(loader, response, active){
+                loader.getTarget().update(response.responseText, active.scripts === true);
+                return true;
+            }
+        }
+    },
+
+    
+
+    
+    url: null,
+
+    
+    params: null,
+
+    
+    baseParams: null,
+
+    
+    autoLoad: false,
+
+    
+    target: null,
+
+    
+    loadMask: false,
+
+    
+    ajaxOptions: null,
+
+    
+    scripts: false,
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    isLoader: true,
+
+    constructor: function(config) {
+        var me = this,
+            autoLoad;
+
+        config = config || {};
+        Ext.apply(me, config);
+        me.setTarget(me.target);
+        me.addEvents(
+            
+            'beforeload',
+
+            
+            'exception',
+
+            
+            'load'
+        );
+
+        
+        me.mixins.observable.constructor.call(me);
+
+        if (me.autoLoad) {
+            autoLoad = me.autoLoad;
+            if (autoLoad === true) {
+                autoLoad = {};
+            }
+            me.load(autoLoad);
+        }
+    },
+
+    
+    setTarget: function(target){
+        var me = this;
+        target = Ext.get(target);
+        if (me.target && me.target != target) {
+            me.abort();
+        }
+        me.target = target;
+    },
+
+    
+    getTarget: function(){
+        return this.target || null;
+    },
+
+    
+    abort: function(){
+        var active = this.active;
+        if (active !== undefined) {
+            Ext.Ajax.abort(active.request);
+            if (active.mask) {
+                this.removeMask();
+            }
+            delete this.active;
+        }
+    },
+
+    
+    removeMask: function(){
+        this.target.unmask();
+    },
+
+    
+    addMask: function(mask){
+        this.target.mask(mask === true ? null : mask);
+    },
+
+    
+    load: function(options) {
+
+        options = Ext.apply({}, options);
+
+        var me = this,
+            target = me.target,
+            mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask,
+            params = Ext.apply({}, options.params),
+            ajaxOptions = Ext.apply({}, options.ajaxOptions),
+            callback = options.callback || me.callback,
+            scope = options.scope || me.scope || me,
+            request;
+
+        Ext.applyIf(ajaxOptions, me.ajaxOptions);
+        Ext.applyIf(options, ajaxOptions);
+
+        Ext.applyIf(params, me.params);
+        Ext.apply(params, me.baseParams);
+
+        Ext.applyIf(options, {
+            url: me.url
+        });
+
+
+        Ext.apply(options, {
+            scope: me,
+            params: params,
+            callback: me.onComplete
+        });
+
+        if (me.fireEvent('beforeload', me, options) === false) {
+            return;
+        }
+
+        if (mask) {
+            me.addMask(mask);
+        }
+
+        request = Ext.Ajax.request(options);
+        me.active = {
+            request: request,
+            options: options,
+            mask: mask,
+            scope: scope,
+            callback: callback,
+            success: options.success || me.success,
+            failure: options.failure || me.failure,
+            renderer: options.renderer || me.renderer,
+            scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts
+        };
+        me.setOptions(me.active, options);
+    },
+
+    
+    setOptions: Ext.emptyFn,
+
+    
+    onComplete: function(options, success, response) {
+        var me = this,
+            active = me.active,
+            scope = active.scope,
+            renderer = me.getRenderer(active.renderer);
+
+
+        if (success) {
+            success = renderer.call(me, me, response, active);
+        }
+
+        if (success) {
+            Ext.callback(active.success, scope, [me, response, options]);
+            me.fireEvent('load', me, response, options);
+        } else {
+            Ext.callback(active.failure, scope, [me, response, options]);
+            me.fireEvent('exception', me, response, options);
+        }
+        Ext.callback(active.callback, scope, [me, success, response, options]);
+
+        if (active.mask) {
+            me.removeMask();
+        }
+
+        delete me.active;
+    },
+
+    
+    getRenderer: function(renderer){
+        if (Ext.isFunction(renderer)) {
+            return renderer;
+        }
+        return this.statics().Renderer.Html;
+    },
+
+    
+    startAutoRefresh: function(interval, options){
+        var me = this;
+        me.stopAutoRefresh();
+        me.autoRefresh = setInterval(function(){
+            me.load(options);
+        }, interval);
+    },
+
+    
+    stopAutoRefresh: function(){
+        clearInterval(this.autoRefresh);
+        delete this.autoRefresh;
+    },
+
+    
+    isAutoRefreshing: function(){
+        return Ext.isDefined(this.autoRefresh);
+    },
+
+    
+    destroy: function(){
+        var me = this;
+        me.stopAutoRefresh();
+        delete me.target;
+        me.abort();
+        me.clearListeners();
+    }
+});
+
+
+Ext.define('Ext.ComponentLoader', {
+
+    
+
+    extend: 'Ext.ElementLoader',
+
+    statics: {
+        Renderer: {
+            Data: function(loader, response, active){
+                var success = true;
+                try {
+                    loader.getTarget().update(Ext.decode(response.responseText));
+                } catch (e) {
+                    success = false;
+                }
+                return success;
+            },
+
+            Component: function(loader, response, active){
+                var success = true,
+                    target = loader.getTarget(),
+                    items = [];
+
+
+                try {
+                    items = Ext.decode(response.responseText);
+                } catch (e) {
+                    success = false;
+                }
+
+                if (success) {
+                    if (active.removeAll) {
+                        target.removeAll();
+                    }
+                    target.add(items);
+                }
+                return success;
+            }
+        }
+    },
+
+    
+
+    
+    target: null,
+
+    
+    loadMask: false,
+
+    
+
+    
+    renderer: 'html',
+
+    
+    setTarget: function(target){
+        var me = this;
+
+        if (Ext.isString(target)) {
+            target = Ext.getCmp(target);
+        }
+
+        if (me.target && me.target != target) {
+            me.abort();
+        }
+        me.target = target;
+    },
+
+    
+    removeMask: function(){
+        this.target.setLoading(false);
+    },
+
+    
+    addMask: function(mask){
+        this.target.setLoading(mask);
+    },
+
+    
+
+    setOptions: function(active, options){
+        active.removeAll = Ext.isDefined(options.removeAll) ? options.removeAll : this.removeAll;
+    },
+
+    
+    getRenderer: function(renderer){
+        if (Ext.isFunction(renderer)) {
+            return renderer;
+        }
+
+        var renderers = this.statics().Renderer;
+        switch (renderer) {
+            case 'component':
+                return renderers.Component;
+            case 'data':
+                return renderers.Data;
+            default:
+                return Ext.ElementLoader.Renderer.Html;
+        }
+    }
+});
+
+
+Ext.define('Ext.data.Association', {
+    
+
+    
+
+    
+    primaryKey: 'id',
+
+    
+    
+    
+
+    defaultReaderType: 'json',
+
+    statics: {
+        create: function(association){
+            if (!association.isAssociation) {
+                if (Ext.isString(association)) {
+                    association = {
+                        type: association
+                    };
+                }
+
+                switch (association.type) {
+                    case 'belongsTo':
+                        return Ext.create('Ext.data.BelongsToAssociation', association);
+                    case 'hasMany':
+                        return Ext.create('Ext.data.HasManyAssociation', association);
+                    
+
+
+                    default:
+                }
+            }
+            return association;
+        }
+    },
+
+    
+    constructor: function(config) {
+        Ext.apply(this, config);
+
+        var types           = Ext.ModelManager.types,
+            ownerName       = config.ownerModel,
+            associatedName  = config.associatedModel,
+            ownerModel      = types[ownerName],
+            associatedModel = types[associatedName],
+            ownerProto;
+
+
+        this.ownerModel = ownerModel;
+        this.associatedModel = associatedModel;
+
+        
+
+        
+
+        Ext.applyIf(this, {
+            ownerName : ownerName,
+            associatedName: associatedName
+        });
+    },
+
+    
+    getReader: function(){
+        var me = this,
+            reader = me.reader,
+            model = me.associatedModel;
+
+        if (reader) {
+            if (Ext.isString(reader)) {
+                reader = {
+                    type: reader
+                };
+            }
+            if (reader.isReader) {
+                reader.setModel(model);
+            } else {
+                Ext.applyIf(reader, {
+                    model: model,
+                    type : me.defaultReaderType
+                });
+            }
+            me.reader = Ext.createByAlias('reader.' + reader.type, reader);
+        }
+        return me.reader || null;
+    }
+});
+
+
+Ext.define('Ext.ModelManager', {
+    extend: 'Ext.AbstractManager',
+    alternateClassName: 'Ext.ModelMgr',
+    requires: ['Ext.data.Association'],
+
+    singleton: true,
+
+    typeName: 'mtype',
+
+    
+    associationStack: [],
+
+    
+    registerType: function(name, config) {
+        var proto = config.prototype,
+            model;
+        if (proto && proto.isModel) {
+            
+            model = config;
+        } else {
+            
+            if (!config.extend) {
+                config.extend = 'Ext.data.Model';
+            }
+            model = Ext.define(name, config);
+        }
+        this.types[name] = model;
+        return model;
+    },
+
+    
+    onModelDefined: function(model) {
+        var stack  = this.associationStack,
+            length = stack.length,
+            create = [],
+            association, i, created;
+
+        for (i = 0; i < length; i++) {
+            association = stack[i];
+
+            if (association.associatedModel == model.modelName) {
+                create.push(association);
+            }
+        }
+
+        for (i = 0, length = create.length; i < length; i++) {
+            created = create[i];
+            this.types[created.ownerModel].prototype.associations.add(Ext.data.Association.create(created));
+            Ext.Array.remove(stack, created);
+        }
+    },
+
+    
+    registerDeferredAssociation: function(association){
+        this.associationStack.push(association);
+    },
+
+    
+    getModel: function(id) {
+        var model = id;
+        if (typeof model == 'string') {
+            model = this.types[model];
+        }
+        return model;
+    },
+
+    
+    create: function(config, name, id) {
+        var con = typeof name == 'function' ? name : this.types[name || config.name];
+
+        return new con(config, id);
+    }
+}, function() {
+
+    
+    Ext.regModel = function() {
+        return this.ModelManager.registerType.apply(this.ModelManager, arguments);
+    };
+});
+
+
+Ext.define('Ext.PluginManager', {
+    extend: 'Ext.AbstractManager',
+    alternateClassName: 'Ext.PluginMgr',
+    singleton: true,
+    typeName: 'ptype',
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+
+    create : function(config, defaultType){
+        if (config.init) {
+            return config;
+        } else {
+            return Ext.createByAlias('plugin.' + (config.ptype || defaultType), config);
+        }
+
+        
+        
+        
+        
+        
+        
+        
+    },
+
+    
+    findByType: function(type, defaultsOnly) {
+        var matches = [],
+            types   = this.types;
+
+        for (var name in types) {
+            if (!types.hasOwnProperty(name)) {
+                continue;
+            }
+            var item = types[name];
+
+            if (item.type == type && (!defaultsOnly || (defaultsOnly === true && item.isDefault))) {
+                matches.push(item);
+            }
+        }
+
+        return matches;
+    }
+}, function() {
+    
+    Ext.preg = function() {
+        return Ext.PluginManager.registerType.apply(Ext.PluginManager, arguments);
+    };
+});
+
+
+Ext.define('Ext.Template', {
+
+    
+
+    requires: ['Ext.DomHelper', 'Ext.util.Format'],
+
+    inheritableStatics: {
+        
+        from: function(el, config) {
+            el = Ext.getDom(el);
+            return new this(el.value || el.innerHTML, config || '');
+        }
+    },
+
+    
+
+    
+    constructor: function(html) {
+        var me = this,
+            args = arguments,
+            buffer = [],
+            i = 0,
+            length = args.length,
+            value;
+
+        me.initialConfig = {};
+
+        if (length > 1) {
+            for (; i < length; i++) {
+                value = args[i];
+                if (typeof value == 'object') {
+                    Ext.apply(me.initialConfig, value);
+                    Ext.apply(me, value);
+                } else {
+                    buffer.push(value);
+                }
+            }
+            html = buffer.join('');
+        } else {
+            if (Ext.isArray(html)) {
+                buffer.push(html.join(''));
+            } else {
+                buffer.push(html);
+            }
+        }
+
+        
+        me.html = buffer.join('');
+
+        if (me.compiled) {
+            me.compile();
+        }
+    },
+
+    isTemplate: true,
+
+    
+
+    
+    disableFormats: false,
+
+    re: /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
+
+    
+    applyTemplate: function(values) {
+        var me = this,
+            useFormat = me.disableFormats !== true,
+            fm = Ext.util.Format,
+            tpl = me;
+
+        if (me.compiled) {
+            return me.compiled(values);
+        }
+        function fn(m, name, format, args) {
+            if (format && useFormat) {
+                if (args) {
+                    args = [values[name]].concat(Ext.functionFactory('return ['+ args +'];')());
+                } else {
+                    args = [values[name]];
+                }
+                if (format.substr(0, 5) == "this.") {
+                    return tpl[format.substr(5)].apply(tpl, args);
+                }
+                else {
+                    return fm[format].apply(fm, args);
+                }
+            }
+            else {
+                return values[name] !== undefined ? values[name] : "";
+            }
+        }
+        return me.html.replace(me.re, fn);
+    },
+
+    
+    set: function(html, compile) {
+        var me = this;
+        me.html = html;
+        me.compiled = null;
+        return compile ? me.compile() : me;
+    },
+
+    compileARe: /\\/g,
+    compileBRe: /(\r\n|\n)/g,
+    compileCRe: /'/g,
+
+    /**
+     * Compiles the template into an internal function, eliminating the RegEx overhead.
+     * @return {Ext.Template} this
+     */
+    compile: function() {
+        var me = this,
+            fm = Ext.util.Format,
+            useFormat = me.disableFormats !== true,
+            body, bodyReturn;
+
+        function fn(m, name, format, args) {
+            if (format && useFormat) {
+                args = args ? ',' + args: "";
+                if (format.substr(0, 5) != "this.") {
+                    format = "fm." + format + '(';
+                }
+                else {
+                    format = 'this.' + format.substr(5) + '(';
+                }
+            }
+            else {
+                args = '';
+                format = "(values['" + name + "'] == undefined ? '' : ";
+            }
+            return "'," + format + "values['" + name + "']" + args + ") ,'";
+        }
+
+        bodyReturn = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn);
+        body = "this.compiled = function(values){ return ['" + bodyReturn + "'].join('');};";
+        eval(body);
+        return me;
+    },
+
+    /**
+     * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
+     *
+     * @param {String/HTMLElement/Ext.Element} el The context element
+     * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
+     * @param {Boolean} returnElement (optional) true to return a Ext.Element.
+     * @return {HTMLElement/Ext.Element} The new node or Element
+     */
+    insertFirst: function(el, values, returnElement) {
+        return this.doInsert('afterBegin', el, values, returnElement);
+    },
+
+    /**
+     * Applies the supplied values to the template and inserts the new node(s) before el.
+     *
+     * @param {String/HTMLElement/Ext.Element} el The context element
+     * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
+     * @param {Boolean} returnElement (optional) true to return a Ext.Element.
+     * @return {HTMLElement/Ext.Element} The new node or Element
+     */
+    insertBefore: function(el, values, returnElement) {
+        return this.doInsert('beforeBegin', el, values, returnElement);
+    },
+
+    /**
+     * Applies the supplied values to the template and inserts the new node(s) after el.
+     *
+     * @param {String/HTMLElement/Ext.Element} el The context element
+     * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
+     * @param {Boolean} returnElement (optional) true to return a Ext.Element.
+     * @return {HTMLElement/Ext.Element} The new node or Element
+     */
+    insertAfter: function(el, values, returnElement) {
+        return this.doInsert('afterEnd', el, values, returnElement);
+    },
+
+    /**
+     * Applies the supplied `values` to the template and appends the new node(s) to the specified `el`.
+     *
+     * For example usage see {@link Ext.Template Ext.Template class docs}.
+     *
+     * @param {String/HTMLElement/Ext.Element} el The context element
+     * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
+     * @param {Boolean} returnElement (optional) true to return an Ext.Element.
+     * @return {HTMLElement/Ext.Element} The new node or Element
+     */
+    append: function(el, values, returnElement) {
+        return this.doInsert('beforeEnd', el, values, returnElement);
+    },
+
+    doInsert: function(where, el, values, returnEl) {
+        el = Ext.getDom(el);
+        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
+        return returnEl ? Ext.get(newNode, true) : newNode;
+    },
+
+    /**
+     * Applies the supplied values to the template and overwrites the content of el with the new node(s).
+     *
+     * @param {String/HTMLElement/Ext.Element} el The context element
+     * @param {Object/Array} values The template values. See {@link #applyTemplate} for details.
+     * @param {Boolean} returnElement (optional) true to return a Ext.Element.
+     * @return {HTMLElement/Ext.Element} The new node or Element
+     */
+    overwrite: function(el, values, returnElement) {
+        el = Ext.getDom(el);
+        el.innerHTML = this.applyTemplate(values);
+        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
+    }
+}, function() {
+
+    /**
+     * @method apply
+     * @member Ext.Template
+     * Alias for {@link #applyTemplate}.
+     * @alias Ext.Template#applyTemplate
+     */
+    this.createAlias('apply', 'applyTemplate');
+});
+
+/**
+ * A template class that supports advanced functionality like:
+ *
+ * - Autofilling arrays using templates and sub-templates
+ * - Conditional processing with basic comparison operators
+ * - Basic math function support
+ * - Execute arbitrary inline code with special built-in template variables
+ * - Custom member functions
+ * - Many special tags and built-in operators that aren't defined as part of the API, but are supported in the templates that can be created
+ *
+ * XTemplate provides the templating mechanism built into:
+ *
+ * - {@link Ext.view.View}
+ *
+ * The {@link Ext.Template} describes the acceptable parameters to pass to the constructor. The following examples
+ * demonstrate all of the supported features.
+ *
+ * # Sample Data
+ *
+ * This is the data object used for reference in each code example:
+ *
+ *     var data = {
+ *         name: 'Tommy Maintz',
+ *         title: 'Lead Developer',
+ *         company: 'Sencha Inc.',
+ *         email: 'tommy@sencha.com',
+ *         address: '5 Cups Drive',
+ *         city: 'Palo Alto',
+ *         state: 'CA',
+ *         zip: '44102',
+ *         drinks: ['Coffee', 'Soda', 'Water'],
+ *         kids: [
+ *             {
+ *                 name: 'Joshua',
+ *                 age:3
+ *             },
+ *             {
+ *                 name: 'Matthew',
+ *                 age:2
+ *             },
+ *             {
+ *                 name: 'Solomon',
+ *                 age:0
+ *             }
+ *         ]
+ *     };
+ *
+ * # Auto filling of arrays
+ *
+ * The **tpl** tag and the **for** operator are used to process the provided data object:
+ *
+ * - If the value specified in for is an array, it will auto-fill, repeating the template block inside the tpl
+ *   tag for each item in the array.
+ * - If for="." is specified, the data object provided is examined.
+ * - While processing an array, the special variable {#} will provide the current array index + 1 (starts at 1, not 0).
+ *
+ * Examples:
+ *
+ *     <tpl for=".">...</tpl>       // loop through array at root node
+ *     <tpl for="foo">...</tpl>     // loop through array at foo node
+ *     <tpl for="foo.bar">...</tpl> // loop through array at foo.bar node
+ *
+ * Using the sample data above:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Kids: ',
+ *         '<tpl for=".">',       // process the data.kids node
+ *             '<p>{#}. {name}</p>',  // use current array index to autonumber
+ *         '</tpl></p>'
+ *     );
+ *     tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
+ *
+ * An example illustrating how the **for** property can be leveraged to access specified members of the provided data
+ * object to populate the template:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Name: {name}</p>',
+ *         '<p>Title: {title}</p>',
+ *         '<p>Company: {company}</p>',
+ *         '<p>Kids: ',
+ *         '<tpl for="kids">',     // interrogate the kids property within the data
+ *             '<p>{name}</p>',
+ *         '</tpl></p>'
+ *     );
+ *     tpl.overwrite(panel.body, data);  // pass the root node of the data object
+ *
+ * Flat arrays that contain values (and not objects) can be auto-rendered using the special **`{.}`** variable inside a
+ * loop. This variable will represent the value of the array at the current index:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>{name}\'s favorite beverages:</p>',
+ *         '<tpl for="drinks">',
+ *             '<div> - {.}</div>',
+ *         '</tpl>'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * When processing a sub-template, for example while looping through a child array, you can access the parent object's
+ * members via the **parent** object:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Name: {name}</p>',
+ *         '<p>Kids: ',
+ *         '<tpl for="kids">',
+ *             '<tpl if="age &gt; 1">',
+ *                 '<p>{name}</p>',
+ *                 '<p>Dad: {parent.name}</p>',
+ *             '</tpl>',
+ *         '</tpl></p>'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Conditional processing with basic comparison operators
+ *
+ * The **tpl** tag and the **if** operator are used to provide conditional checks for deciding whether or not to render
+ * specific parts of the template. Notes:
+ *
+ * - Double quotes must be encoded if used within the conditional
+ * - There is no else operator -- if needed, two opposite if statements should be used.
+ *
+ * Examples:
+ *
+ *     <tpl if="age > 1 && age < 10">Child</tpl>
+ *     <tpl if="age >= 10 && age < 18">Teenager</tpl>
+ *     <tpl if="this.isGirl(name)">...</tpl>
+ *     <tpl if="id==\'download\'">...</tpl>
+ *     <tpl if="needsIcon"><img src="{icon}" class="{iconCls}"/></tpl>
+ *     // no good:
+ *     <tpl if="name == "Tommy"">Hello</tpl>
+ *     // encode " if it is part of the condition, e.g.
+ *     <tpl if="name == &quot;Tommy&quot;">Hello</tpl>
+ *
+ * Using the sample data above:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Name: {name}</p>',
+ *         '<p>Kids: ',
+ *         '<tpl for="kids">',
+ *             '<tpl if="age &gt; 1">',
+ *                 '<p>{name}</p>',
+ *             '</tpl>',
+ *         '</tpl></p>'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Basic math support
+ *
+ * The following basic math operators may be applied directly on numeric data values:
+ *
+ *     + - * /
+ *
+ * For example:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Name: {name}</p>',
+ *         '<p>Kids: ',
+ *         '<tpl for="kids">',
+ *             '<tpl if="age &gt; 1">',  // <-- Note that the > is encoded
+ *                 '<p>{#}: {name}</p>',  // <-- Auto-number each item
+ *                 '<p>In 5 Years: {age+5}</p>',  // <-- Basic math
+ *                 '<p>Dad: {parent.name}</p>',
+ *             '</tpl>',
+ *         '</tpl></p>'
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Execute arbitrary inline code with special built-in template variables
+ *
+ * Anything between `{[ ... ]}` is considered code to be executed in the scope of the template. There are some special
+ * variables available in that code:
+ *
+ * - **values**: The values in the current scope. If you are using scope changing sub-templates,
+ *   you can change what values is.
+ * - **parent**: The scope (values) of the ancestor template.
+ * - **xindex**: If you are in a looping template, the index of the loop you are in (1-based).
+ * - **xcount**: If you are in a looping template, the total length of the array you are looping.
+ *
+ * This example demonstrates basic row striping using an inline code block and the xindex variable:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Name: {name}</p>',
+ *         '<p>Company: {[values.company.toUpperCase() + ", " + values.title]}</p>',
+ *         '<p>Kids: ',
+ *         '<tpl for="kids">',
+ *             '<div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
+ *             '{name}',
+ *             '</div>',
+ *         '</tpl></p>'
+ *      );
+ *     tpl.overwrite(panel.body, data);
+ *
+ * # Template member functions
+ *
+ * One or more member functions can be specified in a configuration object passed into the XTemplate constructor for
+ * more complex processing:
+ *
+ *     var tpl = new Ext.XTemplate(
+ *         '<p>Name: {name}</p>',
+ *         '<p>Kids: ',
+ *         '<tpl for="kids">',
+ *             '<tpl if="this.isGirl(name)">',
+ *                 '<p>Girl: {name} - {age}</p>',
+ *             '</tpl>',
+ *              // use opposite if statement to simulate 'else' processing:
+ *             '<tpl if="this.isGirl(name) == false">',
+ *                 '<p>Boy: {name} - {age}</p>',
+ *             '</tpl>',
+ *             '<tpl if="this.isBaby(age)">',
+ *                 '<p>{name} is a baby!</p>',
+ *             '</tpl>',
+ *         '</tpl></p>',
+ *         {
+ *             // XTemplate configuration:
+ *             disableFormats: true,
+ *             // member functions:
+ *             isGirl: function(name){
+ *                return name == 'Sara Grace';
+ *             },
+ *             isBaby: function(age){
+ *                return age < 1;
+ *             }
+ *         }
+ *     );
+ *     tpl.overwrite(panel.body, data);
+ */
+Ext.define('Ext.XTemplate', {
+
+    /* Begin Definitions */
+
+    extend: 'Ext.Template',
+
+    /* End Definitions */
+
+    argsRe: /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
+    nameRe: /^<tpl\b[^>]*?for="(.*?)"/,
+    ifRe: /^<tpl\b[^>]*?if="(.*?)"/,
+    execRe: /^<tpl\b[^>]*?exec="(.*?)"/,
+    constructor: function() {
+        this.callParent(arguments);
+
+        var me = this,
+            html = me.html,
+            argsRe = me.argsRe,
+            nameRe = me.nameRe,
+            ifRe = me.ifRe,
+            execRe = me.execRe,
+            id = 0,
+            tpls = [],
+            VALUES = 'values',
+            PARENT = 'parent',
+            XINDEX = 'xindex',
+            XCOUNT = 'xcount',
+            RETURN = 'return ',
+            WITHVALUES = 'with(values){ ',
+            m, matchName, matchIf, matchExec, exp, fn, exec, name, i;
+
+        html = ['<tpl>', html, '</tpl>'].join('');
+
+        while ((m = html.match(argsRe))) {
+            exp = null;
+            fn = null;
+            exec = null;
+            matchName = m[0].match(nameRe);
+            matchIf = m[0].match(ifRe);
+            matchExec = m[0].match(execRe);
+
+            exp = matchIf ? matchIf[1] : null;
+            if (exp) {
+                fn = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + Ext.String.htmlDecode(exp) + ';}catch(e){return;}}');
+            }
+
+            exp = matchExec ? matchExec[1] : null;
+            if (exp) {
+                exec = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.String.htmlDecode(exp) + ';}');
+            }
+
+            name = matchName ? matchName[1] : null;
+            if (name) {
+                if (name === '.') {
+                    name = VALUES;
+                } else if (name === '..') {
+                    name = PARENT;
+                }
+                name = Ext.functionFactory(VALUES, PARENT, 'try{' + WITHVALUES + RETURN + name + ';}}catch(e){return;}');
+            }
+
+            tpls.push({
+                id: id,
+                target: name,
+                exec: exec,
+                test: fn,
+                body: m[1] || ''
+            });
+
+            html = html.replace(m[0], '{xtpl' + id + '}');
+            id = id + 1;
+        }
+
+        for (i = tpls.length - 1; i >= 0; --i) {
+            me.compileTpl(tpls[i]);
+        }
+        me.master = tpls[tpls.length - 1];
+        me.tpls = tpls;
+    },
+
+    // @private
+    applySubTemplate: function(id, values, parent, xindex, xcount) {
+        var me = this, t = me.tpls[id];
+        return t.compiled.call(me, values, parent, xindex, xcount);
+    },
+
+    /**
+     * @cfg {RegExp} codeRe
+     * The regular expression used to match code variables. Default: matches {[expression]}.
+     */
+    codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
+
+    /**
+     * @cfg {Boolean} compiled
+     * Only applies to {@link Ext.Template}, XTemplates are compiled automatically.
+     */
+
+    re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
+
+    // @private
+    compileTpl: function(tpl) {
+        var fm = Ext.util.Format,
+            me = this,
+            useFormat = me.disableFormats !== true,
+            body, bodyReturn, evaluatedFn;
+
+        function fn(m, name, format, args, math) {
+            var v;
+            // name is what is inside the {}
+            // Name begins with xtpl, use a Sub Template
+            if (name.substr(0, 4) == 'xtpl') {
+                return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
+            }
+            // name = "." - Just use the values object.
+            if (name == '.') {
+                // filter to not include arrays/objects/nulls
+                v = 'Ext.Array.indexOf(["string", "number", "boolean"], typeof values) > -1 || Ext.isDate(values) ? values : ""';
+            }
+
+            // name = "#" - Use the xindex
+            else if (name == '#') {
+                v = 'xindex';
+            }
+            else if (name.substr(0, 7) == "parent.") {
+                v = name;
+            }
+            // name has a . in it - Use object literal notation, starting from values
+            else if (name.indexOf('.') != -1) {
+                v = "values." + name;
+            }
+
+            // name is a property of values
+            else {
+                v = "values['" + name + "']";
+            }
+            if (math) {
+                v = '(' + v + math + ')';
+            }
+            if (format && useFormat) {
+                args = args ? ',' + args : "";
+                if (format.substr(0, 5) != "this.") {
+                    format = "fm." + format + '(';
+                }
+                else {
+                    format = 'this.' + format.substr(5) + '(';
+                }
+            }
+            else {
+                args = '';
+                format = "(" + v + " === undefined ? '' : ";
+            }
+            return "'," + format + v + args + "),'";
+        }
+
+        function codeFn(m, code) {
+            // Single quotes get escaped when the template is compiled, however we want to undo this when running code.
+            return "',(" + code.replace(me.compileARe, "'") + "),'";
+        }
+
+        bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn).replace(me.codeRe, codeFn);
+        body = "evaluatedFn = function(values, parent, xindex, xcount){return ['" + bodyReturn + "'].join('');};";
+        eval(body);
+
+        tpl.compiled = function(values, parent, xindex, xcount) {
+            var vs,
+                length,
+                buffer,
+                i;
+
+            if (tpl.test && !tpl.test.call(me, values, parent, xindex, xcount)) {
+                return '';
+            }
+
+            vs = tpl.target ? tpl.target.call(me, values, parent) : values;
+            if (!vs) {
+               return '';
+            }
+
+            parent = tpl.target ? values : parent;
+            if (tpl.target && Ext.isArray(vs)) {
+                buffer = [];
+                length = vs.length;
+                if (tpl.exec) {
+                    for (i = 0; i < length; i++) {
+                        buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
+                        tpl.exec.call(me, vs[i], parent, i + 1, length);
+                    }
+                } else {
+                    for (i = 0; i < length; i++) {
+                        buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
+                    }
+                }
+                return buffer.join('');
+            }
+
+            if (tpl.exec) {
+                tpl.exec.call(me, vs, parent, xindex, xcount);
+            }
+            return evaluatedFn.call(me, vs, parent, xindex, xcount);
+        };
+
+        return this;
+    },
+
+    // inherit docs from Ext.Template
+    applyTemplate: function(values) {
+        return this.master.compiled.call(this, values, {}, 1, 1);
+    },
+
+    /**
+     * Does nothing. XTemplates are compiled automatically, so this function simply returns this.
+     * @return {Ext.XTemplate} this
+     */
+    compile: function() {
+        return this;
+    }
+}, function() {
+    // re-create the alias, inheriting it from Ext.Template doesn't work as intended.
+    this.createAlias('apply', 'applyTemplate');
+});
+
+
+Ext.define('Ext.app.Controller', {
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    
+    
+    
+
+    
+
+    
+
+    onClassExtended: function(cls, data) {
+        var className = Ext.getClassName(cls),
+            match = className.match(/^(.*)\.controller\./);
+
+        if (match !== null) {
+            var namespace = Ext.Loader.getPrefix(className) || match[1],
+                onBeforeClassCreated = data.onBeforeClassCreated,
+                requires = [],
+                modules = ['model', 'view', 'store'],
+                prefix;
+
+            data.onBeforeClassCreated = function(cls, data) {
+                var i, ln, module,
+                    items, j, subLn, item;
+
+                for (i = 0,ln = modules.length; i < ln; i++) {
+                    module = modules[i];
+
+                    items = Ext.Array.from(data[module + 's']);
+
+                    for (j = 0,subLn = items.length; j < subLn; j++) {
+                        item = items[j];
+
+                        prefix = Ext.Loader.getPrefix(item);
+
+                        if (prefix === '' || prefix === item) {
+                            requires.push(namespace + '.' + module + '.' + item);
+                        }
+                        else {
+                            requires.push(item);
+                        }
+                    }
+                }
+
+                Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
+            };
+        }
+    },
+
+    
+    constructor: function(config) {
+        this.mixins.observable.constructor.call(this, config);
+
+        Ext.apply(this, config || {});
+
+        this.createGetters('model', this.models);
+        this.createGetters('store', this.stores);
+        this.createGetters('view', this.views);
+
+        if (this.refs) {
+            this.ref(this.refs);
+        }
+    },
+
+    
+    init: function(application) {},
+
+    
+    onLaunch: function(application) {},
+
+    createGetters: function(type, refs) {
+        type = Ext.String.capitalize(type);
+        Ext.Array.each(refs, function(ref) {
+            var fn = 'get',
+                parts = ref.split('.');
+
+            
+            Ext.Array.each(parts, function(part) {
+                fn += Ext.String.capitalize(part);
+            });
+            fn += type;
+
+            if (!this[fn]) {
+                this[fn] = Ext.Function.pass(this['get' + type], [ref], this);
+            }
+            
+            this[fn](ref);
+        },
+        this);
+    },
+
+    ref: function(refs) {
+        var me = this;
+        refs = Ext.Array.from(refs);
+        Ext.Array.each(refs, function(info) {
+            var ref = info.ref,
+                fn = 'get' + Ext.String.capitalize(ref);
+            if (!me[fn]) {
+                me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
+            }
+        });
+    },
+
+    getRef: function(ref, info, config) {
+        this.refCache = this.refCache || {};
+        info = info || {};
+        config = config || {};
+
+        Ext.apply(info, config);
+
+        if (info.forceCreate) {
+            return Ext.ComponentManager.create(info, 'component');
+        }
+
+        var me = this,
+            selector = info.selector,
+            cached = me.refCache[ref];
+
+        if (!cached) {
+            me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
+            if (!cached && info.autoCreate) {
+                me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
+            }
+            if (cached) {
+                cached.on('beforedestroy', function() {
+                    me.refCache[ref] = null;
+                });
+            }
+        }
+
+        return cached;
+    },
+
+    
+    control: function(selectors, listeners) {
+        this.application.control(selectors, listeners, this);
+    },
+
+    
+    getController: function(name) {
+        return this.application.getController(name);
+    },
+
+    
+    getStore: function(name) {
+        return this.application.getStore(name);
+    },
+
+    
+    getModel: function(model) {
+        return this.application.getModel(model);
+    },
+
+    
+    getView: function(view) {
+        return this.application.getView(view);
+    }
+});
+
+
+Ext.define('Ext.data.IdGenerator', {
+
+    isGenerator: true,
+
+    
+    constructor: function(config) {
+        var me = this;
+
+        Ext.apply(me, config);
+
+        if (me.id) {
+            Ext.data.IdGenerator.all[me.id] = me;
+        }
+    },
+
+    
+
+    getRecId: function (rec) {
+        return rec.modelName + '-' + rec.internalId;
+    },
+
+    
+
+    statics: {
+        
+        all: {},
+
+        
+        get: function (config) {
+            var generator,
+                id,
+                type;
+
+            if (typeof config == 'string') {
+                id = type = config;
+                config = null;
+            } else if (config.isGenerator) {
+                return config;
+            } else {
+                id = config.id || config.type;
+                type = config.type;
+            }
+
+            generator = this.all[id];
+            if (!generator) {
+                generator = Ext.create('idgen.' + type, config);
+            }
+
+            return generator;
+        }
+    }
+});
+
+
+Ext.define('Ext.data.SortTypes', {
+    
+    singleton: true,
+    
+    
+    none : function(s) {
+        return s;
+    },
+
+    
+    stripTagsRE : /<\/?[^>]+>/gi,
+
+    
+    asText : function(s) {
+        return String(s).replace(this.stripTagsRE, "");
+    },
+
+    
+    asUCText : function(s) {
+        return String(s).toUpperCase().replace(this.stripTagsRE, "");
+    },
+
+    
+    asUCString : function(s) {
+        return String(s).toUpperCase();
+    },
+
+    
+    asDate : function(s) {
+        if(!s){
+            return 0;
+        }
+        if(Ext.isDate(s)){
+            return s.getTime();
+        }
+        return Date.parse(String(s));
+    },
+
+    
+    asFloat : function(s) {
+        var val = parseFloat(String(s).replace(/,/g, ""));
+        return isNaN(val) ? 0 : val;
+    },
+
+    
+    asInt : function(s) {
+        var val = parseInt(String(s).replace(/,/g, ""), 10);
+        return isNaN(val) ? 0 : val;
+    }
+});
+
+Ext.define('Ext.util.Filter', {
+
+    
+
+    
+    
+    
+    
+    
+    
+    anyMatch: false,
+    
+    
+    exactMatch: false,
+    
+    
+    caseSensitive: false,
+    
+    
+
+    
+    constructor: function(config) {
+        var me = this;
+        Ext.apply(me, config);
+        
+        
+        
+        me.filter = me.filter || me.filterFn;
+        
+        if (me.filter === undefined) {
+            if (me.property === undefined || me.value === undefined) {
+                
+                
+                
+                
+            } else {
+                me.filter = me.createFilterFn();
+            }
+            
+            me.filterFn = me.filter;
+        }
+    },
+    
+    
+    createFilterFn: function() {
+        var me       = this,
+            matcher  = me.createValueMatcher(),
+            property = me.property;
+        
+        return function(item) {
+            var value = me.getRoot.call(me, item)[property];
+            return matcher === null ? value === null : matcher.test(value);
+        };
+    },
+    
+    
+    getRoot: function(item) {
+        var root = this.root;
+        return root === undefined ? item : item[root];
+    },
+    
+    
+    createValueMatcher : function() {
+        var me            = this,
+            value         = me.value,
+            anyMatch      = me.anyMatch,
+            exactMatch    = me.exactMatch,
+            caseSensitive = me.caseSensitive,
+            escapeRe      = Ext.String.escapeRegex;
+            
+        if (value === null) {
+            return value;
+        }
+        
+        if (!value.exec) { 
+            value = String(value);
+
+            if (anyMatch === true) {
+                value = escapeRe(value);
+            } else {
+                value = '^' + escapeRe(value);
+                if (exactMatch === true) {
+                    value += '$';
+                }
+            }
+            value = new RegExp(value, caseSensitive ? '' : 'i');
+         }
+         
+         return value;
+    }
+});
+
+Ext.define('Ext.util.Sorter', {
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    direction: "ASC",
+    
+    constructor: function(config) {
+        var me = this;
+        
+        Ext.apply(me, config);
+        
+        
+        me.updateSortFunction();
+    },
+    
+    
+    createSortFunction: function(sorterFn) {
+        var me        = this,
+            property  = me.property,
+            direction = me.direction || "ASC",
+            modifier  = direction.toUpperCase() == "DESC" ? -1 : 1;
+        
+        
+        
+        return function(o1, o2) {
+            return modifier * sorterFn.call(me, o1, o2);
+        };
+    },
+    
+    
+    defaultSorterFn: function(o1, o2) {
+        var me = this,
+            transform = me.transform,
+            v1 = me.getRoot(o1)[me.property],
+            v2 = me.getRoot(o2)[me.property];
+            
+        if (transform) {
+            v1 = transform(v1);
+            v2 = transform(v2);
+        }
+
+        return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
+    },
+    
+    
+    getRoot: function(item) {
+        return this.root === undefined ? item : item[this.root];
+    },
+    
+    
+    setDirection: function(direction) {
+        var me = this;
+        me.direction = direction;
+        me.updateSortFunction();
+    },
+    
+    
+    toggle: function() {
+        var me = this;
+        me.direction = Ext.String.toggle(me.direction, "ASC", "DESC");
+        me.updateSortFunction();
+    },
+    
+    
+    updateSortFunction: function(fn) {
+        var me = this;
+        fn = fn || me.sorterFn || me.defaultSorterFn;
+        me.sort = me.createSortFunction(fn);
+    }
+});
+
+Ext.define('Ext.data.Operation', {
+    
+    synchronous: true,
+
+    
+    action: undefined,
+
+    
+    filters: undefined,
+
+    
+    sorters: undefined,
+
+    
+    group: undefined,
+
+    
+    start: undefined,
+
+    
+    limit: undefined,
+
+    
+    batch: undefined,
+
+    
+    callback: undefined,
+
+    
+    scope: undefined,
+
+    
+    started: false,
+
+    
+    running: false,
+
+    
+    complete: false,
+
+    
+    success: undefined,
+
+    
+    exception: false,
+
+    
+    error: undefined,
+
+    
+    actionCommitRecordsRe: /^(?:create|update)$/i,
+
+    
+    actionSkipSyncRe: /^destroy$/i,
+
+    
+    constructor: function(config) {
+        Ext.apply(this, config || {});
+    },
+
+    
+    commitRecords: function (serverRecords) {
+        var me = this,
+            mc, index, clientRecords, serverRec, clientRec;
+
+        if (!me.actionSkipSyncRe.test(me.action)) {
+            clientRecords = me.records;
+
+            if (clientRecords && clientRecords.length) {
+                mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
+                mc.addAll(clientRecords);
+
+                for (index = serverRecords ? serverRecords.length : 0; index--; ) {
+                    serverRec = serverRecords[index];
+                    clientRec = mc.get(serverRec.getId());
+
+                    if (clientRec) {
+                        clientRec.beginEdit();
+                        clientRec.set(serverRec.data);
+                        clientRec.endEdit(true);
+                    }
+                }
+
+                if (me.actionCommitRecordsRe.test(me.action)) {
+                    for (index = clientRecords.length; index--; ) {
+                        clientRecords[index].commit();
+                    }
+                }
+            }
+        }
+    },
+
+    
+    setStarted: function() {
+        this.started = true;
+        this.running = true;
+    },
+
+    
+    setCompleted: function() {
+        this.complete = true;
+        this.running  = false;
+    },
+
+    
+    setSuccessful: function() {
+        this.success = true;
+    },
+
+    
+    setException: function(error) {
+        this.exception = true;
+        this.success = false;
+        this.running = false;
+        this.error = error;
+    },
+
+    
+    hasException: function() {
+        return this.exception === true;
+    },
+
+    
+    getError: function() {
+        return this.error;
+    },
+
+    
+    getRecords: function() {
+        var resultSet = this.getResultSet();
+
+        return (resultSet === undefined ? this.records : resultSet.records);
+    },
+
+    
+    getResultSet: function() {
+        return this.resultSet;
+    },
+
+    
+    isStarted: function() {
+        return this.started === true;
+    },
+
+    
+    isRunning: function() {
+        return this.running === true;
+    },
+
+    
+    isComplete: function() {
+        return this.complete === true;
+    },
+
+    
+    wasSuccessful: function() {
+        return this.isComplete() && this.success === true;
+    },
+
+    
+    setBatch: function(batch) {
+        this.batch = batch;
+    },
+
+    
+    allowWrite: function() {
+        return this.action != 'read';
+    }
+});
+
+Ext.define('Ext.data.validations', {
+    singleton: true,
+    
+    
+    presenceMessage: 'must be present',
+    
+    
+    lengthMessage: 'is the wrong length',
+    
+    
+    formatMessage: 'is the wrong format',
+    
+    
+    inclusionMessage: 'is not included in the list of acceptable values',
+    
+    
+    exclusionMessage: 'is not an acceptable value',
+    
+    
+    emailMessage: 'is not a valid email address',
+    
+    
+    emailRe: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
+    
+    
+    presence: function(config, value) {
+        if (value === undefined) {
+            value = config;
+        }
+        
+        
+        return !!value || value === 0;
+    },
+    
+    
+    length: function(config, value) {
+        if (value === undefined || value === null) {
+            return false;
+        }
+        
+        var length = value.length,
+            min    = config.min,
+            max    = config.max;
+        
+        if ((min && length < min) || (max && length > max)) {
+            return false;
+        } else {
+            return true;
+        }
+    },
+    
+    
+    email: function(config, email) {
+        return Ext.data.validations.emailRe.test(email);
+    },
+    
+    
+    format: function(config, value) {
+        return !!(config.matcher && config.matcher.test(value));
+    },
+    
+    
+    inclusion: function(config, value) {
+        return config.list && Ext.Array.indexOf(config.list,value) != -1;
+    },
+    
+    
+    exclusion: function(config, value) {
+        return config.list && Ext.Array.indexOf(config.list,value) == -1;
+    }
+});
+
+Ext.define('Ext.data.ResultSet', {
+    
+    loaded: true,
+
+    
+    count: 0,
+
+    
+    total: 0,
+
+    
+    success: false,
+
+    
+
+    
+    constructor: function(config) {
+        Ext.apply(this, config);
+
+        
+        this.totalRecords = this.total;
+
+        if (config.count === undefined) {
+            this.count = this.records.length;
+        }
+    }
+});
+
+Ext.define('Ext.data.writer.Writer', {
+    alias: 'writer.base',
+    alternateClassName: ['Ext.data.DataWriter', 'Ext.data.Writer'],
+    
+    
+    writeAllFields: true,
+    
+    
+    nameProperty: 'name',
+
+    
+    constructor: function(config) {
+        Ext.apply(this, config);
+    },
+
+    
+    write: function(request) {
+        var operation = request.operation,
+            records   = operation.records || [],
+            len       = records.length,
+            i         = 0,
+            data      = [];
+
+        for (; i < len; i++) {
+            data.push(this.getRecordData(records[i]));
+        }
+        return this.writeRecords(request, data);
+    },
+
+    
+    getRecordData: function(record) {
+        var isPhantom = record.phantom === true,
+            writeAll = this.writeAllFields || isPhantom,
+            nameProperty = this.nameProperty,
+            fields = record.fields,
+            data = {},
+            changes,
+            name,
+            field,
+            key;
+        
+        if (writeAll) {
+            fields.each(function(field){
+                if (field.persist) {
+                    name = field[nameProperty] || field.name;
+                    data[name] = record.get(field.name);
+                }
+            });
+        } else {
+            
+            changes = record.getChanges();
+            for (key in changes) {
+                if (changes.hasOwnProperty(key)) {
+                    field = fields.get(key);
+                    name = field[nameProperty] || field.name;
+                    data[name] = changes[key];
+                }
+            }
+            if (!isPhantom) {
+                
+                data[record.idProperty] = record.getId();
+            }
+        }
+        return data;
+    }
+});
+
+
+Ext.define('Ext.util.Floating', {
+
+    uses: ['Ext.Layer', 'Ext.window.Window'],
+
+    
+    focusOnToFront: true,
+
+    
+    shadow: 'sides',
+
+    constructor: function(config) {
+        var me = this;
+        
+        me.floating = true;
+        me.el = Ext.create('Ext.Layer', Ext.apply({}, config, {
+            hideMode: me.hideMode,
+            hidden: me.hidden,
+            shadow: Ext.isDefined(me.shadow) ? me.shadow : 'sides',
+            shadowOffset: me.shadowOffset,
+            constrain: false,
+            shim: me.shim === false ? false : undefined
+        }), me.el);
+    },
+
+    onFloatRender: function() {
+        var me = this;
+        me.zIndexParent = me.getZIndexParent();
+        me.setFloatParent(me.ownerCt);
+        delete me.ownerCt;
+
+        if (me.zIndexParent) {
+            me.zIndexParent.registerFloatingItem(me);
+        } else {
+            Ext.WindowManager.register(me);
+        }
+    },
+
+    setFloatParent: function(floatParent) {
+        var me = this;
+
+        
+        if (me.floatParent) {
+            me.mun(me.floatParent, {
+                hide: me.onFloatParentHide,
+                show: me.onFloatParentShow,
+                scope: me
+            });
+        }
+
+        me.floatParent = floatParent;
+
+        
+        if (floatParent) {
+            me.mon(me.floatParent, {
+                hide: me.onFloatParentHide,
+                show: me.onFloatParentShow,
+                scope: me
+            });
+        }
+
+        
+        
+        if ((me.constrain || me.constrainHeader) && !me.constrainTo) {
+            me.constrainTo = floatParent ? floatParent.getTargetEl() : me.container;
+        }
+    },
+
+    onFloatParentHide: function() {
+        var me = this;
+        
+        if (me.hideOnParentHide !== false) {
+            me.showOnParentShow = me.isVisible();
+            me.hide();
+        }
+    },
+
+    onFloatParentShow: function() {
+        if (this.showOnParentShow) {
+            delete this.showOnParentShow;
+            this.show();
+        }
+    },
+
+    
+    getZIndexParent: function() {
+        var p = this.ownerCt,
+            c;
+
+        if (p) {
+            while (p) {
+                c = p;
+                p = p.ownerCt;
+            }
+            if (c.floating) {
+                return c;
+            }
+        }
+    },
+
+    
+    
+    
+    
+    
+    setZIndex: function(index) {
+        var me = this;
+        me.el.setZIndex(index);
+
+        
+        index += 10;
+
+        
+        
+        if (me.floatingItems) {
+            index = Math.floor(me.floatingItems.setBase(index) / 100) * 100 + 10000;
+        }
+        return index;
+    },
+
+    
+    doConstrain: function(constrainTo) {
+        var me = this,
+            vector = me.getConstrainVector(constrainTo || me.el.getScopeParent()),
+            xy;
+
+        if (vector) {
+            xy = me.getPosition();
+            xy[0] += vector[0];
+            xy[1] += vector[1];
+            me.setPosition(xy);
+        }
+    },
+
+
+    
+    getConstrainVector: function(constrainTo){
+        var me = this,
+            el;
+
+        if (me.constrain || me.constrainHeader) {
+            el = me.constrainHeader ? me.header.el : me.el;
+            constrainTo = constrainTo || (me.floatParent && me.floatParent.getTargetEl()) || me.container;
+            return el.getConstrainVector(constrainTo);
+        }
+    },
+
+    
+    alignTo: function(element, position, offsets) {
+        if (element.isComponent) {
+            element = element.getEl();
+        }
+        var xy = this.el.getAlignToXY(element, position, offsets);
+        this.setPagePosition(xy);
+        return this;
+    },
+
+    
+    toFront: function(preventFocus) {
+        var me = this;
+
+        
+        
+        if (me.zIndexParent) {
+            me.zIndexParent.toFront(true);
+        }
+        if (me.zIndexManager.bringToFront(me)) {
+            if (!Ext.isDefined(preventFocus)) {
+                preventFocus = !me.focusOnToFront;
+            }
+            if (!preventFocus) {
+                
+                
+                
+                me.focus(false, true);
+            }
+        }
+        return me;
+    },
+
+    
+    setActive: function(active, newActive) {
+        var me = this;
+        
+        if (active) {
+            if (me.el.shadow && !me.maximized) {
+                me.el.enableShadow(true);
+            }
+            me.fireEvent('activate', me);
+        } else {
+            
+            
+            if ((me instanceof Ext.window.Window) && (newActive instanceof Ext.window.Window)) {
+                me.el.disableShadow();
+            }
+            me.fireEvent('deactivate', me);
+        }
+    },
+
+    
+    toBack: function() {
+        this.zIndexManager.sendToBack(this);
+        return this;
+    },
+
+    
+    center: function() {
+        var me = this,
+            xy = me.el.getAlignToXY(me.container, 'c-c');
+        me.setPagePosition(xy);
+        return me;
+    },
+
+    
+    syncShadow : function(){
+        if (this.floating) {
+            this.el.sync(true);
+        }
+    },
+
+    
+    fitContainer: function() {
+        var parent = this.floatParent,
+            container = parent ? parent.getTargetEl() : this.container,
+            size = container.getViewSize(false);
+
+        this.setSize(size);
+    }
+});
+
+Ext.define('Ext.layout.Layout', {
+
+    
+
+    
+
+    isLayout: true,
+    initialized: false,
+
+    statics: {
+        create: function(layout, defaultType) {
+            var type;
+            if (layout instanceof Ext.layout.Layout) {
+                return Ext.createByAlias('layout.' + layout);
+            } else {
+                if (!layout || typeof layout === 'string') {
+                    type = layout || defaultType;
+                    layout = {};                    
+                }
+                else {
+                    type = layout.type || defaultType;
+                }
+                return Ext.createByAlias('layout.' + type, layout || {});
+            }
+        }
+    },
+
+    constructor : function(config) {
+        this.id = Ext.id(null, this.type + '-');
+        Ext.apply(this, config);
+    },
+
+    
+    layout : function() {
+        var me = this;
+        me.layoutBusy = true;
+        me.initLayout();
+
+        if (me.beforeLayout.apply(me, arguments) !== false) {
+            me.layoutCancelled = false;
+            me.onLayout.apply(me, arguments);
+            me.childrenChanged = false;
+            me.owner.needsLayout = false;
+            me.layoutBusy = false;
+            me.afterLayout.apply(me, arguments);
+        }
+        else {
+            me.layoutCancelled = true;
+        }
+        me.layoutBusy = false;
+        me.doOwnerCtLayouts();
+    },
+
+    beforeLayout : function() {
+        this.renderChildren();
+        return true;
+    },
+
+    renderChildren: function () {
+        this.renderItems(this.getLayoutItems(), this.getRenderTarget());
+    },
+
+    
+    renderItems : function(items, target) {
+        var me = this,
+            ln = items.length,
+            i = 0,
+            item;
+
+        for (; i < ln; i++) {
+            item = items[i];
+            if (item && !item.rendered) {
+                me.renderItem(item, target, i);
+            } else if (!me.isValidParent(item, target, i)) {
+                me.moveItem(item, target, i);
+            } else {
+                
+                me.configureItem(item);
+            }
+        }
+    },
+
+    
+    isValidParent : function(item, target, position) {
+        var dom = item.el ? item.el.dom : Ext.getDom(item);
+        if (dom && target && target.dom) {
+            if (Ext.isNumber(position) && dom !== target.dom.childNodes[position]) {
+                return false;
+            }
+            return (dom.parentNode == (target.dom || target));
+        }
+        return false;
+    },
+
+    
+    renderItem : function(item, target, position) {
+        var me = this;
+        if (!item.rendered) {
+            if (me.itemCls) {
+                item.addCls(me.itemCls);
+            }
+            if (me.owner.itemCls) {
+                item.addCls(me.owner.itemCls);
+            }
+            item.render(target, position);
+            me.configureItem(item);
+            me.childrenChanged = true;
+        }
+    },
+
+    
+    moveItem : function(item, target, position) {
+        
+        target = target.dom || target;
+        if (typeof position == 'number') {
+            position = target.childNodes[position];
+        }
+        target.insertBefore(item.el.dom, position || null);
+        item.container = Ext.get(target);
+        this.configureItem(item);
+        this.childrenChanged = true;
+    },
+
+    
+    initLayout : function() {
+        var me = this,
+            targetCls = me.targetCls;
+            
+        if (!me.initialized && !Ext.isEmpty(targetCls)) {
+            me.getTarget().addCls(targetCls);
+        }
+        me.initialized = true;
+    },
+
+    
+    setOwner : function(owner) {
+        this.owner = owner;
+    },
+
+    
+    getLayoutItems : function() {
+        return [];
+    },
+
+    
+    configureItem: Ext.emptyFn,
+    
+    
+    onLayout : Ext.emptyFn,
+    afterLayout : Ext.emptyFn,
+    onRemove : Ext.emptyFn,
+    onDestroy : Ext.emptyFn,
+    doOwnerCtLayouts : Ext.emptyFn,
+
+    
+    afterRemove : function(item) {
+        var el = item.el,
+            owner = this.owner,
+            itemCls = this.itemCls,
+            ownerCls = owner.itemCls;
+            
+        
+        if (item.rendered && !item.isDestroyed) {
+            if (itemCls) {
+                el.removeCls(itemCls);
+            }
+            if (ownerCls) {
+                el.removeCls(ownerCls);
+            }
+        }
+
+        
+        
+        
+        delete item.layoutManagedWidth;
+        delete item.layoutManagedHeight;
+    },
+
+    
+    destroy : function() {
+        var targetCls = this.targetCls,
+            target;
+        
+        if (!Ext.isEmpty(targetCls)) {
+            target = this.getTarget();
+            if (target) {
+                target.removeCls(targetCls);
+            }
+        }
+        this.onDestroy();
+    }
+});
+
+Ext.define('Ext.ZIndexManager', {
+
+    alternateClassName: 'Ext.WindowGroup',
+
+    statics: {
+        zBase : 9000
+    },
+
+    constructor: function(container) {
+        var me = this;
+
+        me.list = {};
+        me.zIndexStack = [];
+        me.front = null;
+
+        if (container) {
+
+            
+            if (container.isContainer) {
+                container.on('resize', me._onContainerResize, me);
+                me.zseed = Ext.Number.from(container.getEl().getStyle('zIndex'), me.getNextZSeed());
+                
+                me.targetEl = container.getTargetEl();
+                me.container = container;
+            }
+            
+            else {
+                Ext.EventManager.onWindowResize(me._onContainerResize, me);
+                me.zseed = me.getNextZSeed();
+                me.targetEl = Ext.get(container);
+            }
+        }
+        
+        
+        else {
+            Ext.EventManager.onWindowResize(me._onContainerResize, me);
+            me.zseed = me.getNextZSeed();
+            Ext.onDocumentReady(function() {
+                me.targetEl = Ext.getBody();
+            });
+        }
+    },
+
+    getNextZSeed: function() {
+        return (Ext.ZIndexManager.zBase += 10000);
+    },
+
+    setBase: function(baseZIndex) {
+        this.zseed = baseZIndex;
+        return this.assignZIndices();
+    },
+
+    
+    assignZIndices: function() {
+        var a = this.zIndexStack,
+            len = a.length,
+            i = 0,
+            zIndex = this.zseed,
+            comp;
+
+        for (; i < len; i++) {
+            comp = a[i];
+            if (comp && !comp.hidden) {
+
+                
+                
+                
+                
+                
+                
+                
+                zIndex = comp.setZIndex(zIndex);
+            }
+        }
+        this._activateLast();
+        return zIndex;
+    },
+
+    
+    _setActiveChild: function(comp) {
+        if (comp !== this.front) {
+
+            if (this.front) {
+                this.front.setActive(false, comp);
+            }
+            this.front = comp;
+            if (comp) {
+                comp.setActive(true);
+                if (comp.modal) {
+                    this._showModalMask(comp);
+                }
+            }
+        }
+    },
+
+    
+    _activateLast: function(justHidden) {
+        var comp,
+            lastActivated = false,
+            i;
+
+        
+        
+        
+        for (i = this.zIndexStack.length-1; i >= 0; --i) {
+            comp = this.zIndexStack[i];
+            if (!comp.hidden) {
+                if (!lastActivated) {
+                    this._setActiveChild(comp);
+                    lastActivated = true;
+                }
+
+                
+                if (comp.modal) {
+                    this._showModalMask(comp);
+                    return;
+                }
+            }
+        }
+
+        
+        
+        this._hideModalMask();
+        if (!lastActivated) {
+            this._setActiveChild(null);
+        }
+    },
+
+    _showModalMask: function(comp) {
+        var zIndex = comp.el.getStyle('zIndex') - 4,
+            maskTarget = comp.floatParent ? comp.floatParent.getTargetEl() : Ext.get(comp.getEl().dom.parentNode),
+            parentBox;
+        
+        if (!maskTarget) {
+            return;
+        }
+        
+        parentBox = maskTarget.getBox();
+
+        if (!this.mask) {
+            this.mask = Ext.getBody().createChild({
+                cls: Ext.baseCSSPrefix + 'mask'
+            });
+            this.mask.setVisibilityMode(Ext.Element.DISPLAY);
+            this.mask.on('click', this._onMaskClick, this);
+        }
+        if (maskTarget.dom === document.body) {
+            parentBox.height = Ext.Element.getViewHeight();
+        }
+        maskTarget.addCls(Ext.baseCSSPrefix + 'body-masked');
+        this.mask.setBox(parentBox);
+        this.mask.setStyle('zIndex', zIndex);
+        this.mask.show();
+    },
+
+    _hideModalMask: function() {
+        if (this.mask && this.mask.dom.parentNode) {
+            Ext.get(this.mask.dom.parentNode).removeCls(Ext.baseCSSPrefix + 'body-masked');
+            this.mask.hide();
+        }
+    },
+
+    _onMaskClick: function() {
+        if (this.front) {
+            this.front.focus();
+        }
+    },
+
+    _onContainerResize: function() {
+        if (this.mask && this.mask.isVisible()) {
+            this.mask.setSize(Ext.get(this.mask.dom.parentNode).getViewSize(true));
+        }
+    },
+
+    
+    register : function(comp) {
+        if (comp.zIndexManager) {
+            comp.zIndexManager.unregister(comp);
+        }
+        comp.zIndexManager = this;
+
+        this.list[comp.id] = comp;
+        this.zIndexStack.push(comp);
+        comp.on('hide', this._activateLast, this);
+    },
+
+    
+    unregister : function(comp) {
+        delete comp.zIndexManager;
+        if (this.list && this.list[comp.id]) {
+            delete this.list[comp.id];
+            comp.un('hide', this._activateLast);
+            Ext.Array.remove(this.zIndexStack, comp);
+
+            
+            this._activateLast(comp);
+        }
+    },
+
+    
+    get : function(id) {
+        return typeof id == "object" ? id : this.list[id];
+    },
+
+   
+    bringToFront : function(comp) {
+        comp = this.get(comp);
+        if (comp !== this.front) {
+            Ext.Array.remove(this.zIndexStack, comp);
+            this.zIndexStack.push(comp);
+            this.assignZIndices();
+            return true;
+        }
+        if (comp.modal) {
+            this._showModalMask(comp);
+        }
+        return false;
+    },
+
+    
+    sendToBack : function(comp) {
+        comp = this.get(comp);
+        Ext.Array.remove(this.zIndexStack, comp);
+        this.zIndexStack.unshift(comp);
+        this.assignZIndices();
+        return comp;
+    },
+
+    
+    hideAll : function() {
+        for (var id in this.list) {
+            if (this.list[id].isComponent && this.list[id].isVisible()) {
+                this.list[id].hide();
+            }
+        }
+    },
+
+    
+    hide: function() {
+        var i = 0,
+            ln = this.zIndexStack.length,
+            comp;
+
+        this.tempHidden = [];
+        for (; i < ln; i++) {
+            comp = this.zIndexStack[i];
+            if (comp.isVisible()) {
+                this.tempHidden.push(comp);
+                comp.hide();
+            }
+        }
+    },
+
+    
+    show: function() {
+        var i = 0,
+            ln = this.tempHidden.length,
+            comp,
+            x,
+            y;
+
+        for (; i < ln; i++) {
+            comp = this.tempHidden[i];
+            x = comp.x;
+            y = comp.y;
+            comp.show();
+            comp.setPosition(x, y);
+        }
+        delete this.tempHidden;
+    },
+
+    
+    getActive : function() {
+        return this.front;
+    },
+
+    
+    getBy : function(fn, scope) {
+        var r = [],
+            i = 0,
+            len = this.zIndexStack.length,
+            comp;
+
+        for (; i < len; i++) {
+            comp = this.zIndexStack[i];
+            if (fn.call(scope||comp, comp) !== false) {
+                r.push(comp);
+            }
+        }
+        return r;
+    },
+
+    
+    each : function(fn, scope) {
+        var comp;
+        for (var id in this.list) {
+            comp = this.list[id];
+            if (comp.isComponent && fn.call(scope || comp, comp) === false) {
+                return;
+            }
+        }
+    },
+
+    
+    eachBottomUp: function (fn, scope) {
+        var comp,
+            stack = this.zIndexStack,
+            i, n;
+
+        for (i = 0, n = stack.length ; i < n; i++) {
+            comp = stack[i];
+            if (comp.isComponent && fn.call(scope || comp, comp) === false) {
+                return;
+            }
+        }
+    },
+
+    
+    eachTopDown: function (fn, scope) {
+        var comp,
+            stack = this.zIndexStack,
+            i;
+
+        for (i = stack.length ; i-- > 0; ) {
+            comp = stack[i];
+            if (comp.isComponent && fn.call(scope || comp, comp) === false) {
+                return;
+            }
+        }
+    },
+
+    destroy: function() {
+        this.each(function(c) {
+            c.destroy();
+        });
+        delete this.zIndexStack;
+        delete this.list;
+        delete this.container;
+        delete this.targetEl;
+    }
+}, function() {
+    
+    Ext.WindowManager = Ext.WindowMgr = new this();
+});
+
+
+Ext.define('Ext.layout.container.boxOverflow.None', {
+    
+    alternateClassName: 'Ext.layout.boxOverflow.None',
+    
+    constructor: function(layout, config) {
+        this.layout = layout;
+        Ext.apply(this, config || {});
+    },
+
+    handleOverflow: Ext.emptyFn,
+
+    clearOverflow: Ext.emptyFn,
+    
+    onRemove: Ext.emptyFn,
+
+    
+    getItem: function(item) {
+        return this.layout.owner.getComponent(item);
+    },
+    
+    onRemove: Ext.emptyFn
+});
+
+Ext.define('Ext.util.KeyMap', {
+    alternateClassName: 'Ext.KeyMap',
+
+    
+    constructor: function(el, binding, eventName){
+        var me = this;
+
+        Ext.apply(me, {
+            el: Ext.get(el),
+            eventName: eventName || me.eventName,
+            bindings: []
+        });
+        if (binding) {
+            me.addBinding(binding);
+        }
+        me.enable();
+    },
+
+    eventName: 'keydown',
+
+    
+    addBinding : function(binding){
+        if (Ext.isArray(binding)) {
+            Ext.each(binding, this.addBinding, this);
+            return;
+        }
+
+        var keyCode = binding.key,
+            processed = false,
+            key,
+            keys,
+            keyString,
+            i,
+            len;
+
+        if (Ext.isString(keyCode)) {
+            keys = [];
+            keyString = keyCode.toUpperCase();
+
+            for (i = 0, len = keyString.length; i < len; ++i){
+                keys.push(keyString.charCodeAt(i));
+            }
+            keyCode = keys;
+            processed = true;
+        }
+
+        if (!Ext.isArray(keyCode)) {
+            keyCode = [keyCode];
+        }
+
+        if (!processed) {
+            for (i = 0, len = keyCode.length; i < len; ++i) {
+                key = keyCode[i];
+                if (Ext.isString(key)) {
+                    keyCode[i] = key.toUpperCase().charCodeAt(0);
+                }
+            }
+        }
+
+        this.bindings.push(Ext.apply({
+            keyCode: keyCode
+        }, binding));
+    },
+
+    
+    handleKeyDown: function(event) {
+        if (this.enabled) { 
+            var bindings = this.bindings,
+                i = 0,
+                len = bindings.length;
+
+            event = this.processEvent(event);
+            for(; i < len; ++i){
+                this.processBinding(bindings[i], event);
+            }
+        }
+    },
+
+    
+    processEvent: function(event){
+        return event;
+    },
+
+    
+    processBinding: function(binding, event){
+        if (this.checkModifiers(binding, event)) {
+            var key = event.getKey(),
+                handler = binding.fn || binding.handler,
+                scope = binding.scope || this,
+                keyCode = binding.keyCode,
+                defaultEventAction = binding.defaultEventAction,
+                i,
+                len,
+                keydownEvent = new Ext.EventObjectImpl(event);
+
+
+            for (i = 0, len = keyCode.length; i < len; ++i) {
+                if (key === keyCode[i]) {
+                    if (handler.call(scope, key, event) !== true && defaultEventAction) {
+                        keydownEvent[defaultEventAction]();
+                    }
+                    break;
+                }
+            }
+        }
+    },
+
+    
+    checkModifiers: function(binding, e){
+        var keys = ['shift', 'ctrl', 'alt'],
+            i = 0,
+            len = keys.length,
+            val, key;
+
+        for (; i < len; ++i){
+            key = keys[i];
+            val = binding[key];
+            if (!(val === undefined || (val === e[key + 'Key']))) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    
+    on: function(key, fn, scope) {
+        var keyCode, shift, ctrl, alt;
+        if (Ext.isObject(key) && !Ext.isArray(key)) {
+            keyCode = key.key;
+            shift = key.shift;
+            ctrl = key.ctrl;
+            alt = key.alt;
+        } else {
+            keyCode = key;
+        }
+        this.addBinding({
+            key: keyCode,
+            shift: shift,
+            ctrl: ctrl,
+            alt: alt,
+            fn: fn,
+            scope: scope
+        });
+    },
+
+    
+    isEnabled : function(){
+        return this.enabled;
+    },
+
+    
+    enable: function(){
+        var me = this;
+        
+        if (!me.enabled) {
+            me.el.on(me.eventName, me.handleKeyDown, me);
+            me.enabled = true;
+        }
+    },
+
+    
+    disable: function(){
+        var me = this;
+        
+        if (me.enabled) {
+            me.el.removeListener(me.eventName, me.handleKeyDown, me);
+            me.enabled = false;
+        }
+    },
+
+    
+    setDisabled : function(disabled){
+        if (disabled) {
+            this.disable();
+        } else {
+            this.enable();
+        }
+    },
+
+    
+    destroy: function(removeEl){
+        var me = this;
+
+        me.bindings = [];
+        me.disable();
+        if (removeEl === true) {
+            me.el.remove();
+        }
+        delete me.el;
+    }
+});
+
+Ext.define('Ext.util.ClickRepeater', {
+    extend: 'Ext.util.Observable',
+
+    
+    constructor : function(el, config){
+        this.el = Ext.get(el);
+        this.el.unselectable();
+
+        Ext.apply(this, config);
+
+        this.addEvents(
+        
+        "mousedown",
+        
+        "click",
+        
+        "mouseup"
+        );
+
+        if(!this.disabled){
+            this.disabled = true;
+            this.enable();
+        }
+
+        
+        if(this.handler){
+            this.on("click", this.handler,  this.scope || this);
+        }
+
+        this.callParent();
+    },
+
+    
+
+    
+
+    
+
+    
+    interval : 20,
+
+    
+    delay: 250,
+
+    
+    preventDefault : true,
+    
+    stopDefault : false,
+
+    timer : 0,
+
+    
+    enable: function(){
+        if(this.disabled){
+            this.el.on('mousedown', this.handleMouseDown, this);
+            if (Ext.isIE){
+                this.el.on('dblclick', this.handleDblClick, this);
+            }
+            if(this.preventDefault || this.stopDefault){
+                this.el.on('click', this.eventOptions, this);
+            }
+        }
+        this.disabled = false;
+    },
+
+    
+    disable: function( force){
+        if(force || !this.disabled){
+            clearTimeout(this.timer);
+            if(this.pressedCls){
+                this.el.removeCls(this.pressedCls);
+            }
+            Ext.getDoc().un('mouseup', this.handleMouseUp, this);
+            this.el.removeAllListeners();
+        }
+        this.disabled = true;
+    },
+
+    
+    setDisabled: function(disabled){
+        this[disabled ? 'disable' : 'enable']();
+    },
+
+    eventOptions: function(e){
+        if(this.preventDefault){
+            e.preventDefault();
+        }
+        if(this.stopDefault){
+            e.stopEvent();
+        }
+    },
+
+    
+    destroy : function() {
+        this.disable(true);
+        Ext.destroy(this.el);
+        this.clearListeners();
+    },
+
+    handleDblClick : function(e){
+        clearTimeout(this.timer);
+        this.el.blur();
+
+        this.fireEvent("mousedown", this, e);
+        this.fireEvent("click", this, e);
+    },
+
+    
+    handleMouseDown : function(e){
+        clearTimeout(this.timer);
+        this.el.blur();
+        if(this.pressedCls){
+            this.el.addCls(this.pressedCls);
+        }
+        this.mousedownTime = new Date();
+
+        Ext.getDoc().on("mouseup", this.handleMouseUp, this);
+        this.el.on("mouseout", this.handleMouseOut, this);
+
+        this.fireEvent("mousedown", this, e);
+        this.fireEvent("click", this, e);
+
+        
+        if (this.accelerate) {
+            this.delay = 400;
+        }
+
+        
+        
+        e = new Ext.EventObjectImpl(e);
+
+        this.timer =  Ext.defer(this.click, this.delay || this.interval, this, [e]);
+    },
+
+    
+    click : function(e){
+        this.fireEvent("click", this, e);
+        this.timer =  Ext.defer(this.click, this.accelerate ?
+            this.easeOutExpo(Ext.Date.getElapsed(this.mousedownTime),
+                400,
+                -390,
+                12000) :
+            this.interval, this, [e]);
+    },
+
+    easeOutExpo : function (t, b, c, d) {
+        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
+    },
+
+    
+    handleMouseOut : function(){
+        clearTimeout(this.timer);
+        if(this.pressedCls){
+            this.el.removeCls(this.pressedCls);
+        }
+        this.el.on("mouseover", this.handleMouseReturn, this);
+    },
+
+    
+    handleMouseReturn : function(){
+        this.el.un("mouseover", this.handleMouseReturn, this);
+        if(this.pressedCls){
+            this.el.addCls(this.pressedCls);
+        }
+        this.click();
+    },
+
+    
+    handleMouseUp : function(e){
+        clearTimeout(this.timer);
+        this.el.un("mouseover", this.handleMouseReturn, this);
+        this.el.un("mouseout", this.handleMouseOut, this);
+        Ext.getDoc().un("mouseup", this.handleMouseUp, this);
+        if(this.pressedCls){
+            this.el.removeCls(this.pressedCls);
+        }
+        this.fireEvent("mouseup", this, e);
+    }
+});
+
+
+Ext.define('Ext.layout.component.Component', {
+
+    
+
+    extend: 'Ext.layout.Layout',
+
+    
+
+    type: 'component',
+
+    monitorChildren: true,
+
+    initLayout : function() {
+        var me = this,
+            owner = me.owner,
+            ownerEl = owner.el;
+
+        if (!me.initialized) {
+            if (owner.frameSize) {
+                me.frameSize = owner.frameSize;
+            }
+            else {
+                owner.frameSize = me.frameSize = {
+                    top: 0,
+                    left: 0,
+                    bottom: 0,
+                    right: 0
+                };
+            }
+        }
+        me.callParent(arguments);
+    },
+
+    beforeLayout : function(width, height, isSetSize, callingContainer) {
+        this.callParent(arguments);
+
+        var me = this,
+            owner = me.owner,
+            ownerCt = owner.ownerCt,
+            layout = owner.layout,
+            isVisible = owner.isVisible(true),
+            ownerElChild = owner.el.child,
+            layoutCollection;
+
+        
+        me.previousComponentSize = me.lastComponentSize;
+
+        
+        if (!isSetSize
+            && ((!Ext.isNumber(width) && owner.isFixedWidth()) ||
+                (!Ext.isNumber(height) && owner.isFixedHeight()))
+            
+            && callingContainer && callingContainer !== ownerCt) {
+            
+            me.doContainerLayout();
+            return false;
+        }
+
+        
+        
+        if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
+            if (owner.hiddenAncestor) {
+                layoutCollection = owner.hiddenAncestor.layoutOnShow;
+                layoutCollection.remove(owner);
+                layoutCollection.add(owner);
+            }
+            owner.needsLayout = {
+                width: width,
+                height: height,
+                isSetSize: false
+            };
+        }
+
+        if (isVisible && this.needsLayout(width, height)) {
+            return owner.beforeComponentLayout(width, height, isSetSize, callingContainer);
+        }
+        else {
+            return false;
+        }
+    },
+
+    
+    needsLayout : function(width, height) {
+        var me = this,
+            widthBeingChanged,
+            heightBeingChanged;
+            me.lastComponentSize = me.lastComponentSize || {
+                width: -Infinity,
+                height: -Infinity
+            };
+
+        
+        widthBeingChanged  = !Ext.isDefined(width)  || me.lastComponentSize.width  !== width;
+
+        
+        heightBeingChanged = !Ext.isDefined(height) || me.lastComponentSize.height !== height;
+
+
+        
+        return !me.isSizing && (me.childrenChanged || widthBeingChanged || heightBeingChanged);
+    },
+
+    
+    setElementSize: function(el, width, height) {
+        if (width !== undefined && height !== undefined) {
+            el.setSize(width, height);
+        }
+        else if (height !== undefined) {
+            el.setHeight(height);
+        }
+        else if (width !== undefined) {
+            el.setWidth(width);
+        }
+    },
+
+    
+     getTarget : function() {
+         return this.owner.el;
+     },
+
+    
+    getRenderTarget : function() {
+        return this.owner.el;
+    },
+
+    
+    setTargetSize : function(width, height) {
+        var me = this;
+        me.setElementSize(me.owner.el, width, height);
+
+        if (me.owner.frameBody) {
+            var targetInfo = me.getTargetInfo(),
+                padding = targetInfo.padding,
+                border = targetInfo.border,
+                frameSize = me.frameSize;
+
+            me.setElementSize(me.owner.frameBody,
+                Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
+                Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
+            );
+        }
+
+        me.autoSized = {
+            width: !Ext.isNumber(width),
+            height: !Ext.isNumber(height)
+        };
+
+        me.lastComponentSize = {
+            width: width,
+            height: height
+        };
+    },
+
+    getTargetInfo : function() {
+        if (!this.targetInfo) {
+            var target = this.getTarget(),
+                body = this.owner.getTargetEl();
+
+            this.targetInfo = {
+                padding: {
+                    top: target.getPadding('t'),
+                    right: target.getPadding('r'),
+                    bottom: target.getPadding('b'),
+                    left: target.getPadding('l')
+                },
+                border: {
+                    top: target.getBorderWidth('t'),
+                    right: target.getBorderWidth('r'),
+                    bottom: target.getBorderWidth('b'),
+                    left: target.getBorderWidth('l')
+                },
+                bodyMargin: {
+                    top: body.getMargin('t'),
+                    right: body.getMargin('r'),
+                    bottom: body.getMargin('b'),
+                    left: body.getMargin('l')
+                }
+            };
+        }
+        return this.targetInfo;
+    },
+
+    
+    doOwnerCtLayouts: function() {
+        var owner = this.owner,
+            ownerCt = owner.ownerCt,
+            ownerCtComponentLayout, ownerCtContainerLayout,
+            curSize = this.lastComponentSize,
+            prevSize = this.previousComponentSize,
+            widthChange  = (prevSize && curSize && Ext.isNumber(curSize.width )) ? curSize.width  !== prevSize.width  : true,
+            heightChange = (prevSize && curSize && Ext.isNumber(curSize.height)) ? curSize.height !== prevSize.height : true;
+
+        
+        if (!ownerCt || (!widthChange && !heightChange)) {
+            return;
+        }
+
+        ownerCtComponentLayout = ownerCt.componentLayout;
+        ownerCtContainerLayout = ownerCt.layout;
+
+        if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
+            if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
+
+                
+                if (((widthChange && !ownerCt.isFixedWidth()) || (heightChange && !ownerCt.isFixedHeight()))) {
+                    
+                    this.isSizing = true;
+                    ownerCt.doComponentLayout();
+                    this.isSizing = false;
+                }
+                
+                else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
+                    ownerCtContainerLayout.layout();
+                }
+            }
+        }
+    },
+
+    doContainerLayout: function() {
+        var me = this,
+            owner = me.owner,
+            ownerCt = owner.ownerCt,
+            layout = owner.layout,
+            ownerCtComponentLayout;
+
+        
+        
+        if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy && !layout.isAutoDock) {
+            layout.layout();
+        }
+
+        
+        if (ownerCt && ownerCt.componentLayout) {
+            ownerCtComponentLayout = ownerCt.componentLayout;
+            if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
+                ownerCtComponentLayout.childrenChanged = true;
+            }
+        }
+    },
+
+    afterLayout : function(width, height, isSetSize, layoutOwner) {
+        this.doContainerLayout();
+        this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
+    }
+});
+
+
+Ext.define('Ext.util.TextMetrics', {
+    statics: {
+        shared: null,
+        
+        measure: function(el, text, fixedWidth){
+            var me = this,
+                shared = me.shared;
+            
+            if(!shared){
+                shared = me.shared = new me(el, fixedWidth);
+            }
+            shared.bind(el);
+            shared.setFixedWidth(fixedWidth || 'auto');
+            return shared.getSize(text);
+        },
+        
+        
+         destroy: function(){
+             var me = this;
+             Ext.destroy(me.shared);
+             me.shared = null;
+         }
+    },
+    
+    
+    constructor: function(bindTo, fixedWidth){
+        var measure = this.measure = Ext.getBody().createChild({
+            cls: 'x-textmetrics'
+        });
+        this.el = Ext.get(bindTo);
+        
+        measure.position('absolute');
+        measure.setLeftTop(-1000, -1000);
+        measure.hide();
+
+        if (fixedWidth) {
+           measure.setWidth(fixedWidth);
+        }
+    },
+    
+    
+    getSize: function(text){
+        var measure = this.measure,
+            size;
+        
+        measure.update(text);
+        size = measure.getSize();
+        measure.update('');
+        return size;
+    },
+    
+    
+    bind: function(el){
+        var me = this;
+        
+        me.el = Ext.get(el);
+        me.measure.setStyle(
+            me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
+        );
+    },
+    
+    
+     setFixedWidth : function(width){
+         this.measure.setWidth(width);
+     },
+     
+     
+     getWidth : function(text){
+         this.measure.dom.style.width = 'auto';
+         return this.getSize(text).width;
+     },
+     
+     
+     getHeight : function(text){
+         return this.getSize(text).height;
+     },
+     
+     
+     destroy: function(){
+         var me = this;
+         me.measure.remove();
+         delete me.el;
+         delete me.measure;
+     }
+}, function(){
+    Ext.Element.addMethods({
+        
+        getTextWidth : function(text, min, max){
+            return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000);
+        }
+    });
+});
+
+
+Ext.define('Ext.layout.container.boxOverflow.Scroller', {
+
+    
+
+    extend: 'Ext.layout.container.boxOverflow.None',
+    requires: ['Ext.util.ClickRepeater', 'Ext.Element'],
+    alternateClassName: 'Ext.layout.boxOverflow.Scroller',
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+    
+    
+
+    
+    animateScroll: false,
+
+    
+    scrollIncrement: 20,
+
+    
+    wheelIncrement: 10,
+
+    
+    scrollRepeatInterval: 60,
+
+    
+    scrollDuration: 400,
+
+    
+
+    
+
+    
+    scrollerCls: Ext.baseCSSPrefix + 'box-scroller',
+
+    
+
+    
+    
+    constructor: function(layout, config) {
+        this.layout = layout;
+        Ext.apply(this, config || {});
+        
+        this.addEvents(
+            
+            'scroll'
+        );
+    },
+    
+    initCSSClasses: function() {
+        var me = this,
+        layout = me.layout;
+
+        if (!me.CSSinitialized) {
+            me.beforeCtCls = me.beforeCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelBefore;
+            me.afterCtCls  = me.afterCtCls  || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelAfter;
+            me.beforeScrollerCls = me.beforeScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelBefore;
+            me.afterScrollerCls  = me.afterScrollerCls  || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelAfter;
+            me.CSSinitializes = true;
+        }
+    },
+
+    handleOverflow: function(calculations, targetSize) {
+        var me = this,
+            layout = me.layout,
+            methodName = 'get' + layout.parallelPrefixCap,
+            newSize = {};
+
+        me.initCSSClasses();
+        me.callParent(arguments);
+        this.createInnerElements();
+        this.showScrollers();
+        newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
+        newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - (me.beforeCt[methodName]() + me.afterCt[methodName]());
+        return { targetSize: newSize };
+    },
+
+    
+    createInnerElements: function() {
+        var me = this,
+            target = me.layout.getRenderTarget();
+
+        
+        
+        if (!me.beforeCt) {
+            target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
+            me.beforeCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls}, 'before');
+            me.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls},  'after');
+            me.createWheelListener();
+        }
+    },
+
+    
+    createWheelListener: function() {
+        this.layout.innerCt.on({
+            scope     : this,
+            mousewheel: function(e) {
+                e.stopEvent();
+
+                this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
+            }
+        });
+    },
+
+    
+    clearOverflow: function() {
+        this.hideScrollers();
+    },
+
+    
+    showScrollers: function() {
+        this.createScrollers();
+        this.beforeScroller.show();
+        this.afterScroller.show();
+        this.updateScrollButtons();
+        
+        this.layout.owner.addClsWithUI('scroller');
+    },
+
+    
+    hideScrollers: function() {
+        if (this.beforeScroller != undefined) {
+            this.beforeScroller.hide();
+            this.afterScroller.hide();
+            
+            this.layout.owner.removeClsWithUI('scroller');
+        }
+    },
+
+    
+    createScrollers: function() {
+        if (!this.beforeScroller && !this.afterScroller) {
+            var before = this.beforeCt.createChild({
+                cls: Ext.String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
+            });
+
+            var after = this.afterCt.createChild({
+                cls: Ext.String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
+            });
+
+            before.addClsOnOver(this.beforeScrollerCls + '-hover');
+            after.addClsOnOver(this.afterScrollerCls + '-hover');
+
+            before.setVisibilityMode(Ext.Element.DISPLAY);
+            after.setVisibilityMode(Ext.Element.DISPLAY);
+
+            this.beforeRepeater = Ext.create('Ext.util.ClickRepeater', before, {
+                interval: this.scrollRepeatInterval,
+                handler : this.scrollLeft,
+                scope   : this
+            });
+
+            this.afterRepeater = Ext.create('Ext.util.ClickRepeater', after, {
+                interval: this.scrollRepeatInterval,
+                handler : this.scrollRight,
+                scope   : this
+            });
+
+            
+            this.beforeScroller = before;
+
+            
+            this.afterScroller = after;
+        }
+    },
+
+    
+    destroy: function() {
+        Ext.destroy(this.beforeRepeater, this.afterRepeater, this.beforeScroller, this.afterScroller, this.beforeCt, this.afterCt);
+    },
+
+    
+    scrollBy: function(delta, animate) {
+        this.scrollTo(this.getScrollPosition() + delta, animate);
+    },
+
+    
+    getScrollAnim: function() {
+        return {
+            duration: this.scrollDuration, 
+            callback: this.updateScrollButtons, 
+            scope   : this
+        };
+    },
+
+    
+    updateScrollButtons: function() {
+        if (this.beforeScroller == undefined || this.afterScroller == undefined) {
+            return;
+        }
+
+        var beforeMeth = this.atExtremeBefore()  ? 'addCls' : 'removeCls',
+            afterMeth  = this.atExtremeAfter() ? 'addCls' : 'removeCls',
+            beforeCls  = this.beforeScrollerCls + '-disabled',
+            afterCls   = this.afterScrollerCls  + '-disabled';
+        
+        this.beforeScroller[beforeMeth](beforeCls);
+        this.afterScroller[afterMeth](afterCls);
+        this.scrolling = false;
+    },
+
+    
+    atExtremeBefore: function() {
+        return this.getScrollPosition() === 0;
+    },
+
+    
+    scrollLeft: function() {
+        this.scrollBy(-this.scrollIncrement, false);
+    },
+
+    
+    scrollRight: function() {
+        this.scrollBy(this.scrollIncrement, false);
+    },
+
+    
+    getScrollPosition: function(){
+        var layout = this.layout;
+        return parseInt(layout.innerCt.dom['scroll' + layout.parallelBeforeCap], 10) || 0;
+    },
+
+    
+    getMaxScrollPosition: function() {
+        var layout = this.layout;
+        return layout.innerCt.dom['scroll' + layout.parallelPrefixCap] - this.layout.innerCt['get' + layout.parallelPrefixCap]();
+    },
+
+    
+    atExtremeAfter: function() {
+        return this.getScrollPosition() >= this.getMaxScrollPosition();
+    },
+
+    
+    scrollTo: function(position, animate) {
+        var me = this,
+            layout = me.layout,
+            oldPosition = me.getScrollPosition(),
+            newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());
+
+        if (newPosition != oldPosition && !me.scrolling) {
+            if (animate == undefined) {
+                animate = me.animateScroll;
+            }
+
+            layout.innerCt.scrollTo(layout.parallelBefore, newPosition, animate ? me.getScrollAnim() : false);
+            if (animate) {
+                me.scrolling = true;
+            } else {
+                me.scrolling = false;
+                me.updateScrollButtons();
+            }
+            
+            me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);
+        }
+    },
+
+    
+    scrollToItem: function(item, animate) {
+        var me = this,
+            layout = me.layout,
+            visibility,
+            box,
+            newPos;
+
+        item = me.getItem(item);
+        if (item != undefined) {
+            visibility = this.getItemVisibility(item);
+            if (!visibility.fullyVisible) {
+                box  = item.getBox(true, true);
+                newPos = box[layout.parallelPosition];
+                if (visibility.hiddenEnd) {
+                    newPos -= (this.layout.innerCt['get' + layout.parallelPrefixCap]() - box[layout.parallelPrefix]);
+                }
+                this.scrollTo(newPos, animate);
+            }
+        }
+    },
+
+    
+    getItemVisibility: function(item) {
+        var me          = this,
+            box         = me.getItem(item).getBox(true, true),
+            layout      = me.layout,
+            itemStart   = box[layout.parallelPosition],
+            itemEnd     = itemStart + box[layout.parallelPrefix],
+            scrollStart = me.getScrollPosition(),
+            scrollEnd   = scrollStart + layout.innerCt['get' + layout.parallelPrefixCap]();
+
+        return {
+            hiddenStart : itemStart < scrollStart,
+            hiddenEnd   : itemEnd > scrollEnd,
+            fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd
+        };
+    }
+});
+
+Ext.define('Ext.util.Offset', {
+
+    
+
+    statics: {
+        fromObject: function(obj) {
+            return new this(obj.x, obj.y);
+        }
+    },
+
+    
+
+    constructor: function(x, y) {
+        this.x = (x != null && !isNaN(x)) ? x : 0;
+        this.y = (y != null && !isNaN(y)) ? y : 0;
+
+        return this;
+    },
+
+    copy: function() {
+        return new Ext.util.Offset(this.x, this.y);
+    },
+
+    copyFrom: function(p) {
+        this.x = p.x;
+        this.y = p.y;
+    },
+
+    toString: function() {
+        return "Offset[" + this.x + "," + this.y + "]";
+    },
+
+    equals: function(offset) {
+
+        return (this.x == offset.x && this.y == offset.y);
+    },
+
+    round: function(to) {
+        if (!isNaN(to)) {
+            var factor = Math.pow(10, to);
+            this.x = Math.round(this.x * factor) / factor;
+            this.y = Math.round(this.y * factor) / factor;
+        } else {
+            this.x = Math.round(this.x);
+            this.y = Math.round(this.y);
+        }
+    },
+
+    isZero: function() {
+        return this.x == 0 && this.y == 0;
+    }
+});
+
+
+Ext.define('Ext.util.KeyNav', {
+    
+    alternateClassName: 'Ext.KeyNav',
+    
+    requires: ['Ext.util.KeyMap'],
+    
+    statics: {
+        keyOptions: {
+            left: 37,
+            right: 39,
+            up: 38,
+            down: 40,
+            space: 32,
+            pageUp: 33,
+            pageDown: 34,
+            del: 46,
+            backspace: 8,
+            home: 36,
+            end: 35,
+            enter: 13,
+            esc: 27,
+            tab: 9
+        }
+    },
+
+    
+    constructor: function(el, config){
+        this.setConfig(el, config || {});
+    },
+    
+    
+    setConfig: function(el, config) {
+        if (this.map) {
+            this.map.destroy();
+        }
+        
+        var map = Ext.create('Ext.util.KeyMap', el, null, this.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : this.forceKeyDown)),
+            keys = Ext.util.KeyNav.keyOptions,
+            scope = config.scope || this,
+            key;
+        
+        this.map = map;
+        for (key in keys) {
+            if (keys.hasOwnProperty(key)) {
+                if (config[key]) {
+                    map.addBinding({
+                        scope: scope,
+                        key: keys[key],
+                        handler: Ext.Function.bind(this.handleEvent, scope, [config[key]], true),
+                        defaultEventAction: config.defaultEventAction || this.defaultEventAction
+                    });
+                }
+            }
+        }
+        
+        map.disable();
+        if (!config.disabled) {
+            map.enable();
+        }
+    },
+    
+    
+    handleEvent: function(map, event, handler){
+        return handler.call(this, event);
+    },
+    
+    
+    disabled: false,
+    
+    
+    defaultEventAction: "stopEvent",
+    
+    
+    forceKeyDown: false,
+    
+    
+    destroy: function(removeEl){
+        this.map.destroy(removeEl);
+        delete this.map;
+    },
+
+    
+    enable: function() {
+        this.map.enable();
+        this.disabled = false;
+    },
+
+    
+    disable: function() {
+        this.map.disable();
+        this.disabled = true;
+    },
+    
+    
+    setDisabled : function(disabled){
+        this.map.setDisabled(disabled);
+        this.disabled = disabled;
+    },
+    
+    
+    getKeyEvent: function(forceKeyDown){
+        return (forceKeyDown || Ext.EventManager.useKeyDown) ? 'keydown' : 'keypress';
+    }
+});
+
+
+
+Ext.define('Ext.fx.Queue', {
+
+    requires: ['Ext.util.HashMap'],
+
+    constructor: function() {
+        this.targets = Ext.create('Ext.util.HashMap');
+        this.fxQueue = {};
+    },
+
+    
+    getFxDefaults: function(targetId) {
+        var target = this.targets.get(targetId);
+        if (target) {
+            return target.fxDefaults;
+        }
+        return {};
+    },
+
+    
+    setFxDefaults: function(targetId, obj) {
+        var target = this.targets.get(targetId);
+        if (target) {
+            target.fxDefaults = Ext.apply(target.fxDefaults || {}, obj);
+        }
+    },
+
+    
+    stopAnimation: function(targetId) {
+        var me = this,
+            queue = me.getFxQueue(targetId),
+            ln = queue.length;
+        while (ln) {
+            queue[ln - 1].end();
+            ln--;
+        }
+    },
+
+    
+    getActiveAnimation: function(targetId) {
+        var queue = this.getFxQueue(targetId);
+        return (queue && !!queue.length) ? queue[0] : false;
+    },
+
+    
+    hasFxBlock: function(targetId) {
+        var queue = this.getFxQueue(targetId);
+        return queue && queue[0] && queue[0].block;
+    },
+
+    
+    getFxQueue: function(targetId) {
+        if (!targetId) {
+            return false;
+        }
+        var me = this,
+            queue = me.fxQueue[targetId],
+            target = me.targets.get(targetId);
+
+        if (!target) {
+            return false;
+        }
+
+        if (!queue) {
+            me.fxQueue[targetId] = [];
+            
+            if (target.type != 'element') {
+                target.target.on('destroy', function() {
+                    me.fxQueue[targetId] = [];
+                });
+            }
+        }
+        return me.fxQueue[targetId];
+    },
+
+    
+    queueFx: function(anim) {
+        var me = this,
+            target = anim.target,
+            queue, ln;
+
+        if (!target) {
+            return;
+        }
+
+        queue = me.getFxQueue(target.getId());
+        ln = queue.length;
+
+        if (ln) {
+            if (anim.concurrent) {
+                anim.paused = false;
+            }
+            else {
+                queue[ln - 1].on('afteranimate', function() {
+                    anim.paused = false;
+                });
+            }
+        }
+        else {
+            anim.paused = false;
+        }
+        anim.on('afteranimate', function() {
+            Ext.Array.remove(queue, anim);
+            if (anim.remove) {
+                if (target.type == 'element') {
+                    var el = Ext.get(target.id);
+                    if (el) {
+                        el.remove();
+                    }
+                }
+            }
+        }, this);
+        queue.push(anim);
+    }
+});
+
+Ext.define('Ext.fx.target.Target', {
+
+    isAnimTarget: true,
+
+    
+    constructor: function(target) {
+        this.target = target;
+        this.id = this.getId();
+    },
+    
+    getId: function() {
+        return this.target.id;
+    }
+});
+
+
+
+Ext.define('Ext.fx.target.Sprite', {
+
+    
+
+    extend: 'Ext.fx.target.Target',
+
+    
+
+    type: 'draw',
+
+    getFromPrim: function(sprite, attr) {
+        var o;
+        if (attr == 'translate') {
+            o = {
+                x: sprite.attr.translation.x || 0,
+                y: sprite.attr.translation.y || 0
+            };
+        }
+        else if (attr == 'rotate') {
+            o = {
+                degrees: sprite.attr.rotation.degrees || 0,
+                x: sprite.attr.rotation.x,
+                y: sprite.attr.rotation.y
+            };
+        }
+        else {
+            o = sprite.attr[attr];
+        }
+        return o;
+    },
+
+    getAttr: function(attr, val) {
+        return [[this.target, val != undefined ? val : this.getFromPrim(this.target, attr)]];
+    },
+
+    setAttr: function(targetData) {
+        var ln = targetData.length,
+            spriteArr = [],
+            attrs, attr, attrArr, attPtr, spritePtr, idx, value, i, j, x, y, ln2;
+        for (i = 0; i < ln; i++) {
+            attrs = targetData[i].attrs;
+            for (attr in attrs) {
+                attrArr = attrs[attr];
+                ln2 = attrArr.length;
+                for (j = 0; j < ln2; j++) {
+                    spritePtr = attrArr[j][0];
+                    attPtr = attrArr[j][1];
+                    if (attr === 'translate') {
+                        value = {
+                            x: attPtr.x,
+                            y: attPtr.y
+                        };
+                    }
+                    else if (attr === 'rotate') {
+                        x = attPtr.x;
+                        if (isNaN(x)) {
+                            x = null;
+                        }
+                        y = attPtr.y;
+                        if (isNaN(y)) {
+                            y = null;
+                        }
+                        value = {
+                            degrees: attPtr.degrees,
+                            x: x,
+                            y: y
+                        };
+                    }
+                    else if (attr === 'width' || attr === 'height' || attr === 'x' || attr === 'y') {
+                        value = parseFloat(attPtr);
+                    }
+                    else {
+                        value = attPtr;
+                    }
+                    idx = Ext.Array.indexOf(spriteArr, spritePtr);
+                    if (idx == -1) {
+                        spriteArr.push([spritePtr, {}]);
+                        idx = spriteArr.length - 1;
+                    }
+                    spriteArr[idx][1][attr] = value;
+                }
+            }
+        }
+        ln = spriteArr.length;
+        for (i = 0; i < ln; i++) {
+            spritePtr = spriteArr[i];
+            spritePtr[0].setAttributes(spritePtr[1]);
+        }
+        this.target.redraw();
+    }
+});
+
+
+
+Ext.define('Ext.fx.target.CompositeSprite', {
+
+    
+
+    extend: 'Ext.fx.target.Sprite',
+
+    
+
+    getAttr: function(attr, val) {
+        var out = [],
+            target = this.target;
+        target.each(function(sprite) {
+            out.push([sprite, val != undefined ? val : this.getFromPrim(sprite, attr)]);
+        }, this);
+        return out;
+    }
+});
+
+
+Ext.define('Ext.fx.target.Component', {
+
+    
+   
+    extend: 'Ext.fx.target.Target',
+    
+    
+
+    type: 'component',
+
+    
+    getPropMethod: {
+        top: function() {
+            return this.getPosition(true)[1];
+        },
+        left: function() {
+            return this.getPosition(true)[0];
+        },
+        x: function() {
+            return this.getPosition()[0];
+        },
+        y: function() {
+            return this.getPosition()[1];
+        },
+        height: function() {
+            return this.getHeight();
+        },
+        width: function() {
+            return this.getWidth();
+        },
+        opacity: function() {
+            return this.el.getStyle('opacity');
+        }
+    },
+
+    compMethod: {
+        top: 'setPosition',
+        left: 'setPosition',
+        x: 'setPagePosition',
+        y: 'setPagePosition',
+        height: 'setSize',
+        width: 'setSize',
+        opacity: 'setOpacity'
+    },
+
+    
+    getAttr: function(attr, val) {
+        return [[this.target, val !== undefined ? val : this.getPropMethod[attr].call(this.target)]];
+    },
+
+    setAttr: function(targetData, isFirstFrame, isLastFrame) {
+        var me = this,
+            target = me.target,
+            ln = targetData.length,
+            attrs, attr, o, i, j, meth, targets, left, top, w, h;
+        for (i = 0; i < ln; i++) {
+            attrs = targetData[i].attrs;
+            for (attr in attrs) {
+                targets = attrs[attr].length;
+                meth = {
+                    setPosition: {},
+                    setPagePosition: {},
+                    setSize: {},
+                    setOpacity: {}
+                };
+                for (j = 0; j < targets; j++) {
+                    o = attrs[attr][j];
+                    
+                    
+                    
+                    
+                    meth[me.compMethod[attr]].target = o[0];
+                    meth[me.compMethod[attr]][attr] = o[1];
+                }
+                if (meth.setPosition.target) {
+                    o = meth.setPosition;
+                    left = (o.left === undefined) ? undefined : parseInt(o.left, 10);
+                    top = (o.top === undefined) ? undefined : parseInt(o.top, 10);
+                    o.target.setPosition(left, top);
+                }
+                if (meth.setPagePosition.target) {
+                    o = meth.setPagePosition;
+                    o.target.setPagePosition(o.x, o.y);
+                }
+                if (meth.setSize.target && meth.setSize.target.el) {
+                    o = meth.setSize;
+                    
+                    w = (o.width === undefined) ? o.target.getWidth() : parseInt(o.width, 10);
+                    h = (o.height === undefined) ? o.target.getHeight() : parseInt(o.height, 10);
+
+                    
+                    
+                    
+                    
+                    
+                    
+                    
+                    if (isLastFrame || me.dynamic) {
+                        o.target.componentLayout.childrenChanged = true;
+
+                        
+                        if (me.layoutAnimation) {
+                            o.target.setCalculatedSize(w, h);
+                        } else {
+                            o.target.setSize(w, h);
+                        }
+                    }
+                    else {
+                        o.target.el.setSize(w, h);
+                    }
+                }
+                if (meth.setOpacity.target) {
+                    o = meth.setOpacity;
+                    o.target.el.setStyle('opacity', o.opacity);
+                }
+            }
+        }
+    }
+});
+
+
+Ext.define('Ext.fx.CubicBezier', {
+
+    
+
+    singleton: true,
+
+    
+
+    cubicBezierAtTime: function(t, p1x, p1y, p2x, p2y, duration) {
+        var cx = 3 * p1x,
+            bx = 3 * (p2x - p1x) - cx,
+            ax = 1 - cx - bx,
+            cy = 3 * p1y,
+            by = 3 * (p2y - p1y) - cy,
+            ay = 1 - cy - by;
+        function sampleCurveX(t) {
+            return ((ax * t + bx) * t + cx) * t;
+        }
+        function solve(x, epsilon) {
+            var t = solveCurveX(x, epsilon);
+            return ((ay * t + by) * t + cy) * t;
+        }
+        function solveCurveX(x, epsilon) {
+            var t0, t1, t2, x2, d2, i;
+            for (t2 = x, i = 0; i < 8; i++) {
+                x2 = sampleCurveX(t2) - x;
+                if (Math.abs(x2) < epsilon) {
+                    return t2;
+                }
+                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
+                if (Math.abs(d2) < 1e-6) {
+                    break;
+                }
+                t2 = t2 - x2 / d2;
+            }
+            t0 = 0;
+            t1 = 1;
+            t2 = x;
+            if (t2 < t0) {
+                return t0;
+            }
+            if (t2 > t1) {
+                return t1;
+            }
+            while (t0 < t1) {
+                x2 = sampleCurveX(t2);
+                if (Math.abs(x2 - x) < epsilon) {
+                    return t2;
+                }
+                if (x > x2) {
+                    t0 = t2;
+                } else {
+                    t1 = t2;
+                }
+                t2 = (t1 - t0) / 2 + t0;
+            }
+            return t2;
+        }
+        return solve(t, 1 / (200 * duration));
+    },
+
+    cubicBezier: function(x1, y1, x2, y2) {
+        var fn = function(pos) {
+            return Ext.fx.CubicBezier.cubicBezierAtTime(pos, x1, y1, x2, y2, 1);
+        };
+        fn.toCSS3 = function() {
+            return 'cubic-bezier(' + [x1, y1, x2, y2].join(',') + ')';
+        };
+        fn.reverse = function() {
+            return Ext.fx.CubicBezier.cubicBezier(1 - x2, 1 - y2, 1 - x1, 1 - y1);
+        };
+        return fn;
+    }
+});
+
+Ext.define('Ext.draw.Color', {
+
+    
+
+    
+
+    colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
+    rgbRe: /\s*rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/,
+    hexRe: /\s*#([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/,
+
+    
+    lightnessFactor: 0.2,
+
+    
+    constructor : function(red, green, blue) {
+        var me = this,
+            clamp = Ext.Number.constrain;
+        me.r = clamp(red, 0, 255);
+        me.g = clamp(green, 0, 255);
+        me.b = clamp(blue, 0, 255);
+    },
+
+    
+    getRed: function() {
+        return this.r;
+    },
+
+    
+    getGreen: function() {
+        return this.g;
+    },
+
+    
+    getBlue: function() {
+        return this.b;
+    },
+
+    
+    getRGB: function() {
+        var me = this;
+        return [me.r, me.g, me.b];
+    },
+
+    
+    getHSL: function() {
+        var me = this,
+            r = me.r / 255,
+            g = me.g / 255,
+            b = me.b / 255,
+            max = Math.max(r, g, b),
+            min = Math.min(r, g, b),
+            delta = max - min,
+            h,
+            s = 0,
+            l = 0.5 * (max + min);
+
+        
+        if (min != max) {
+            s = (l < 0.5) ? delta / (max + min) : delta / (2 - max - min);
+            if (r == max) {
+                h = 60 * (g - b) / delta;
+            } else if (g == max) {
+                h = 120 + 60 * (b - r) / delta;
+            } else {
+                h = 240 + 60 * (r - g) / delta;
+            }
+            if (h < 0) {
+                h += 360;
+            }
+            if (h >= 360) {
+                h -= 360;
+            }
+        }
+        return [h, s, l];
+    },
+
+    
+    getLighter: function(factor) {
+        var hsl = this.getHSL();
+        factor = factor || this.lightnessFactor;
+        hsl[2] = Ext.Number.constrain(hsl[2] + factor, 0, 1);
+        return this.fromHSL(hsl[0], hsl[1], hsl[2]);
+    },
+
+    
+    getDarker: function(factor) {
+        factor = factor || this.lightnessFactor;
+        return this.getLighter(-factor);
+    },
+
+    
+    toString: function() {
+        var me = this,
+            round = Math.round,
+            r = round(me.r).toString(16),
+            g = round(me.g).toString(16),
+            b = round(me.b).toString(16);
+        r = (r.length == 1) ? '0' + r : r;
+        g = (g.length == 1) ? '0' + g : g;
+        b = (b.length == 1) ? '0' + b : b;
+        return ['#', r, g, b].join('');
+    },
+
+    
+    toHex: function(color) {
+        if (Ext.isArray(color)) {
+            color = color[0];
+        }
+        if (!Ext.isString(color)) {
+            return '';
+        }
+        if (color.substr(0, 1) === '#') {
+            return color;
+        }
+        var digits = this.colorToHexRe.exec(color);
+
+        if (Ext.isArray(digits)) {
+            var red = parseInt(digits[2], 10),
+                green = parseInt(digits[3], 10),
+                blue = parseInt(digits[4], 10),
+                rgb = blue | (green << 8) | (red << 16);
+            return digits[1] + '#' + ("000000" + rgb.toString(16)).slice(-6);
+        }
+        else {
+            return '';
+        }
+    },
+
+    
+    fromString: function(str) {
+        var values, r, g, b,
+            parse = parseInt;
+
+        if ((str.length == 4 || str.length == 7) && str.substr(0, 1) === '#') {
+            values = str.match(this.hexRe);
+            if (values) {
+                r = parse(values[1], 16) >> 0;
+                g = parse(values[2], 16) >> 0;
+                b = parse(values[3], 16) >> 0;
+                if (str.length == 4) {
+                    r += (r * 16);
+                    g += (g * 16);
+                    b += (b * 16);
+                }
+            }
+        }
+        else {
+            values = str.match(this.rgbRe);
+            if (values) {
+                r = values[1];
+                g = values[2];
+                b = values[3];
+            }
+        }
+
+        return (typeof r == 'undefined') ? undefined : Ext.create('Ext.draw.Color', r, g, b);
+    },
+
+    
+    getGrayscale: function() {
+        
+        return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
+    },
+
+    
+    fromHSL: function(h, s, l) {
+        var C, X, m, i, rgb = [],
+            abs = Math.abs,
+            floor = Math.floor;
+
+        if (s == 0 || h == null) {
+            
+            rgb = [l, l, l];
+        }
+        else {
+            
+            
+            
+            
+            h /= 60;
+            C = s * (1 - abs(2 * l - 1));
+            X = C * (1 - abs(h - 2 * floor(h / 2) - 1));
+            m = l - C / 2;
+            switch (floor(h)) {
+                case 0:
+                    rgb = [C, X, 0];
+                    break;
+                case 1:
+                    rgb = [X, C, 0];
+                    break;
+                case 2:
+                    rgb = [0, C, X];
+                    break;
+                case 3:
+                    rgb = [0, X, C];
+                    break;
+                case 4:
+                    rgb = [X, 0, C];
+                    break;
+                case 5:
+                    rgb = [C, 0, X];
+                    break;
+            }
+            rgb = [rgb[0] + m, rgb[1] + m, rgb[2] + m];
+        }
+        return Ext.create('Ext.draw.Color', rgb[0] * 255, rgb[1] * 255, rgb[2] * 255);
+    }
+}, function() {
+    var prototype = this.prototype;
+
+    
+    this.addStatics({
+        fromHSL: function() {
+            return prototype.fromHSL.apply(prototype, arguments);
+        },
+        fromString: function() {
+            return prototype.fromString.apply(prototype, arguments);
+        },
+        toHex: function() {
+            return prototype.toHex.apply(prototype, arguments);
+        }
+    });
+});
+
+
+Ext.define('Ext.dd.StatusProxy', {
+    animRepair: false,
+
+    
+    constructor: function(config){
+        Ext.apply(this, config);
+        this.id = this.id || Ext.id();
+        this.proxy = Ext.createWidget('component', {
+            floating: true,
+            stateful: false,
+            id: this.id,
+            html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
+                  '<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
+            cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
+            shadow: !config || config.shadow !== false,
+            renderTo: document.body
+        });
+
+        this.el = this.proxy.el;
+        this.el.show();
+        this.el.setVisibilityMode(Ext.Element.VISIBILITY);
+        this.el.hide();
+
+        this.ghost = Ext.get(this.el.dom.childNodes[1]);
+        this.dropStatus = this.dropNotAllowed;
+    },
+    
+    dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
+    
+    dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+    
+    setStatus : function(cssClass){
+        cssClass = cssClass || this.dropNotAllowed;
+        if(this.dropStatus != cssClass){
+            this.el.replaceCls(this.dropStatus, cssClass);
+            this.dropStatus = cssClass;
+        }
+    },
+
+    
+    reset : function(clearGhost){
+        this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
+        this.dropStatus = this.dropNotAllowed;
+        if(clearGhost){
+            this.ghost.update("");
+        }
+    },
+
+    
+    update : function(html){
+        if(typeof html == "string"){
+            this.ghost.update(html);
+        }else{
+            this.ghost.update("");
+            html.style.margin = "0";
+            this.ghost.dom.appendChild(html);
+        }
+        var el = this.ghost.dom.firstChild;
+        if(el){
+            Ext.fly(el).setStyle('float', 'none');
+        }
+    },
+
+    
+    getEl : function(){
+        return this.el;
+    },
+
+    
+    getGhost : function(){
+        return this.ghost;
+    },
+
+    
+    hide : function(clear) {
+        this.proxy.hide();
+        if (clear) {
+            this.reset(true);
+        }
+    },
+
+    
+    stop : function(){
+        if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
+            this.anim.stop();
+        }
+    },
+
+    
+    show : function() {
+        this.proxy.show();
+        this.proxy.toFront();
+    },
+
+    
+    sync : function(){
+        this.proxy.el.sync();
+    },
+
+    
+    repair : function(xy, callback, scope){
+        this.callback = callback;
+        this.scope = scope;
+        if (xy && this.animRepair !== false) {
+            this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
+            this.el.hideUnders(true);
+            this.anim = this.el.animate({
+                duration: this.repairDuration || 500,
+                easing: 'ease-out',
+                to: {
+                    x: xy[0],
+                    y: xy[1]
+                },
+                stopAnimation: true,
+                callback: this.afterRepair,
+                scope: this
+            });
+        } else {
+            this.afterRepair();
+        }
+    },
+
+    
+    afterRepair : function(){
+        this.hide(true);
+        if(typeof this.callback == "function"){
+            this.callback.call(this.scope || this);
+        }
+        this.callback = null;
+        this.scope = null;
+    },
+
+    destroy: function(){
+        Ext.destroy(this.ghost, this.proxy, this.el);
+    }
+});
+
+Ext.define('Ext.panel.Proxy', {
+
+    alternateClassName: 'Ext.dd.PanelProxy',
+
+    
+    constructor: function(panel, config){
+        
+        this.panel = panel;
+        this.id = this.panel.id +'-ddproxy';
+        Ext.apply(this, config);
+    },
+
+    
+    insertProxy: true,
+
+    
+    setStatus: Ext.emptyFn,
+    reset: Ext.emptyFn,
+    update: Ext.emptyFn,
+    stop: Ext.emptyFn,
+    sync: Ext.emptyFn,
+
+    
+    getEl: function(){
+        return this.ghost.el;
+    },
+
+    
+    getGhost: function(){
+        return this.ghost;
+    },
+
+    
+    getProxy: function(){
+        return this.proxy;
+    },
+
+    
+    hide : function(){
+        if (this.ghost) {
+            if (this.proxy) {
+                this.proxy.remove();
+                delete this.proxy;
+            }
+
+            
+            this.panel.unghost(null, false);
+            delete this.ghost;
+        }
+    },
+
+    
+    show: function(){
+        if (!this.ghost) {
+            var panelSize = this.panel.getSize();
+            this.panel.el.setVisibilityMode(Ext.Element.DISPLAY);
+            this.ghost = this.panel.ghost();
+            if (this.insertProxy) {
+                
+                
+                this.proxy = this.panel.el.insertSibling({cls: Ext.baseCSSPrefix + 'panel-dd-spacer'});
+                this.proxy.setSize(panelSize);
+            }
+        }
+    },
+
+    
+    repair: function(xy, callback, scope) {
+        this.hide();
+        if (typeof callback == "function") {
+            callback.call(scope || this);
+        }
+    },
+
+    
+    moveProxy : function(parentNode, before){
+        if (this.proxy) {
+            parentNode.insertBefore(this.proxy.dom, before);
+        }
+    }
+});
+
+
+Ext.define('Ext.layout.component.AbstractDock', {
+
+    
+
+    extend: 'Ext.layout.component.Component',
+
+    
+
+    type: 'dock',
+
+    
+    autoSizing: true,
+
+    beforeLayout: function() {
+        var returnValue = this.callParent(arguments);
+        if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
+            this.handleItemBorders();
+            this.initializedBorders = true;
+        }
+        return returnValue;
+    },
+    
+    handleItemBorders: function() {
+        var owner = this.owner,
+            body = owner.body,
+            docked = this.getLayoutItems(),
+            borders = {
+                top: [],
+                right: [],
+                bottom: [],
+                left: []
+            },
+            oldBorders = this.borders,
+            opposites = {
+                top: 'bottom',
+                right: 'left',
+                bottom: 'top',
+                left: 'right'
+            },
+            i, ln, item, dock, side;
+
+        for (i = 0, ln = docked.length; i < ln; i++) {
+            item = docked[i];
+            dock = item.dock;
+            
+            if (item.ignoreBorderManagement) {
+                continue;
+            }
+            
+            if (!borders[dock].satisfied) {
+                borders[dock].push(item);
+                borders[dock].satisfied = true;
+            }
+            
+            if (!borders.top.satisfied && opposites[dock] !== 'top') {
+                borders.top.push(item);
+            }
+            if (!borders.right.satisfied && opposites[dock] !== 'right') {
+                borders.right.push(item);
+            }            
+            if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
+                borders.bottom.push(item);
+            }            
+            if (!borders.left.satisfied && opposites[dock] !== 'left') {
+                borders.left.push(item);
+            }
+        }
+
+        if (oldBorders) {
+            for (side in oldBorders) {
+                if (oldBorders.hasOwnProperty(side)) {
+                    ln = oldBorders[side].length;
+                    if (!owner.manageBodyBorders) {
+                        for (i = 0; i < ln; i++) {
+                            oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
+                        }
+                        if (!oldBorders[side].satisfied && !owner.bodyBorder) {
+                            body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
+                        }                    
+                    }
+                    else if (oldBorders[side].satisfied) {
+                        body.setStyle('border-' + side + '-width', '');
+                    }
+                }
+            }
+        }
+                
+        for (side in borders) {
+            if (borders.hasOwnProperty(side)) {
+                ln = borders[side].length;
+                if (!owner.manageBodyBorders) {
+                    for (i = 0; i < ln; i++) {
+                        borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
+                    }
+                    if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
+                        body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
+                    }                    
+                }
+                else if (borders[side].satisfied) {
+                    body.setStyle('border-' + side + '-width', '1px');
+                }
+            }
+        }
+        
+        this.borders = borders;
+    },
+    
+    
+    onLayout: function(width, height) {
+        if (this.onLayout_running) {
+            return;
+        }
+        this.onLayout_running = true;
+        var me = this,
+            owner = me.owner,
+            body = owner.body,
+            layout = owner.layout,
+            target = me.getTarget(),
+            autoWidth = false,
+            autoHeight = false,
+            padding, border, frameSize;
+
+        
+        var info = me.info = {
+            boxes: [],
+            size: {
+                width: width,
+                height: height
+            },
+            bodyBox: {}
+        };
+        
+        delete layout.isAutoDock;
+
+        Ext.applyIf(info, me.getTargetInfo());
+
+        
+        if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
+            if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
+                owner.ownerCt.layout.bindToOwnerCtComponent = true;
+            }
+            else {
+                owner.ownerCt.layout.bindToOwnerCtComponent = false;
+            }
+        }
+
+        
+        if (height == null || width == null) {
+            padding = info.padding;
+            border = info.border;
+            frameSize = me.frameSize;
+
+            
+            if ((height == null) && (width == null)) {
+                autoHeight = true;
+                autoWidth = true;
+                me.setTargetSize(null);
+                me.setBodyBox({width: null, height: null});
+            }
+            
+            else if (height == null) {
+                autoHeight = true;
+                
+                me.setTargetSize(width);
+                me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
+            
+            }
+            else {
+                autoWidth = true;
+                
+                me.setTargetSize(null, height);
+                me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
+            }
+
+            
+            if (layout && layout.isLayout) {
+                
+                layout.bindToOwnerCtComponent = true;
+                
+                layout.isAutoDock = layout.autoSize !== true;
+                layout.layout();
+
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                
+                info.autoSizedCtLayout = layout.autoSize === true;
+                info.autoHeight = autoHeight;
+                info.autoWidth = autoWidth;
+            }
+
+            
+            
+            
+            
+            
+            me.dockItems();
+            me.setTargetSize(info.size.width, info.size.height);
+        }
+        else {
+            me.setTargetSize(width, height);
+            me.dockItems();
+        }
+        me.callParent(arguments);
+        this.onLayout_running = false;
+    },
+
+    
+    dockItems : function() {
+        this.calculateDockBoxes();
+
+        
+        
+        
+        var info = this.info,
+            autoWidth = info.autoWidth,
+            autoHeight = info.autoHeight,
+            boxes = info.boxes,
+            ln = boxes.length,
+            dock, i, item;
+
+        
+        
+        for (i = 0; i < ln; i++) {
+            dock = boxes[i];
+            item = dock.item;
+            item.setPosition(dock.x, dock.y);
+            if ((autoWidth || autoHeight) && item.layout && item.layout.isLayout) {
+                
+                item.layout.bindToOwnerCtComponent = true;
+            }
+        }
+
+        
+        
+        if (!info.autoSizedCtLayout) {
+            if (autoWidth) {
+                info.bodyBox.width = null;
+            }
+            if (autoHeight) {
+                info.bodyBox.height = null;
+            }
+        }
+
+        
+        
+        this.setBodyBox(info.bodyBox);
+    },
+
+    
+    calculateDockBoxes : function() {
+        if (this.calculateDockBoxes_running) {
+            
+            return;
+        }
+        this.calculateDockBoxes_running = true;
+        
+        
+        
+        var me = this,
+            target = me.getTarget(),
+            items = me.getLayoutItems(),
+            owner = me.owner,
+            bodyEl = owner.body,
+            info = me.info,
+            autoWidth = info.autoWidth,
+            autoHeight = info.autoHeight,
+            size = info.size,
+            ln = items.length,
+            padding = info.padding,
+            border = info.border,
+            frameSize = me.frameSize,
+            item, i, box, rect;
+
+        
+        
+        if (autoHeight) {
+            size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
+        }
+        else {
+            size.height = target.getHeight();
+        }
+        if (autoWidth) {
+            size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
+        }
+        else {
+            size.width = target.getWidth();
+        }
+
+        info.bodyBox = {
+            x: padding.left + frameSize.left,
+            y: padding.top + frameSize.top,
+            width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
+            height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
+        };
+
+        
+        for (i = 0; i < ln; i++) {
+            item = items[i];
+            
+            
+            
+            box = me.initBox(item);
+
+            if (autoHeight === true) {
+                box = me.adjustAutoBox(box, i);
+            }
+            else {
+                box = me.adjustSizedBox(box, i);
+            }
+
+            
+            
+            
+            info.boxes.push(box);
+        }
+        this.calculateDockBoxes_running = false;
+    },
+
+    
+    adjustSizedBox : function(box, index) {
+        var bodyBox = this.info.bodyBox,
+            frameSize = this.frameSize,
+            info = this.info,
+            padding = info.padding,
+            pos = box.type,
+            border = info.border;
+
+        switch (pos) {
+            case 'top':
+                box.y = bodyBox.y;
+                break;
+
+            case 'left':
+                box.x = bodyBox.x;
+                break;
+
+            case 'bottom':
+                box.y = (bodyBox.y + bodyBox.height) - box.height;
+                break;
+
+            case 'right':
+                box.x = (bodyBox.x + bodyBox.width) - box.width;
+                break;
+        }
+
+        if (box.ignoreFrame) {
+            if (pos == 'bottom') {
+                box.y += (frameSize.bottom + padding.bottom + border.bottom);
+            }
+            else {
+                box.y -= (frameSize.top + padding.top + border.top);
+            }
+            if (pos == 'right') {
+                box.x += (frameSize.right + padding.right + border.right);
+            }
+            else {
+                box.x -= (frameSize.left + padding.left + border.left);
+            }
+        }
+
+        
+        if (!box.overlay) {
+            switch (pos) {
+                case 'top':
+                    bodyBox.y += box.height;
+                    bodyBox.height -= box.height;
+                    break;
+
+                case 'left':
+                    bodyBox.x += box.width;
+                    bodyBox.width -= box.width;
+                    break;
+
+                case 'bottom':
+                    bodyBox.height -= box.height;
+                    break;
+
+                case 'right':
+                    bodyBox.width -= box.width;
+                    break;
+            }
+        }
+        return box;
+    },
+
+    
+    adjustAutoBox : function (box, index) {
+        var info = this.info,
+            owner = this.owner,
+            bodyBox = info.bodyBox,
+            size = info.size,
+            boxes = info.boxes,
+            boxesLn = boxes.length,
+            pos = box.type,
+            frameSize = this.frameSize,
+            padding = info.padding,
+            border = info.border,
+            autoSizedCtLayout = info.autoSizedCtLayout,
+            ln = (boxesLn < index) ? boxesLn : index,
+            i, adjustBox;
+
+        if (pos == 'top' || pos == 'bottom') {
+            
+            for (i = 0; i < ln; i++) {
+                adjustBox = boxes[i];
+                if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
+                    adjustBox.height += box.height;
+                }
+                else if (adjustBox.type == 'bottom') {
+                    adjustBox.y += box.height;
+                }
+            }
+        }
+
+        switch (pos) {
+            case 'top':
+                box.y = bodyBox.y;
+                if (!box.overlay) {
+                    bodyBox.y += box.height;
+                    if (info.autoHeight) {
+                        size.height += box.height;
+                    } else {
+                        bodyBox.height -= box.height;
+                    }
+                }
+                break;
+
+            case 'bottom':
+                if (!box.overlay) {
+                    if (info.autoHeight) {
+                        size.height += box.height;
+                    } else {
+                        bodyBox.height -= box.height;
+                    }
+                }
+                box.y = (bodyBox.y + bodyBox.height);
+                break;
+
+            case 'left':
+                box.x = bodyBox.x;
+                if (!box.overlay) {
+                    bodyBox.x += box.width;
+                    if (info.autoWidth) {
+                        size.width += box.width;
+                    } else {
+                        bodyBox.width -= box.width;
+                    }
+                }
+                break;
+
+            case 'right':
+                if (!box.overlay) {
+                    if (info.autoWidth) {
+                        size.width += box.width;
+                    } else {
+                        bodyBox.width -= box.width;
+                    }
+                }
+                box.x = (bodyBox.x + bodyBox.width);
+                break;
+        }
+
+        if (box.ignoreFrame) {
+            if (pos == 'bottom') {
+                box.y += (frameSize.bottom + padding.bottom + border.bottom);
+            }
+            else {
+                box.y -= (frameSize.top + padding.top + border.top);
+            }
+            if (pos == 'right') {
+                box.x += (frameSize.right + padding.right + border.right);
+            }
+            else {
+                box.x -= (frameSize.left + padding.left + border.left);
+            }
+        }
+        return box;
+    },
+
+    
+    initBox : function(item) {
+        var me = this,
+            bodyBox = me.info.bodyBox,
+            horizontal = (item.dock == 'top' || item.dock == 'bottom'),
+            owner = me.owner,
+            frameSize = me.frameSize,
+            info = me.info,
+            padding = info.padding,
+            border = info.border,
+            box = {
+                item: item,
+                overlay: item.overlay,
+                type: item.dock,
+                offsets: Ext.Element.parseBox(item.offsets || {}),
+                ignoreFrame: item.ignoreParentFrame
+            };
+        
+        if (item.stretch !== false) {
+            box.stretched = true;
+            if (horizontal) {
+                box.x = bodyBox.x + box.offsets.left;
+                box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
+                if (box.ignoreFrame) {
+                    box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
+                }
+                item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
+            }
+            else {
+                box.y = bodyBox.y + box.offsets.top;
+                box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
+                if (box.ignoreFrame) {
+                    box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
+                }
+                item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
+
+                
+                
+                if (!Ext.supports.ComputedStyle) {
+                    item.el.repaint();
+                }
+            }
+        }
+        else {
+            item.doComponentLayout();
+            box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
+            box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
+            box.y += box.offsets.top;
+            if (horizontal) {
+                box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
+                box.x += box.offsets.left;
+            }
+        }
+
+        
+        
+        if (box.width === undefined) {
+            box.width = item.getWidth() + item.el.getMargin('lr');
+        }
+        if (box.height === undefined) {
+            box.height = item.getHeight() + item.el.getMargin('tb');
+        }
+
+        return box;
+    },
+
+    
+    getLayoutItems : function() {
+        var it = this.owner.getDockedItems(),
+            ln = it.length,
+            i = 0,
+            result = [];
+        for (; i < ln; i++) {
+            if (it[i].isVisible(true)) {
+                result.push(it[i]);
+            }
+        }
+        return result;
+    },
+
+    
+    renderItems: function(items, target) {
+        var cns = target.dom.childNodes,
+            cnsLn = cns.length,
+            ln = items.length,
+            domLn = 0,
+            i, j, cn, item;
+
+        
+        for (i = 0; i < cnsLn; i++) {
+            cn = Ext.get(cns[i]);
+            for (j = 0; j < ln; j++) {
+                item = items[j];
+                if (item.rendered && (cn.id == item.el.id || cn.contains(item.el.id))) {
+                    break;
+                }
+            }
+
+            if (j === ln) {
+                domLn++;
+            }
+        }
+
+        
+        for (i = 0, j = 0; i < ln; i++, j++) {
+            item = items[i];
+
+            
+            
+            
+            
+            
+            
+            
+            
+            if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
+                j += domLn;
+            }
+
+            
+            if (item && !item.rendered) {
+                this.renderItem(item, target, j);
+            }
+            else if (!this.isValidParent(item, target, j)) {
+                this.moveItem(item, target, j);
+            }
+        }
+    },
+
+    
+    setBodyBox : function(box) {
+        var me = this,
+            owner = me.owner,
+            body = owner.body,
+            info = me.info,
+            bodyMargin = info.bodyMargin,
+            padding = info.padding,
+            border = info.border,
+            frameSize = me.frameSize;
+        
+        
+        if (owner.collapsed) {
+            return;
+        }
+        
+        if (Ext.isNumber(box.width)) {
+            box.width -= bodyMargin.left + bodyMargin.right;
+        }
+        
+        if (Ext.isNumber(box.height)) {
+            box.height -= bodyMargin.top + bodyMargin.bottom;
+        }
+        
+        me.setElementSize(body, box.width, box.height);
+        if (Ext.isNumber(box.x)) {
+            body.setLeft(box.x - padding.left - frameSize.left);
+        }
+        if (Ext.isNumber(box.y)) {
+            body.setTop(box.y - padding.top - frameSize.top);
+        }
+    },
+
+    
+    configureItem : function(item, pos) {
+        this.callParent(arguments);
+        if (item.dock == 'top' || item.dock == 'bottom') {
+            item.layoutManagedWidth = 1;
+            item.layoutManagedHeight = 2;
+        } else {
+            item.layoutManagedWidth = 2;
+            item.layoutManagedHeight = 1;
+        }
+        
+        item.addCls(Ext.baseCSSPrefix + 'docked');
+        item.addClsWithUI('docked-' + item.dock);
+    },
+
+    afterRemove : function(item) {
+        this.callParent(arguments);
+        if (this.itemCls) {
+            item.el.removeCls(this.itemCls + '-' + item.dock);
+        }
+        var dom = item.el.dom;
+
+        if (!item.destroying && dom) {
+            dom.parentNode.removeChild(dom);
+        }
+        this.childrenChanged = true;
+    }
+});
+
+Ext.define('Ext.util.Memento', function () {
+
+    function captureOne (src, target, prop) {
+        src[prop] = target[prop];
+    }
+
+    function removeOne (src, target, prop) {
+        delete src[prop];
+    }
+
+    function restoreOne (src, target, prop) {
+        var value = src[prop];
+        if (value || src.hasOwnProperty(prop)) {
+            restoreValue(target, prop, value);
+        }
+    }
+
+    function restoreValue (target, prop, value) {
+        if (Ext.isDefined(value)) {
+            target[prop] = value;
+        } else {
+            delete target[prop];
+        }
+    }
+
+    function doMany (doOne, src, target, props) {
+        if (src) {
+            if (Ext.isArray(props)) {
+                Ext.each(props, function (prop) {
+                    doOne(src, target, prop);
+                });
+            } else {
+                doOne(src, target, props);
+            }
+        }
+    }
+
+    return {
+        
+        data: null,
+
+        
+        target: null,
+
+        
+        constructor: function (target, props) {
+            if (target) {
+                this.target = target;
+                if (props) {
+                    this.capture(props);
+                }
+            }
+        },
+
+        
+        capture: function (props, target) {
+            doMany(captureOne, this.data || (this.data = {}), target || this.target, props);
+        },
+
+        
+        remove: function (props) {
+            doMany(removeOne, this.data, null, props);
+        },
+
+        
+        restore: function (props, clear, target) {
+            doMany(restoreOne, this.data, target || this.target, props);
+            if (clear !== false) {
+                this.remove(props);
+            }
+        },
+
+        
+        restoreAll: function (clear, target) {
+            var me = this,
+                t = target || this.target;
+
+            Ext.Object.each(me.data, function (prop, value) {
+                restoreValue(t, prop, value);
+            });
+
+            if (clear !== false) {
+                delete me.data;
+            }
+        }
+    };
+}());
+
+
+Ext.define('Ext.app.EventBus', {
+    requires: [
+        'Ext.util.Event'
+    ],
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    constructor: function() {
+        this.mixins.observable.constructor.call(this);
+
+        this.bus = {};
+
+        var me = this;
+        Ext.override(Ext.Component, {
+            fireEvent: function(ev) {
+                if (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false) {
+                    return me.dispatch.call(me, ev, this, arguments);
+                }
+                return false;
+            }
+        });
+    },
+
+    dispatch: function(ev, target, args) {
+        var bus = this.bus,
+            selectors = bus[ev],
+            selector, controllers, id, events, event, i, ln;
+
+        if (selectors) {
+            
+            for (selector in selectors) {
+                
+                if (target.is(selector)) {
+                    
+                    controllers = selectors[selector];
+                    for (id in controllers) {
+                        
+                        events = controllers[id];
+                        for (i = 0, ln = events.length; i < ln; i++) {
+                            event = events[i];
+                            
+                            if (event.fire.apply(event, Array.prototype.slice.call(args, 1)) === false) {
+                                return false;
+                            };
+                        }
+                    }
+                }
+            }
+        }
+    },
+
+    control: function(selectors, listeners, controller) {
+        var bus = this.bus,
+            selector, fn;
+
+        if (Ext.isString(selectors)) {
+            selector = selectors;
+            selectors = {};
+            selectors[selector] = listeners;
+            this.control(selectors, null, controller);
+            return;
+        }
+
+        Ext.Object.each(selectors, function(selector, listeners) {
+            Ext.Object.each(listeners, function(ev, listener) {
+                var options = {},
+                    scope = controller,
+                    event = Ext.create('Ext.util.Event', controller, ev);
+
+                
+                if (Ext.isObject(listener)) {
+                    options = listener;
+                    listener = options.fn;
+                    scope = options.scope || controller;
+                    delete options.fn;
+                    delete options.scope;
+                }
+
+                event.addListener(listener, scope, options);
+
+                
+                bus[ev] = bus[ev] || {};
+                bus[ev][selector] = bus[ev][selector] || {};
+                bus[ev][selector][controller.id] = bus[ev][selector][controller.id] || [];
+
+                
+                bus[ev][selector][controller.id].push(event);
+            });
+        });
+    }
+});
+
+Ext.define('Ext.data.Types', {
+    singleton: true,
+    requires: ['Ext.data.SortTypes']
+}, function() {
+    var st = Ext.data.SortTypes;
+
+    Ext.apply(Ext.data.Types, {
+        
+        stripRe: /[\$,%]/g,
+
+        
+        AUTO: {
+            convert: function(v) {
+                return v;
+            },
+            sortType: st.none,
+            type: 'auto'
+        },
+
+        
+        STRING: {
+            convert: function(v) {
+                var defaultValue = this.useNull ? null : '';
+                return (v === undefined || v === null) ? defaultValue : String(v);
+            },
+            sortType: st.asUCString,
+            type: 'string'
+        },
+
+        
+        INT: {
+            convert: function(v) {
+                return v !== undefined && v !== null && v !== '' ?
+                    parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
+            },
+            sortType: st.none,
+            type: 'int'
+        },
+
+        
+        FLOAT: {
+            convert: function(v) {
+                return v !== undefined && v !== null && v !== '' ?
+                    parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
+            },
+            sortType: st.none,
+            type: 'float'
+        },
+
+        
+        BOOL: {
+            convert: function(v) {
+                if (this.useNull && (v === undefined || v === null || v === '')) {
+                    return null;
+                }
+                return v === true || v === 'true' || v == 1;
+            },
+            sortType: st.none,
+            type: 'bool'
+        },
+
+        
+        DATE: {
+            convert: function(v) {
+                var df = this.dateFormat,
+                    parsed;
+
+                if (!v) {
+                    return null;
+                }
+                if (Ext.isDate(v)) {
+                    return v;
+                }
+                if (df) {
+                    if (df == 'timestamp') {
+                        return new Date(v*1000);
+                    }
+                    if (df == 'time') {
+                        return new Date(parseInt(v, 10));
+                    }
+                    return Ext.Date.parse(v, df);
+                }
+
+                parsed = Date.parse(v);
+                return parsed ? new Date(parsed) : null;
+            },
+            sortType: st.asDate,
+            type: 'date'
+        }
+    });
+
+    Ext.apply(Ext.data.Types, {
+        
+        BOOLEAN: this.BOOL,
+
+        
+        INTEGER: this.INT,
+
+        
+        NUMBER: this.FLOAT
+    });
+});
+
+
+Ext.define('Ext.data.Field', {
+    requires: ['Ext.data.Types', 'Ext.data.SortTypes'],
+    alias: 'data.field',
+    
+    constructor : function(config) {
+        if (Ext.isString(config)) {
+            config = {name: config};
+        }
+        Ext.apply(this, config);
+        
+        var types = Ext.data.Types,
+            st = this.sortType,
+            t;
+
+        if (this.type) {
+            if (Ext.isString(this.type)) {
+                this.type = types[this.type.toUpperCase()] || types.AUTO;
+            }
+        } else {
+            this.type = types.AUTO;
+        }
+
+        
+        if (Ext.isString(st)) {
+            this.sortType = Ext.data.SortTypes[st];
+        } else if(Ext.isEmpty(st)) {
+            this.sortType = this.type.sortType;
+        }
+
+        if (!this.convert) {
+            this.convert = this.type.convert;
+        }
+    },
+    
+    
+    
+    
+    
+    
+
+    
+    dateFormat: null,
+    
+    
+    useNull: false,
+    
+    
+    defaultValue: "",
+
+    
+    mapping: null,
+
+    
+    sortType : null,
+
+    
+    sortDir : "ASC",
+
+    
+    allowBlank : true,
+
+    
+    persist: true
+});
+
+
+Ext.define('Ext.util.AbstractMixedCollection', {
+    requires: ['Ext.util.Filter'],
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    constructor: function(allowFunctions, keyFn) {
+        var me = this;
+
+        me.items = [];
+        me.map = {};
+        me.keys = [];
+        me.length = 0;
+
+        me.addEvents(
+            
+            'clear',
+
+            
+            'add',
+
+            
+            'replace',
+
+            
+            'remove'
+        );
+
+        me.allowFunctions = allowFunctions === true;
+
+        if (keyFn) {
+            me.getKey = keyFn;
+        }
+
+        me.mixins.observable.constructor.call(me);
+    },
+
+    
+    allowFunctions : false,
+
+    
+    add : function(key, obj){
+        var me = this,
+            myObj = obj,
+            myKey = key,
+            old;
+
+        if (arguments.length == 1) {
+            myObj = myKey;
+            myKey = me.getKey(myObj);
+        }
+        if (typeof myKey != 'undefined' && myKey !== null) {
+            old = me.map[myKey];
+            if (typeof old != 'undefined') {
+                return me.replace(myKey, myObj);
+            }
+            me.map[myKey] = myObj;
+        }
+        me.length++;
+        me.items.push(myObj);
+        me.keys.push(myKey);
+        me.fireEvent('add', me.length - 1, myObj, myKey);
+        return myObj;
+    },
+
+    
+    getKey : function(o){
+         return o.id;
+    },
+
+    
+    replace : function(key, o){
+        var me = this,
+            old,
+            index;
+
+        if (arguments.length == 1) {
+            o = arguments[0];
+            key = me.getKey(o);
+        }
+        old = me.map[key];
+        if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
+             return me.add(key, o);
+        }
+        index = me.indexOfKey(key);
+        me.items[index] = o;
+        me.map[key] = o;
+        me.fireEvent('replace', key, old, o);
+        return o;
+    },
+
+    
+    addAll : function(objs){
+        var me = this,
+            i = 0,
+            args,
+            len,
+            key;
+
+        if (arguments.length > 1 || Ext.isArray(objs)) {
+            args = arguments.length > 1 ? arguments : objs;
+            for (len = args.length; i < len; i++) {
+                me.add(args[i]);
+            }
+        } else {
+            for (key in objs) {
+                if (objs.hasOwnProperty(key)) {
+                    if (me.allowFunctions || typeof objs[key] != 'function') {
+                        me.add(key, objs[key]);
+                    }
+                }
+            }
+        }
+    },
+
+    
+    each : function(fn, scope){
+        var items = [].concat(this.items), 
+            i = 0,
+            len = items.length,
+            item;
+
+        for (; i < len; i++) {
+            item = items[i];
+            if (fn.call(scope || item, item, i, len) === false) {
+                break;
+            }
+        }
+    },
+
+    
+    eachKey : function(fn, scope){
+        var keys = this.keys,
+            items = this.items,
+            i = 0,
+            len = keys.length;
+
+        for (; i < len; i++) {
+            fn.call(scope || window, keys[i], items[i], i, len);
+        }
+    },
+
+    
+    findBy : function(fn, scope) {
+        var keys = this.keys,
+            items = this.items,
+            i = 0,
+            len = items.length;
+
+        for (; i < len; i++) {
+            if (fn.call(scope || window, items[i], keys[i])) {
+                return items[i];
+            }
+        }
+        return null;
+    },
+
+    find : function() {
+        if (Ext.isDefined(Ext.global.console)) {
+            Ext.global.console.warn('Ext.util.MixedCollection: find has been deprecated. Use findBy instead.');
+        }
+        return this.findBy.apply(this, arguments);
+    },
+
+    
+    insert : function(index, key, obj){
+        var me = this,
+            myKey = key,
+            myObj = obj;
+
+        if (arguments.length == 2) {
+            myObj = myKey;
+            myKey = me.getKey(myObj);
+        }
+        if (me.containsKey(myKey)) {
+            me.suspendEvents();
+            me.removeAtKey(myKey);
+            me.resumeEvents();
+        }
+        if (index >= me.length) {
+            return me.add(myKey, myObj);
+        }
+        me.length++;
+        Ext.Array.splice(me.items, index, 0, myObj);
+        if (typeof myKey != 'undefined' && myKey !== null) {
+            me.map[myKey] = myObj;
+        }
+        Ext.Array.splice(me.keys, index, 0, myKey);
+        me.fireEvent('add', index, myObj, myKey);
+        return myObj;
+    },
+
+    
+    remove : function(o){
+        return this.removeAt(this.indexOf(o));
+    },
+
+    
+    removeAll : function(items){
+        Ext.each(items || [], function(item) {
+            this.remove(item);
+        }, this);
+
+        return this;
+    },
+
+    
+    removeAt : function(index){
+        var me = this,
+            o,
+            key;
+
+        if (index < me.length && index >= 0) {
+            me.length--;
+            o = me.items[index];
+            Ext.Array.erase(me.items, index, 1);
+            key = me.keys[index];
+            if (typeof key != 'undefined') {
+                delete me.map[key];
+            }
+            Ext.Array.erase(me.keys, index, 1);
+            me.fireEvent('remove', o, key);
+            return o;
+        }
+        return false;
+    },
+
+    
+    removeAtKey : function(key){
+        return this.removeAt(this.indexOfKey(key));
+    },
+
+    
+    getCount : function(){
+        return this.length;
+    },
+
+    
+    indexOf : function(o){
+        return Ext.Array.indexOf(this.items, o);
+    },
+
+    
+    indexOfKey : function(key){
+        return Ext.Array.indexOf(this.keys, key);
+    },
+
+    
+    get : function(key) {
+        var me = this,
+            mk = me.map[key],
+            item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined;
+        return typeof item != 'function' || me.allowFunctions ? item : null; 
+    },
+
+    
+    getAt : function(index) {
+        return this.items[index];
+    },
+
+    
+    getByKey : function(key) {
+        return this.map[key];
+    },
+
+    
+    contains : function(o){
+        return Ext.Array.contains(this.items, o);
+    },
+
+    
+    containsKey : function(key){
+        return typeof this.map[key] != 'undefined';
+    },
+
+    
+    clear : function(){
+        var me = this;
+
+        me.length = 0;
+        me.items = [];
+        me.keys = [];
+        me.map = {};
+        me.fireEvent('clear');
+    },
+
+    
+    first : function() {
+        return this.items[0];
+    },
+
+    
+    last : function() {
+        return this.items[this.length - 1];
+    },
+
+    
+    sum: function(property, root, start, end) {
+        var values = this.extractValues(property, root),
+            length = values.length,
+            sum    = 0,
+            i;
+
+        start = start || 0;
+        end   = (end || end === 0) ? end : length - 1;
+
+        for (i = start; i <= end; i++) {
+            sum += values[i];
+        }
+
+        return sum;
+    },
+
+    
+    collect: function(property, root, allowNull) {
+        var values = this.extractValues(property, root),
+            length = values.length,
+            hits   = {},
+            unique = [],
+            value, strValue, i;
+
+        for (i = 0; i < length; i++) {
+            value = values[i];
+            strValue = String(value);
+
+            if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
+                hits[strValue] = true;
+                unique.push(value);
+            }
+        }
+
+        return unique;
+    },
+
+    
+    extractValues: function(property, root) {
+        var values = this.items;
+
+        if (root) {
+            values = Ext.Array.pluck(values, root);
+        }
+
+        return Ext.Array.pluck(values, property);
+    },
+
+    
+    getRange : function(start, end){
+        var me = this,
+            items = me.items,
+            range = [],
+            i;
+
+        if (items.length < 1) {
+            return range;
+        }
+
+        start = start || 0;
+        end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
+        if (start <= end) {
+            for (i = start; i <= end; i++) {
+                range[range.length] = items[i];
+            }
+        } else {
+            for (i = start; i >= end; i--) {
+                range[range.length] = items[i];
+            }
+        }
+        return range;
+    },
+
+    
+    filter : function(property, value, anyMatch, caseSensitive) {
+        var filters = [],
+            filterFn;
+
+        
+        if (Ext.isString(property)) {
+            filters.push(Ext.create('Ext.util.Filter', {
+                property     : property,
+                value        : value,
+                anyMatch     : anyMatch,
+                caseSensitive: caseSensitive
+            }));
+        } else if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
+            filters = filters.concat(property);
+        }
+
+        
+        
+        filterFn = function(record) {
+            var isMatch = true,
+                length = filters.length,
+                i;
+
+            for (i = 0; i < length; i++) {
+                var filter = filters[i],
+                    fn     = filter.filterFn,
+                    scope  = filter.scope;
+
+                isMatch = isMatch && fn.call(scope, record);
+            }
+
+            return isMatch;
+        };
+
+        return this.filterBy(filterFn);
+    },
+
+    
+    filterBy : function(fn, scope) {
+        var me = this,
+            newMC  = new this.self(),
+            keys   = me.keys,
+            items  = me.items,
+            length = items.length,
+            i;
+
+        newMC.getKey = me.getKey;
+
+        for (i = 0; i < length; i++) {
+            if (fn.call(scope || me, items[i], keys[i])) {
+                newMC.add(keys[i], items[i]);
+            }
+        }
+
+        return newMC;
+    },
+
+    
+    findIndex : function(property, value, start, anyMatch, caseSensitive){
+        if(Ext.isEmpty(value, false)){
+            return -1;
+        }
+        value = this.createValueMatcher(value, anyMatch, caseSensitive);
+        return this.findIndexBy(function(o){
+            return o && value.test(o[property]);
+        }, null, start);
+    },
+
+    
+    findIndexBy : function(fn, scope, start){
+        var me = this,
+            keys = me.keys,
+            items = me.items,
+            i = start || 0,
+            len = items.length;
+
+        for (; i < len; i++) {
+            if (fn.call(scope || me, items[i], keys[i])) {
+                return i;
+            }
+        }
+        return -1;
+    },
+
+    
+    createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
+        if (!value.exec) { 
+            var er = Ext.String.escapeRegex;
+            value = String(value);
+
+            if (anyMatch === true) {
+                value = er(value);
+            } else {
+                value = '^' + er(value);
+                if (exactMatch === true) {
+                    value += '$';
+                }
+            }
+            value = new RegExp(value, caseSensitive ? '' : 'i');
+        }
+        return value;
+    },
+
+    
+    clone : function() {
+        var me = this,
+            copy = new this.self(),
+            keys = me.keys,
+            items = me.items,
+            i = 0,
+            len = items.length;
+
+        for(; i < len; i++){
+            copy.add(keys[i], items[i]);
+        }
+        copy.getKey = me.getKey;
+        return copy;
+    }
+});
+
+
+Ext.define("Ext.util.Sortable", {
+    
+    isSortable: true,
+
+    
+    defaultSortDirection: "ASC",
+
+    requires: [
+        'Ext.util.Sorter'
+    ],
+
+    
+
+    
+    initSortable: function() {
+        var me = this,
+            sorters = me.sorters;
+
+        
+        me.sorters = Ext.create('Ext.util.AbstractMixedCollection', false, function(item) {
+            return item.id || item.property;
+        });
+
+        if (sorters) {
+            me.sorters.addAll(me.decodeSorters(sorters));
+        }
+    },
+
+    
+    sort: function(sorters, direction, where, doSort) {
+        var me = this,
+            sorter, sorterFn,
+            newSorters;
+
+        if (Ext.isArray(sorters)) {
+            doSort = where;
+            where = direction;
+            newSorters = sorters;
+        }
+        else if (Ext.isObject(sorters)) {
+            doSort = where;
+            where = direction;
+            newSorters = [sorters];
+        }
+        else if (Ext.isString(sorters)) {
+            sorter = me.sorters.get(sorters);
+
+            if (!sorter) {
+                sorter = {
+                    property : sorters,
+                    direction: direction
+                };
+                newSorters = [sorter];
+            }
+            else if (direction === undefined) {
+                sorter.toggle();
+            }
+            else {
+                sorter.setDirection(direction);
+            }
+        }
+
+        if (newSorters && newSorters.length) {
+            newSorters = me.decodeSorters(newSorters);
+            if (Ext.isString(where)) {
+                if (where === 'prepend') {
+                    sorters = me.sorters.clone().items;
+
+                    me.sorters.clear();
+                    me.sorters.addAll(newSorters);
+                    me.sorters.addAll(sorters);
+                }
+                else {
+                    me.sorters.addAll(newSorters);
+                }
+            }
+            else {
+                me.sorters.clear();
+                me.sorters.addAll(newSorters);
+            }
+        }
+
+        if (doSort !== false) {
+            me.onBeforeSort(newSorters);
+            
+            sorters = me.sorters.items;
+            if (sorters.length) {
+                
+                sorterFn = function(r1, r2) {
+                    var result = sorters[0].sort(r1, r2),
+                        length = sorters.length,
+                        i;
+
+                        
+                        for (i = 1; i < length; i++) {
+                            result = result || sorters[i].sort.call(this, r1, r2);
+                        }
+
+                    return result;
+                };
+
+                me.doSort(sorterFn);
+            }
+        }
+
+        return sorters;
+    },
+
+    onBeforeSort: Ext.emptyFn,
+
+    
+    decodeSorters: function(sorters) {
+        if (!Ext.isArray(sorters)) {
+            if (sorters === undefined) {
+                sorters = [];
+            } else {
+                sorters = [sorters];
+            }
+        }
+
+        var length = sorters.length,
+            Sorter = Ext.util.Sorter,
+            fields = this.model ? this.model.prototype.fields : null,
+            field,
+            config, i;
+
+        for (i = 0; i < length; i++) {
+            config = sorters[i];
+
+            if (!(config instanceof Sorter)) {
+                if (Ext.isString(config)) {
+                    config = {
+                        property: config
+                    };
+                }
+
+                Ext.applyIf(config, {
+                    root     : this.sortRoot,
+                    direction: "ASC"
+                });
+
+                
+                if (config.fn) {
+                    config.sorterFn = config.fn;
+                }
+
+                
+                if (typeof config == 'function') {
+                    config = {
+                        sorterFn: config
+                    };
+                }
+
+                
+                if (fields && !config.transform) {
+                    field = fields.get(config.property);
+                    config.transform = field ? field.sortType : undefined;
+                }
+                sorters[i] = Ext.create('Ext.util.Sorter', config);
+            }
+        }
+
+        return sorters;
+    },
+
+    getSorters: function() {
+        return this.sorters.items;
+    }
+});
+
+Ext.define('Ext.util.MixedCollection', {
+    extend: 'Ext.util.AbstractMixedCollection',
+    mixins: {
+        sortable: 'Ext.util.Sortable'
+    },
+
+    
+    constructor: function() {
+        var me = this;
+        me.callParent(arguments);
+        me.addEvents('sort');
+        me.mixins.sortable.initSortable.call(me);
+    },
+
+    doSort: function(sorterFn) {
+        this.sortBy(sorterFn);
+    },
+
+    
+    _sort : function(property, dir, fn){
+        var me = this,
+            i, len,
+            dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
+
+            
+            c     = [],
+            keys  = me.keys,
+            items = me.items;
+
+        
+        fn = fn || function(a, b) {
+            return a - b;
+        };
+
+        
+        for(i = 0, len = items.length; i < len; i++){
+            c[c.length] = {
+                key  : keys[i],
+                value: items[i],
+                index: i
+            };
+        }
+
+        
+        Ext.Array.sort(c, function(a, b){
+            var v = fn(a[property], b[property]) * dsc;
+            if(v === 0){
+                v = (a.index < b.index ? -1 : 1);
+            }
+            return v;
+        });
+
+        
+        for(i = 0, len = c.length; i < len; i++){
+            items[i] = c[i].value;
+            keys[i]  = c[i].key;
+        }
+
+        me.fireEvent('sort', me);
+    },
+
+    
+    sortBy: function(sorterFn) {
+        var me     = this,
+            items  = me.items,
+            keys   = me.keys,
+            length = items.length,
+            temp   = [],
+            i;
+
+        
+        for (i = 0; i < length; i++) {
+            temp[i] = {
+                key  : keys[i],
+                value: items[i],
+                index: i
+            };
+        }
+
+        Ext.Array.sort(temp, function(a, b) {
+            var v = sorterFn(a.value, b.value);
+            if (v === 0) {
+                v = (a.index < b.index ? -1 : 1);
+            }
+
+            return v;
+        });
+
+        
+        for (i = 0; i < length; i++) {
+            items[i] = temp[i].value;
+            keys[i]  = temp[i].key;
+        }
+        
+        me.fireEvent('sort', me, items, keys);
+    },
+
+    
+    reorder: function(mapping) {
+        var me = this,
+            items = me.items,
+            index = 0,
+            length = items.length,
+            order = [],
+            remaining = [],
+            oldIndex;
+
+        me.suspendEvents();
+
+        
+        for (oldIndex in mapping) {
+            order[mapping[oldIndex]] = items[oldIndex];
+        }
+
+        for (index = 0; index < length; index++) {
+            if (mapping[index] == undefined) {
+                remaining.push(items[index]);
+            }
+        }
+
+        for (index = 0; index < length; index++) {
+            if (order[index] == undefined) {
+                order[index] = remaining.shift();
+            }
+        }
+
+        me.clear();
+        me.addAll(order);
+
+        me.resumeEvents();
+        me.fireEvent('sort', me);
+    },
+
+    
+    sortByKey : function(dir, fn){
+        this._sort('key', dir, fn || function(a, b){
+            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
+            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
+        });
+    }
+});
+
+
+Ext.define('Ext.data.Errors', {
+    extend: 'Ext.util.MixedCollection',
+
+    
+    isValid: function() {
+        return this.length === 0;
+    },
+
+    
+    getByField: function(fieldName) {
+        var errors = [],
+            error, field, i;
+
+        for (i = 0; i < this.length; i++) {
+            error = this.items[i];
+
+            if (error.field == fieldName) {
+                errors.push(error);
+            }
+        }
+
+        return errors;
+    }
+});
+
+
+Ext.define('Ext.data.reader.Reader', {
+    requires: ['Ext.data.ResultSet'],
+    alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
+    
+    
+
+    
+    totalProperty: 'total',
+
+    
+    successProperty: 'success',
+
+    
+    root: '',
+    
+    
+    
+    
+    implicitIncludes: true,
+    
+    isReader: true,
+    
+    
+    constructor: function(config) {
+        var me = this;
+        
+        Ext.apply(me, config || {});
+        me.fieldCount = 0;
+        me.model = Ext.ModelManager.getModel(config.model);
+        if (me.model) {
+            me.buildExtractors();
+        }
+    },
+
+    
+    setModel: function(model, setOnProxy) {
+        var me = this;
+        
+        me.model = Ext.ModelManager.getModel(model);
+        me.buildExtractors(true);
+        
+        if (setOnProxy && me.proxy) {
+            me.proxy.setModel(me.model, true);
+        }
+    },
+
+    
+    read: function(response) {
+        var data = response;
+        
+        if (response && response.responseText) {
+            data = this.getResponseData(response);
+        }
+        
+        if (data) {
+            return this.readRecords(data);
+        } else {
+            return this.nullResultSet;
+        }
+    },
+
+    
+    readRecords: function(data) {
+        var me  = this;
+        
+        
+        if (me.fieldCount !== me.getFields().length) {
+            me.buildExtractors(true);
+        }
+        
+        
+        me.rawData = data;
+
+        data = me.getData(data);
+
+        
+        
+        var root    = Ext.isArray(data) ? data : me.getRoot(data),
+            success = true,
+            recordCount = 0,
+            total, value, records, message;
+            
+        if (root) {
+            total = root.length;
+        }
+
+        if (me.totalProperty) {
+            value = parseInt(me.getTotal(data), 10);
+            if (!isNaN(value)) {
+                total = value;
+            }
+        }
+
+        if (me.successProperty) {
+            value = me.getSuccess(data);
+            if (value === false || value === 'false') {
+                success = false;
+            }
+        }
+        
+        if (me.messageProperty) {
+            message = me.getMessage(data);
+        }
+        
+        if (root) {
+            records = me.extractData(root);
+            recordCount = records.length;
+        } else {
+            recordCount = 0;
+            records = [];
+        }
+
+        return Ext.create('Ext.data.ResultSet', {
+            total  : total || recordCount,
+            count  : recordCount,
+            records: records,
+            success: success,
+            message: message
+        });
+    },
+
+    
+    extractData : function(root) {
+        var me = this,
+            values  = [],
+            records = [],
+            Model   = me.model,
+            i       = 0,
+            length  = root.length,
+            idProp  = me.getIdProperty(),
+            node, id, record;
+            
+        if (!root.length && Ext.isObject(root)) {
+            root = [root];
+            length = 1;
+        }
+
+        for (; i < length; i++) {
+            node   = root[i];
+            values = me.extractValues(node);
+            id     = me.getId(node);
+
+            
+            record = new Model(values, id, node);
+            records.push(record);
+                
+            if (me.implicitIncludes) {
+                me.readAssociated(record, node);
+            }
+        }
+
+        return records;
+    },
+    
+    
+    readAssociated: function(record, data) {
+        var associations = record.associations.items,
+            i            = 0,
+            length       = associations.length,
+            association, associationData, proxy, reader;
+        
+        for (; i < length; i++) {
+            association     = associations[i];
+            associationData = this.getAssociatedDataRoot(data, association.associationKey || association.name);
+            
+            if (associationData) {
+                reader = association.getReader();
+                if (!reader) {
+                    proxy = association.associatedModel.proxy;
+                    
+                    if (proxy) {
+                        reader = proxy.getReader();
+                    } else {
+                        reader = new this.constructor({
+                            model: association.associatedName
+                        });
+                    }
+                }
+                association.read(record, reader, associationData);
+            }  
+        }
+    },
+    
+    
+    getAssociatedDataRoot: function(data, associationName) {
+        return data[associationName];
+    },
+    
+    getFields: function() {
+        return this.model.prototype.fields.items;
+    },
+
+    
+    extractValues: function(data) {
+        var fields = this.getFields(),
+            i      = 0,
+            length = fields.length,
+            output = {},
+            field, value;
+
+        for (; i < length; i++) {
+            field = fields[i];
+            value = this.extractorFunctions[i](data);
+
+            output[field.name] = value;
+        }
+
+        return output;
+    },
+
+    
+    getData: function(data) {
+        return data;
+    },
+
+    
+    getRoot: function(data) {
+        return data;
+    },
+
+    
+    getResponseData: function(response) {
+    },
+
+    
+    onMetaChange : function(meta) {
+        var fields = meta.fields,
+            newModel;
+        
+        Ext.apply(this, meta);
+        
+        if (fields) {
+            newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
+                extend: 'Ext.data.Model',
+                fields: fields
+            });
+            this.setModel(newModel, true);
+        } else {
+            this.buildExtractors(true);
+        }
+    },
+    
+    
+    getIdProperty: function(){
+        var prop = this.idProperty;
+        if (Ext.isEmpty(prop)) {
+            prop = this.model.prototype.idProperty;
+        }
+        return prop;
+    },
+
+    
+    buildExtractors: function(force) {
+        var me          = this,
+            idProp      = me.getIdProperty(),
+            totalProp   = me.totalProperty,
+            successProp = me.successProperty,
+            messageProp = me.messageProperty,
+            accessor;
+            
+        if (force === true) {
+            delete me.extractorFunctions;
+        }
+        
+        if (me.extractorFunctions) {
+            return;
+        }   
+
+        
+        if (totalProp) {
+            me.getTotal = me.createAccessor(totalProp);
+        }
+
+        if (successProp) {
+            me.getSuccess = me.createAccessor(successProp);
+        }
+
+        if (messageProp) {
+            me.getMessage = me.createAccessor(messageProp);
+        }
+
+        if (idProp) {
+            accessor = me.createAccessor(idProp);
+
+            me.getId = function(record) {
+                var id = accessor.call(me, record);
+                return (id === undefined || id === '') ? null : id;
+            };
+        } else {
+            me.getId = function() {
+                return null;
+            };
+        }
+        me.buildFieldExtractors();
+    },
+
+    
+    buildFieldExtractors: function() {
+        
+        var me = this,
+            fields = me.getFields(),
+            ln = fields.length,
+            i  = 0,
+            extractorFunctions = [],
+            field, map;
+
+        for (; i < ln; i++) {
+            field = fields[i];
+            map   = (field.mapping !== undefined && field.mapping !== null) ? field.mapping : field.name;
+
+            extractorFunctions.push(me.createAccessor(map));
+        }
+        me.fieldCount = ln;
+
+        me.extractorFunctions = extractorFunctions;
+    }
+}, function() {
+    Ext.apply(this, {
+        
+        nullResultSet: Ext.create('Ext.data.ResultSet', {
+            total  : 0,
+            count  : 0,
+            records: [],
+            success: true
+        })
+    });
+});
+
+Ext.define('Ext.data.reader.Json', {
+    extend: 'Ext.data.reader.Reader',
+    alternateClassName: 'Ext.data.JsonReader',
+    alias : 'reader.json',
+
+    root: '',
+
+    
+
+    
+    useSimpleAccessors: false,
+
+    
+    readRecords: function(data) {
+        
+        if (data.metaData) {
+            this.onMetaChange(data.metaData);
+        }
+
+        
+        this.jsonData = data;
+        return this.callParent([data]);
+    },
+
+    
+    getResponseData: function(response) {
+        var data;
+        try {
+            data = Ext.decode(response.responseText);
+        }
+        catch (ex) {
+            Ext.Error.raise({
+                response: response,
+                json: response.responseText,
+                parseError: ex,
+                msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
+            });
+        }
+
+        return data;
+    },
+
+    
+    buildExtractors : function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        if (me.root) {
+            me.getRoot = me.createAccessor(me.root);
+        } else {
+            me.getRoot = function(root) {
+                return root;
+            };
+        }
+    },
+
+    
+    extractData: function(root) {
+        var recordName = this.record,
+            data = [],
+            length, i;
+
+        if (recordName) {
+            length = root.length;
+            
+            if (!length && Ext.isObject(root)) {
+                length = 1;
+                root = [root];
+            }
+
+            for (i = 0; i < length; i++) {
+                data[i] = root[i][recordName];
+            }
+        } else {
+            data = root;
+        }
+        return this.callParent([data]);
+    },
+
+    
+    createAccessor: function() {
+        var re = /[\[\.]/;
+
+        return function(expr) {
+            if (Ext.isEmpty(expr)) {
+                return Ext.emptyFn;
+            }
+            if (Ext.isFunction(expr)) {
+                return expr;
+            }
+            if (this.useSimpleAccessors !== true) {
+                var i = String(expr).search(re);
+                if (i >= 0) {
+                    return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
+                }
+            }
+            return function(obj) {
+                return obj[expr];
+            };
+        };
+    }()
+});
+
+Ext.define('Ext.data.writer.Json', {
+    extend: 'Ext.data.writer.Writer',
+    alternateClassName: 'Ext.data.JsonWriter',
+    alias: 'writer.json',
+    
+    
+    root: undefined,
+    
+    
+    encode: false,
+    
+    
+    allowSingle: true,
+    
+    
+    writeRecords: function(request, data) {
+        var root = this.root;
+        
+        if (this.allowSingle && data.length == 1) {
+            
+            data = data[0];
+        }
+        
+        if (this.encode) {
+            if (root) {
+                
+                request.params[root] = Ext.encode(data);
+            } else {
+            }
+        } else {
+            
+            request.jsonData = request.jsonData || {};
+            if (root) {
+                request.jsonData[root] = data;
+            } else {
+                request.jsonData = data;
+            }
+        }
+        return request;
+    }
+});
+
+
+Ext.define('Ext.data.proxy.Proxy', {
+    alias: 'proxy.proxy',
+    alternateClassName: ['Ext.data.DataProxy', 'Ext.data.Proxy'],
+    requires: [
+        'Ext.data.reader.Json',
+        'Ext.data.writer.Json'
+    ],
+    uses: [
+        'Ext.data.Batch', 
+        'Ext.data.Operation', 
+        'Ext.data.Model'
+    ],
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+    
+    
+    batchOrder: 'create,update,destroy',
+    
+    
+    batchActions: true,
+    
+    
+    defaultReaderType: 'json',
+    
+    
+    defaultWriterType: 'json',
+    
+    
+    
+    
+    
+    
+    
+    isProxy: true,
+    
+    
+    constructor: function(config) {
+        config = config || {};
+        
+        if (config.model === undefined) {
+            delete config.model;
+        }
+
+        this.mixins.observable.constructor.call(this, config);
+        
+        if (this.model !== undefined && !(this.model instanceof Ext.data.Model)) {
+            this.setModel(this.model);
+        }
+    },
+    
+    
+    setModel: function(model, setOnStore) {
+        this.model = Ext.ModelManager.getModel(model);
+        
+        var reader = this.reader,
+            writer = this.writer;
+        
+        this.setReader(reader);
+        this.setWriter(writer);
+        
+        if (setOnStore && this.store) {
+            this.store.setModel(this.model);
+        }
+    },
+    
+    
+    getModel: function() {
+        return this.model;
+    },
+    
+    
+    setReader: function(reader) {
+        var me = this;
+        
+        if (reader === undefined || typeof reader == 'string') {
+            reader = {
+                type: reader
+            };
+        }
+
+        if (reader.isReader) {
+            reader.setModel(me.model);
+        } else {
+            Ext.applyIf(reader, {
+                proxy: me,
+                model: me.model,
+                type : me.defaultReaderType
+            });
+
+            reader = Ext.createByAlias('reader.' + reader.type, reader);
+        }
+        
+        me.reader = reader;
+        return me.reader;
+    },
+    
+    
+    getReader: function() {
+        return this.reader;
+    },
+    
+    
+    setWriter: function(writer) {
+        if (writer === undefined || typeof writer == 'string') {
+            writer = {
+                type: writer
+            };
+        }
+
+        if (!(writer instanceof Ext.data.writer.Writer)) {
+            Ext.applyIf(writer, {
+                model: this.model,
+                type : this.defaultWriterType
+            });
+
+            writer = Ext.createByAlias('writer.' + writer.type, writer);
+        }
+        
+        this.writer = writer;
+        
+        return this.writer;
+    },
+    
+    
+    getWriter: function() {
+        return this.writer;
+    },
+    
+    
+    create: Ext.emptyFn,
+    
+    
+    read: Ext.emptyFn,
+    
+    
+    update: Ext.emptyFn,
+    
+    
+    destroy: Ext.emptyFn,
+    
+    
+    batch: function(operations, listeners) {
+        var me = this,
+            batch = Ext.create('Ext.data.Batch', {
+                proxy: me,
+                listeners: listeners || {}
+            }),
+            useBatch = me.batchActions, 
+            records;
+        
+        Ext.each(me.batchOrder.split(','), function(action) {
+            records = operations[action];
+            if (records) {
+                if (useBatch) {
+                    batch.add(Ext.create('Ext.data.Operation', {
+                        action: action,
+                        records: records
+                    }));
+                } else {
+                    Ext.each(records, function(record){
+                        batch.add(Ext.create('Ext.data.Operation', {
+                            action : action, 
+                            records: [record]
+                        }));
+                    });
+                }
+            }
+        }, me);
+        
+        batch.start();
+        return batch;
+    }
+}, function() {
+    
+    
+    
+    Ext.data.DataProxy = this;
+    
+    
+    
+});
+
+
+Ext.define('Ext.data.proxy.Server', {
+    extend: 'Ext.data.proxy.Proxy',
+    alias : 'proxy.server',
+    alternateClassName: 'Ext.data.ServerProxy',
+    uses  : ['Ext.data.Request'],
+
+    
+
+    
+    pageParam: 'page',
+
+    
+    startParam: 'start',
+
+    
+    limitParam: 'limit',
+
+    
+    groupParam: 'group',
+
+    
+    sortParam: 'sort',
+
+    
+    filterParam: 'filter',
+
+    
+    directionParam: 'dir',
+
+    
+    simpleSortMode: false,
+
+    
+    noCache : true,
+
+    
+    cacheString: "_dc",
+
+    
+    timeout : 30000,
+
+    
+
+    constructor: function(config) {
+        var me = this;
+
+        config = config || {};
+        this.addEvents(
+            
+            'exception'
+        );
+        me.callParent([config]);
+
+        
+        me.extraParams = config.extraParams || {};
+
+        me.api = config.api || {};
+
+        
+        me.nocache = me.noCache;
+    },
+
+    
+    create: function() {
+        return this.doRequest.apply(this, arguments);
+    },
+
+    read: function() {
+        return this.doRequest.apply(this, arguments);
+    },
+
+    update: function() {
+        return this.doRequest.apply(this, arguments);
+    },
+
+    destroy: function() {
+        return this.doRequest.apply(this, arguments);
+    },
+
+    
+    buildRequest: function(operation) {
+        var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
+            request;
+
+        
+        params = Ext.applyIf(params, this.getParams(operation));
+
+        if (operation.id && !params.id) {
+            params.id = operation.id;
+        }
+
+        request = Ext.create('Ext.data.Request', {
+            params   : params,
+            action   : operation.action,
+            records  : operation.records,
+            operation: operation,
+            url      : operation.url
+        });
+
+        request.url = this.buildUrl(request);
+
+        
+        operation.request = request;
+
+        return request;
+    },
+
+    
+    processResponse: function(success, operation, request, response, callback, scope){
+        var me = this,
+            reader,
+            result;
+
+        if (success === true) {
+            reader = me.getReader();
+            result = reader.read(me.extractResponseData(response));
+
+            if (result.success !== false) {
+                
+                Ext.apply(operation, {
+                    response: response,
+                    resultSet: result
+                });
+
+                operation.commitRecords(result.records);
+                operation.setCompleted();
+                operation.setSuccessful();
+            } else {
+                operation.setException(result.message);
+                me.fireEvent('exception', this, response, operation);
+            }
+        } else {
+            me.setException(operation, response);
+            me.fireEvent('exception', this, response, operation);
+        }
+
+        
+        if (typeof callback == 'function') {
+            callback.call(scope || me, operation);
+        }
+
+        me.afterRequest(request, success);
+    },
+
+    
+    setException: function(operation, response){
+        operation.setException({
+            status: response.status,
+            statusText: response.statusText
+        });
+    },
+
+    
+    extractResponseData: function(response){
+        return response;
+    },
+
+    
+    applyEncoding: function(value){
+        return Ext.encode(value);
+    },
+
+    
+    encodeSorters: function(sorters) {
+        var min = [],
+            length = sorters.length,
+            i = 0;
+
+        for (; i < length; i++) {
+            min[i] = {
+                property : sorters[i].property,
+                direction: sorters[i].direction
+            };
+        }
+        return this.applyEncoding(min);
+
+    },
+
+    
+    encodeFilters: function(filters) {
+        var min = [],
+            length = filters.length,
+            i = 0;
+
+        for (; i < length; i++) {
+            min[i] = {
+                property: filters[i].property,
+                value   : filters[i].value
+            };
+        }
+        return this.applyEncoding(min);
+    },
+
+    
+    getParams: function(operation) {
+        var me             = this,
+            params         = {},
+            isDef          = Ext.isDefined,
+            groupers       = operation.groupers,
+            sorters        = operation.sorters,
+            filters        = operation.filters,
+            page           = operation.page,
+            start          = operation.start,
+            limit          = operation.limit,
+
+            simpleSortMode = me.simpleSortMode,
+
+            pageParam      = me.pageParam,
+            startParam     = me.startParam,
+            limitParam     = me.limitParam,
+            groupParam     = me.groupParam,
+            sortParam      = me.sortParam,
+            filterParam    = me.filterParam,
+            directionParam = me.directionParam;
+
+        if (pageParam && isDef(page)) {
+            params[pageParam] = page;
+        }
+
+        if (startParam && isDef(start)) {
+            params[startParam] = start;
+        }
+
+        if (limitParam && isDef(limit)) {
+            params[limitParam] = limit;
+        }
+
+        if (groupParam && groupers && groupers.length > 0) {
+            
+            params[groupParam] = me.encodeSorters(groupers);
+        }
+
+        if (sortParam && sorters && sorters.length > 0) {
+            if (simpleSortMode) {
+                params[sortParam] = sorters[0].property;
+                params[directionParam] = sorters[0].direction;
+            } else {
+                params[sortParam] = me.encodeSorters(sorters);
+            }
+
+        }
+
+        if (filterParam && filters && filters.length > 0) {
+            params[filterParam] = me.encodeFilters(filters);
+        }
+
+        return params;
+    },
+
+    
+    buildUrl: function(request) {
+        var me = this,
+            url = me.getUrl(request);
+
+
+        if (me.noCache) {
+            url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now()));
+        }
+
+        return url;
+    },
+
+    
+    getUrl: function(request){
+        return request.url || this.api[request.action] || this.url;
+    },
+
+    
+    doRequest: function(operation, callback, scope) {
+    },
+
+    
+    afterRequest: Ext.emptyFn,
+
+    onDestroy: function() {
+        Ext.destroy(this.reader, this.writer);
+    }
+});
+
+
+Ext.define('Ext.data.proxy.Ajax', {
+    requires: ['Ext.util.MixedCollection', 'Ext.Ajax'],
+    extend: 'Ext.data.proxy.Server',
+    alias: 'proxy.ajax',
+    alternateClassName: ['Ext.data.HttpProxy', 'Ext.data.AjaxProxy'],
+    
+    
+    actionMethods: {
+        create : 'POST',
+        read   : 'GET',
+        update : 'POST',
+        destroy: 'POST'
+    },
+    
+    
+    
+    
+    doRequest: function(operation, callback, scope) {
+        var writer  = this.getWriter(),
+            request = this.buildRequest(operation, callback, scope);
+            
+        if (operation.allowWrite()) {
+            request = writer.write(request);
+        }
+        
+        Ext.apply(request, {
+            headers       : this.headers,
+            timeout       : this.timeout,
+            scope         : this,
+            callback      : this.createRequestCallback(request, operation, callback, scope),
+            method        : this.getMethod(request),
+            disableCaching: false 
+        });
+        
+        Ext.Ajax.request(request);
+        
+        return request;
+    },
+    
+    
+    getMethod: function(request) {
+        return this.actionMethods[request.action];
+    },
+    
+    
+    createRequestCallback: function(request, operation, callback, scope) {
+        var me = this;
+        
+        return function(options, success, response) {
+            me.processResponse(success, operation, request, response, callback, scope);
+        };
+    }
+}, function() {
+    
+    Ext.data.HttpProxy = this;
+});
+
+
+Ext.define('Ext.data.Model', {
+    alternateClassName: 'Ext.data.Record',
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: [
+        'Ext.ModelManager',
+        'Ext.data.IdGenerator',
+        'Ext.data.Field',
+        'Ext.data.Errors',
+        'Ext.data.Operation',
+        'Ext.data.validations',
+        'Ext.data.proxy.Ajax',
+        'Ext.util.MixedCollection'
+    ],
+
+    onClassExtended: function(cls, data) {
+        var onBeforeClassCreated = data.onBeforeClassCreated;
+
+        data.onBeforeClassCreated = function(cls, data) {
+            var me = this,
+                name = Ext.getClassName(cls),
+                prototype = cls.prototype,
+                superCls = cls.prototype.superclass,
+
+                validations = data.validations || [],
+                fields = data.fields || [],
+                associations = data.associations || [],
+                belongsTo = data.belongsTo,
+                hasMany = data.hasMany,
+                idgen = data.idgen,
+
+                fieldsMixedCollection = new Ext.util.MixedCollection(false, function(field) {
+                    return field.name;
+                }),
+
+                associationsMixedCollection = new Ext.util.MixedCollection(false, function(association) {
+                    return association.name;
+                }),
+
+                superValidations = superCls.validations,
+                superFields = superCls.fields,
+                superAssociations = superCls.associations,
+
+                association, i, ln,
+                dependencies = [];
+
+            
+            cls.modelName = name;
+            prototype.modelName = name;
+
+            
+            if (superValidations) {
+                validations = superValidations.concat(validations);
+            }
+
+            data.validations = validations;
+
+            
+            if (superFields) {
+                fields = superFields.items.concat(fields);
+            }
+
+            for (i = 0, ln = fields.length; i < ln; ++i) {
+                fieldsMixedCollection.add(new Ext.data.Field(fields[i]));
+            }
+
+            data.fields = fieldsMixedCollection;
+
+            if (idgen) {
+                data.idgen = Ext.data.IdGenerator.get(idgen);
+            }
+
+            
+            
+            if (belongsTo) {
+                belongsTo = Ext.Array.from(belongsTo);
+
+                for (i = 0, ln = belongsTo.length; i < ln; ++i) {
+                    association = belongsTo[i];
+
+                    if (!Ext.isObject(association)) {
+                        association = {model: association};
+                    }
+
+                    association.type = 'belongsTo';
+                    associations.push(association);
+                }
+
+                delete data.belongsTo;
+            }
+
+            if (hasMany) {
+                hasMany = Ext.Array.from(hasMany);
+                for (i = 0, ln = hasMany.length; i < ln; ++i) {
+                    association = hasMany[i];
+
+                    if (!Ext.isObject(association)) {
+                        association = {model: association};
+                    }
+
+                    association.type = 'hasMany';
+                    associations.push(association);
+                }
+
+                delete data.hasMany;
+            }
+
+            if (superAssociations) {
+                associations = superAssociations.items.concat(associations);
+            }
+
+            for (i = 0, ln = associations.length; i < ln; ++i) {
+                dependencies.push('association.' + associations[i].type.toLowerCase());
+            }
+
+            if (data.proxy) {
+                if (typeof data.proxy === 'string') {
+                    dependencies.push('proxy.' + data.proxy);
+                }
+                else if (typeof data.proxy.type === 'string') {
+                    dependencies.push('proxy.' + data.proxy.type);
+                }
+            }
+
+            Ext.require(dependencies, function() {
+                Ext.ModelManager.registerType(name, cls);
+
+                for (i = 0, ln = associations.length; i < ln; ++i) {
+                    association = associations[i];
+
+                    Ext.apply(association, {
+                        ownerModel: name,
+                        associatedModel: association.model
+                    });
+
+                    if (Ext.ModelManager.getModel(association.model) === undefined) {
+                        Ext.ModelManager.registerDeferredAssociation(association);
+                    } else {
+                        associationsMixedCollection.add(Ext.data.Association.create(association));
+                    }
+                }
+
+                data.associations = associationsMixedCollection;
+
+                onBeforeClassCreated.call(me, cls, data);
+
+                cls.setProxy(cls.prototype.proxy || cls.prototype.defaultProxyType);
+
+                
+                Ext.ModelManager.onModelDefined(cls);
+            });
+        };
+    },
+
+    inheritableStatics: {
+        
+        setProxy: function(proxy) {
+            
+            if (!proxy.isProxy) {
+                if (typeof proxy == "string") {
+                    proxy = {
+                        type: proxy
+                    };
+                }
+                proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
+            }
+            proxy.setModel(this);
+            this.proxy = this.prototype.proxy = proxy;
+
+            return proxy;
+        },
+
+        
+        getProxy: function() {
+            return this.proxy;
+        },
+
+        
+        load: function(id, config) {
+            config = Ext.apply({}, config);
+            config = Ext.applyIf(config, {
+                action: 'read',
+                id    : id
+            });
+
+            var operation  = Ext.create('Ext.data.Operation', config),
+                scope      = config.scope || this,
+                record     = null,
+                callback;
+
+            callback = function(operation) {
+                if (operation.wasSuccessful()) {
+                    record = operation.getRecords()[0];
+                    Ext.callback(config.success, scope, [record, operation]);
+                } else {
+                    Ext.callback(config.failure, scope, [record, operation]);
+                }
+                Ext.callback(config.callback, scope, [record, operation]);
+            };
+
+            this.proxy.read(operation, callback, this);
+        }
+    },
+
+    statics: {
+        PREFIX : 'ext-record',
+        AUTO_ID: 1,
+        EDIT   : 'edit',
+        REJECT : 'reject',
+        COMMIT : 'commit',
+
+        
+        id: function(rec) {
+            var id = [this.PREFIX, '-', this.AUTO_ID++].join('');
+            rec.phantom = true;
+            rec.internalId = id;
+            return id;
+        }
+    },
+
+    
+    idgen: {
+        isGenerator: true,
+        type: 'default',
+
+        generate: function () {
+            return null;
+        },
+        getRecId: function (rec) {
+            return rec.modelName + '-' + rec.internalId;
+        }
+    },
+
+    
+    editing : false,
+
+    
+    dirty : false,
+
+    
+    persistenceProperty: 'data',
+
+    evented: false,
+    isModel: true,
+
+    
+    phantom : false,
+
+    
+    idProperty: 'id',
+
+    
+    defaultProxyType: 'ajax',
+
+    
+    
+    
+
+    
+
+    
+    
+    
+    
+    
+
+    
+
+    
+    constructor: function(data, id, raw) {
+        data = data || {};
+
+        var me = this,
+            fields,
+            length,
+            field,
+            name,
+            i,
+            newId,
+            isArray = Ext.isArray(data),
+            newData = isArray ? {} : null; 
+
+        
+        me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
+
+        
+        me.raw = raw;
+
+        Ext.applyIf(me, {
+            data: {}
+        });
+
+        
+        me.modified = {};
+
+        
+        if (me.persistanceProperty) {
+            me.persistenceProperty = me.persistanceProperty;
+        }
+        me[me.persistenceProperty] = {};
+
+        me.mixins.observable.constructor.call(me);
+
+        
+        fields = me.fields.items;
+        length = fields.length;
+
+        for (i = 0; i < length; i++) {
+            field = fields[i];
+            name  = field.name;
+
+            if (isArray){
+                
+                
+                newData[name] = data[i];
+            }
+            else if (data[name] === undefined) {
+                data[name] = field.defaultValue;
+            }
+        }
+
+        me.set(newData || data);
+
+        if (me.getId()) {
+            me.phantom = false;
+        } else if (me.phantom) {
+            newId = me.idgen.generate();
+            if (newId !== null) {
+                me.setId(newId);
+            }
+        }
+
+        
+        me.dirty = false;
+        me.modified = {};
+
+        if (typeof me.init == 'function') {
+            me.init();
+        }
+
+        me.id = me.idgen.getRecId(me);
+    },
+
+    
+    get: function(field) {
+        return this[this.persistenceProperty][field];
+    },
+
+    
+    set: function(fieldName, value) {
+        var me = this,
+            fields = me.fields,
+            modified = me.modified,
+            convertFields = [],
+            field, key, i, currentValue, notEditing, count, length;
+
+        
+        if (arguments.length == 1 && Ext.isObject(fieldName)) {
+            notEditing = !me.editing;
+            count = 0;
+            for (key in fieldName) {
+                if (fieldName.hasOwnProperty(key)) {
+
+                    
+                    
+                    field = fields.get(key);
+                    if (field && field.convert !== field.type.convert) {
+                        convertFields.push(key);
+                        continue;
+                    }
+
+                    if (!count && notEditing) {
+                        me.beginEdit();
+                    }
+                    ++count;
+                    me.set(key, fieldName[key]);
+                }
+            }
+
+            length = convertFields.length;
+            if (length) {
+                if (!count && notEditing) {
+                    me.beginEdit();
+                }
+                count += length;
+                for (i = 0; i < length; i++) {
+                    field = convertFields[i];
+                    me.set(field, fieldName[field]);
+                }
+            }
+
+            if (notEditing && count) {
+                me.endEdit();
+            }
+        } else {
+            if (fields) {
+                field = fields.get(fieldName);
+
+                if (field && field.convert) {
+                    value = field.convert(value, me);
+                }
+            }
+            currentValue = me.get(fieldName);
+            me[me.persistenceProperty][fieldName] = value;
+
+            if (field && field.persist && !me.isEqual(currentValue, value)) {
+                if (me.isModified(fieldName)) {
+                    if (me.isEqual(modified[fieldName], value)) {
+                        
+                        
+                        delete modified[fieldName];
+                        
+                        
+                        me.dirty = false;
+                        for (key in modified) {
+                            if (modified.hasOwnProperty(key)){
+                                me.dirty = true;
+                                break;
+                            }
+                        }
+                    }
+                } else {
+                    me.dirty = true;
+                    modified[fieldName] = currentValue;
+                }
+            }
+
+            if (!me.editing) {
+                me.afterEdit();
+            }
+        }
+    },
+
+    
+    isEqual: function(a, b){
+        if (Ext.isDate(a) && Ext.isDate(b)) {
+            return a.getTime() === b.getTime();
+        }
+        return a === b;
+    },
+
+    
+    beginEdit : function(){
+        var me = this;
+        if (!me.editing) {
+            me.editing = true;
+            me.dirtySave = me.dirty;
+            me.dataSave = Ext.apply({}, me[me.persistenceProperty]);
+            me.modifiedSave = Ext.apply({}, me.modified);
+        }
+    },
+
+    
+    cancelEdit : function(){
+        var me = this;
+        if (me.editing) {
+            me.editing = false;
+            
+            me.modified = me.modifiedSave;
+            me[me.persistenceProperty] = me.dataSave;
+            me.dirty = me.dirtySave;
+            delete me.modifiedSave;
+            delete me.dataSave;
+            delete me.dirtySave;
+        }
+    },
+
+    
+    endEdit : function(silent){
+        var me = this,
+            didChange;
+            
+        if (me.editing) {
+            me.editing = false;
+            didChange = me.dirty || me.changedWhileEditing();
+            delete me.modifiedSave;
+            delete me.dataSave;
+            delete me.dirtySave;
+            if (silent !== true && didChange) {
+                me.afterEdit();
+            }
+        }
+    },
+    
+    
+    changedWhileEditing: function(){
+        var me = this,
+            saved = me.dataSave,
+            data = me[me.persistenceProperty],
+            key;
+            
+        for (key in data) {
+            if (data.hasOwnProperty(key)) {
+                if (!me.isEqual(data[key], saved[key])) {
+                    return true;
+                }
+            }
+        }
+        return false; 
+    },
+
+    
+    getChanges : function(){
+        var modified = this.modified,
+            changes  = {},
+            field;
+
+        for (field in modified) {
+            if (modified.hasOwnProperty(field)){
+                changes[field] = this.get(field);
+            }
+        }
+
+        return changes;
+    },
+
+    
+    isModified : function(fieldName) {
+        return this.modified.hasOwnProperty(fieldName);
+    },
+
+    
+    setDirty : function() {
+        var me = this,
+            name;
+
+        me.dirty = true;
+
+        me.fields.each(function(field) {
+            if (field.persist) {
+                name = field.name;
+                me.modified[name] = me.get(name);
+            }
+        }, me);
+    },
+
+
+    
+    reject : function(silent) {
+        var me = this,
+            modified = me.modified,
+            field;
+
+        for (field in modified) {
+            if (modified.hasOwnProperty(field)) {
+                if (typeof modified[field] != "function") {
+                    me[me.persistenceProperty][field] = modified[field];
+                }
+            }
+        }
+
+        me.dirty = false;
+        me.editing = false;
+        me.modified = {};
+
+        if (silent !== true) {
+            me.afterReject();
+        }
+    },
+
+    
+    commit : function(silent) {
+        var me = this;
+
+        me.phantom = me.dirty = me.editing = false;
+        me.modified = {};
+
+        if (silent !== true) {
+            me.afterCommit();
+        }
+    },
+
+    
+    copy : function(newId) {
+        var me = this;
+
+        return new me.self(Ext.apply({}, me[me.persistenceProperty]), newId || me.internalId);
+    },
+
+    
+    setProxy: function(proxy) {
+        
+        if (!proxy.isProxy) {
+            if (typeof proxy === "string") {
+                proxy = {
+                    type: proxy
+                };
+            }
+            proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
+        }
+        proxy.setModel(this.self);
+        this.proxy = proxy;
+
+        return proxy;
+    },
+
+    
+    getProxy: function() {
+        return this.proxy;
+    },
+
+    
+    validate: function() {
+        var errors      = Ext.create('Ext.data.Errors'),
+            validations = this.validations,
+            validators  = Ext.data.validations,
+            length, validation, field, valid, type, i;
+
+        if (validations) {
+            length = validations.length;
+
+            for (i = 0; i < length; i++) {
+                validation = validations[i];
+                field = validation.field || validation.name;
+                type  = validation.type;
+                valid = validators[type](validation, this.get(field));
+
+                if (!valid) {
+                    errors.add({
+                        field  : field,
+                        message: validation.message || validators[type + 'Message']
+                    });
+                }
+            }
+        }
+
+        return errors;
+    },
+
+    
+    isValid: function(){
+        return this.validate().isValid();
+    },
+
+    
+    save: function(options) {
+        options = Ext.apply({}, options);
+
+        var me     = this,
+            action = me.phantom ? 'create' : 'update',
+            record = null,
+            scope  = options.scope || me,
+            operation,
+            callback;
+
+        Ext.apply(options, {
+            records: [me],
+            action : action
+        });
+
+        operation = Ext.create('Ext.data.Operation', options);
+
+        callback = function(operation) {
+            if (operation.wasSuccessful()) {
+                record = operation.getRecords()[0];
+                
+                
+                me.set(record.data);
+                record.dirty = false;
+
+                Ext.callback(options.success, scope, [record, operation]);
+            } else {
+                Ext.callback(options.failure, scope, [record, operation]);
+            }
+
+            Ext.callback(options.callback, scope, [record, operation]);
+        };
+
+        me.getProxy()[action](operation, callback, me);
+
+        return me;
+    },
+
+    
+    destroy: function(options){
+        options = Ext.apply({}, options);
+
+        var me     = this,
+            record = null,
+            scope  = options.scope || me,
+            operation,
+            callback;
+
+        Ext.apply(options, {
+            records: [me],
+            action : 'destroy'
+        });
+
+        operation = Ext.create('Ext.data.Operation', options);
+        callback = function(operation) {
+            if (operation.wasSuccessful()) {
+                Ext.callback(options.success, scope, [record, operation]);
+            } else {
+                Ext.callback(options.failure, scope, [record, operation]);
+            }
+            Ext.callback(options.callback, scope, [record, operation]);
+        };
+
+        me.getProxy().destroy(operation, callback, me);
+        return me;
+    },
+
+    
+    getId: function() {
+        return this.get(this.idProperty);
+    },
+
+    
+    setId: function(id) {
+        this.set(this.idProperty, id);
+    },
+
+    
+    join : function(store) {
+        
+        this.store = store;
+    },
+
+    
+    unjoin: function(store) {
+        delete this.store;
+    },
+
+    
+    afterEdit : function() {
+        this.callStore('afterEdit');
+    },
+
+    
+    afterReject : function() {
+        this.callStore("afterReject");
+    },
+
+    
+    afterCommit: function() {
+        this.callStore('afterCommit');
+    },
+
+    
+    callStore: function(fn) {
+        var store = this.store;
+
+        if (store !== undefined && typeof store[fn] == "function") {
+            store[fn](this);
+        }
+    },
+
+    
+    getAssociatedData: function(){
+        return this.prepareAssociatedData(this, [], null);
+    },
+
+    
+    prepareAssociatedData: function(record, ids, associationType) {
+        
+        var associations     = record.associations.items,
+            associationCount = associations.length,
+            associationData  = {},
+            associatedStore, associatedName, associatedRecords, associatedRecord,
+            associatedRecordCount, association, id, i, j, type, allow;
+
+        for (i = 0; i < associationCount; i++) {
+            association = associations[i];
+            type = association.type;
+            allow = true;
+            if (associationType) {
+                allow = type == associationType;
+            }
+            if (allow && type == 'hasMany') {
+
+                
+                associatedStore = record[association.storeName];
+
+                
+                associationData[association.name] = [];
+
+                
+                if (associatedStore && associatedStore.data.length > 0) {
+                    associatedRecords = associatedStore.data.items;
+                    associatedRecordCount = associatedRecords.length;
+
+                    
+                    for (j = 0; j < associatedRecordCount; j++) {
+                        associatedRecord = associatedRecords[j];
+                        
+                        id = associatedRecord.id;
+
+                        
+                        
+                        if (Ext.Array.indexOf(ids, id) == -1) {
+                            ids.push(id);
+
+                            associationData[association.name][j] = associatedRecord.data;
+                            Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids, type));
+                        }
+                    }
+                }
+            } else if (allow && type == 'belongsTo') {
+                associatedRecord = record[association.instanceName];
+                if (associatedRecord !== undefined) {
+                    id = associatedRecord.id;
+                    if (Ext.Array.indexOf(ids, id) == -1) {
+                        ids.push(id);
+                        associationData[association.name] = associatedRecord.data;
+                        Ext.apply(associationData[association.name], this.prepareAssociatedData(associatedRecord, ids, type));
+                    }
+                }
+            }
+        }
+
+        return associationData;
+    }
+});
+
+
+Ext.define('Ext.data.StoreManager', {
+    extend: 'Ext.util.MixedCollection',
+    alternateClassName: ['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'],
+    singleton: true,
+    uses: ['Ext.data.ArrayStore'],
+    
+    
+
+    
+    register : function() {
+        for (var i = 0, s; (s = arguments[i]); i++) {
+            this.add(s);
+        }
+    },
+
+    
+    unregister : function() {
+        for (var i = 0, s; (s = arguments[i]); i++) {
+            this.remove(this.lookup(s));
+        }
+    },
+
+    
+    lookup : function(store) {
+        
+        if (Ext.isArray(store)) {
+            var fields = ['field1'], 
+                expand = !Ext.isArray(store[0]),
+                data = store,
+                i,
+                len;
+                
+            if(expand){
+                data = [];
+                for (i = 0, len = store.length; i < len; ++i) {
+                    data.push([store[i]]);
+                }
+            } else {
+                for(i = 2, len = store[0].length; i <= len; ++i){
+                    fields.push('field' + i);
+                }
+            }
+            return Ext.create('Ext.data.ArrayStore', {
+                data  : data,
+                fields: fields,
+                autoDestroy: true,
+                autoCreated: true,
+                expanded: expand
+            });
+        }
+        
+        if (Ext.isString(store)) {
+            
+            return this.get(store);
+        } else {
+            
+            return Ext.data.AbstractStore.create(store);
+        }
+    },
+
+    
+    getKey : function(o) {
+         return o.storeId;
+    }
+}, function() {    
+    
+    Ext.regStore = function(name, config) {
+        var store;
+
+        if (Ext.isObject(name)) {
+            config = name;
+        } else {
+            config.storeId = name;
+        }
+
+        if (config instanceof Ext.data.Store) {
+            store = config;
+        } else {
+            store = Ext.create('Ext.data.Store', config);
+        }
+
+        return Ext.data.StoreManager.register(store);
+    };
+
+    
+    Ext.getStore = function(name) {
+        return Ext.data.StoreManager.lookup(name);
+    };
+});
+
+
+Ext.define('Ext.Component', {
+
+    
+
+    alias: ['widget.component', 'widget.box'],
+
+    extend: 'Ext.AbstractComponent',
+
+    requires: [
+        'Ext.util.DelayedTask'
+    ],
+
+    uses: [
+        'Ext.Layer',
+        'Ext.resizer.Resizer',
+        'Ext.util.ComponentDragger'
+    ],
+
+    mixins: {
+        floating: 'Ext.util.Floating'
+    },
+
+    statics: {
+        
+        DIRECTION_TOP: 'top',
+        DIRECTION_RIGHT: 'right',
+        DIRECTION_BOTTOM: 'bottom',
+        DIRECTION_LEFT: 'left',
+
+        VERTICAL_DIRECTION_Re: /^(?:top|bottom)$/,
+
+        
+        
+        INVALID_ID_CHARS_Re: /[\.,\s]/g
+    },
+
+    
+
+    
+
+    
+    resizeHandles: 'all',
+
+    
+
+    
+    floating: false,
+
+    
+    toFrontOnShow: true,
+
+    
+
+    
+
+    
+
+    
+
+    hideMode: 'display',
+    
+    hideParent: false,
+
+    ariaRole: 'presentation',
+
+    bubbleEvents: [],
+
+    actionMode: 'el',
+    monPropRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
+
+    
+    
+    
+    
+    
+    
+
+    
+    constructor: function(config) {
+        var me = this;
+
+        config = config || {};
+        if (config.initialConfig) {
+
+            
+            if (config.isAction) {
+                me.baseAction = config;
+            }
+            config = config.initialConfig;
+            
+        }
+        else if (config.tagName || config.dom || Ext.isString(config)) {
+            
+            config = {
+                applyTo: config,
+                id: config.id || config
+            };
+        }
+
+        me.callParent([config]);
+
+        
+        
+        if (me.baseAction){
+            me.baseAction.addComponent(me);
+        }
+    },
+
+    
+    initComponent: function() {
+        var me = this;
+
+        me.callParent();
+
+        if (me.listeners) {
+            me.on(me.listeners);
+            delete me.listeners;
+        }
+        me.enableBubble(me.bubbleEvents);
+        me.mons = [];
+    },
+
+    
+    afterRender: function() {
+        var me = this,
+            resizable = me.resizable;
+
+        if (me.floating) {
+            me.makeFloating(me.floating);
+        } else {
+            me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
+        }
+
+        if (Ext.isDefined(me.autoScroll)) {
+            me.setAutoScroll(me.autoScroll);
+        }
+        me.callParent();
+
+        if (!(me.x && me.y) && (me.pageX || me.pageY)) {
+            me.setPagePosition(me.pageX, me.pageY);
+        }
+
+        if (resizable) {
+            me.initResizable(resizable);
+        }
+
+        if (me.draggable) {
+            me.initDraggable();
+        }
+
+        me.initAria();
+    },
+
+    initAria: function() {
+        var actionEl = this.getActionEl(),
+            role = this.ariaRole;
+        if (role) {
+            actionEl.dom.setAttribute('role', role);
+        }
+    },
+
+    
+    setAutoScroll : function(scroll){
+        var me = this,
+            targetEl;
+        scroll = !!scroll;
+        if (me.rendered) {
+            targetEl = me.getTargetEl();
+            targetEl.setStyle('overflow', scroll ? 'auto' : '');
+            if (scroll && (Ext.isIE6 || Ext.isIE7)) {
+                
+                
+                targetEl.position();
+            }
+        }
+        me.autoScroll = scroll;
+        return me;
+    },
+
+    
+    makeFloating : function(cfg){
+        this.mixins.floating.constructor.call(this, cfg);
+    },
+
+    initResizable: function(resizable) {
+        var me = this;
+
+        resizable = Ext.apply({
+            target: me,
+            dynamic: false,
+            constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.getScopeParent()),
+            handles: me.resizeHandles
+        }, resizable);
+        resizable.target = me;
+        me.resizer = Ext.create('Ext.resizer.Resizer', resizable);
+    },
+
+    getDragEl: function() {
+        return this.el;
+    },
+
+    initDraggable: function() {
+        var me = this,
+            ddConfig = Ext.applyIf({
+                el: me.getDragEl(),
+                constrainTo: me.constrain ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.getScopeParent())) : undefined
+            }, me.draggable);
+
+        
+        if (me.constrain || me.constrainDelegate) {
+            ddConfig.constrain = me.constrain;
+            ddConfig.constrainDelegate = me.constrainDelegate;
+        }
+
+        me.dd = Ext.create('Ext.util.ComponentDragger', me, ddConfig);
+    },
+
+    
+    setPosition: function(x, y, animate) {
+        var me = this,
+            el = me.el,
+            to = {},
+            adj, adjX, adjY, xIsNumber, yIsNumber;
+
+        if (Ext.isArray(x)) {
+            animate = y;
+            y = x[1];
+            x = x[0];
+        }
+        me.x = x;
+        me.y = y;
+
+        if (!me.rendered) {
+            return me;
+        }
+
+        adj = me.adjustPosition(x, y);
+        adjX = adj.x;
+        adjY = adj.y;
+        xIsNumber = Ext.isNumber(adjX);
+        yIsNumber = Ext.isNumber(adjY);
+
+        if (xIsNumber || yIsNumber) {
+            if (animate) {
+                if (xIsNumber) {
+                    to.left = adjX;
+                }
+                if (yIsNumber) {
+                    to.top = adjY;
+                }
+
+                me.stopAnimation();
+                me.animate(Ext.apply({
+                    duration: 1000,
+                    listeners: {
+                        afteranimate: Ext.Function.bind(me.afterSetPosition, me, [adjX, adjY])
+                    },
+                    to: to
+                }, animate));
+            }
+            else {
+                if (!xIsNumber) {
+                    el.setTop(adjY);
+                }
+                else if (!yIsNumber) {
+                    el.setLeft(adjX);
+                }
+                else {
+                    el.setLeftTop(adjX, adjY);
+                }
+                me.afterSetPosition(adjX, adjY);
+            }
+        }
+        return me;
+    },
+
+    
+    afterSetPosition: function(ax, ay) {
+        this.onPosition(ax, ay);
+        this.fireEvent('move', this, ax, ay);
+    },
+
+    
+    showAt: function(x, y, animate) {
+        var me = this;
+
+        if (me.floating) {
+            me.setPosition(x, y, animate);
+        } else {
+            me.setPagePosition(x, y, animate);
+        }
+        me.show();
+    },
+
+    
+    setPagePosition: function(x, y, animate) {
+        var me = this,
+            p;
+
+        if (Ext.isArray(x)) {
+            y = x[1];
+            x = x[0];
+        }
+        me.pageX = x;
+        me.pageY = y;
+        if (me.floating && me.floatParent) {
+            
+            p = me.floatParent.getTargetEl().getViewRegion();
+            if (Ext.isNumber(x) && Ext.isNumber(p.left)) {
+                x -= p.left;
+            }
+            if (Ext.isNumber(y) && Ext.isNumber(p.top)) {
+                y -= p.top;
+            }
+            me.setPosition(x, y, animate);
+        }
+        else {
+            p = me.el.translatePoints(x, y);
+            me.setPosition(p.left, p.top, animate);
+        }
+        return me;
+    },
+
+    
+    getBox : function(local){
+        var pos = this.getPosition(local),
+            size = this.getSize();
+
+        size.x = pos[0];
+        size.y = pos[1];
+        return size;
+    },
+
+    
+    updateBox : function(box){
+        this.setSize(box.width, box.height);
+        this.setPagePosition(box.x, box.y);
+        return this;
+    },
+
+    
+    getOuterSize: function() {
+        var el = this.el;
+        return {
+            width: el.getWidth() + el.getMargin('lr'),
+            height: el.getHeight() + el.getMargin('tb')
+        };
+    },
+
+    
+    adjustPosition: function(x, y) {
+
+        
+        if (this.floating && this.floatParent) {
+            var o = this.floatParent.getTargetEl().getViewRegion();
+            x += o.left;
+            y += o.top;
+        }
+
+        return {
+            x: x,
+            y: y
+        };
+    },
+
+    
+    getPosition: function(local) {
+        var me = this,
+            el = me.el,
+            xy,
+            o;
+
+        
+        if ((local === true) || (me.floating && !me.floatParent)) {
+            return [el.getLeft(true), el.getTop(true)];
+        }
+        xy = me.xy || el.getXY();
+
+        
+        if (me.floating) {
+            o = me.floatParent.getTargetEl().getViewRegion();
+            xy[0] -= o.left;
+            xy[1] -= o.top;
+        }
+        return xy;
+    },
+
+    getId: function() {
+        var me = this,
+            xtype;
+
+        if (!me.id) {
+            xtype = me.getXType();
+            xtype = xtype ? xtype.replace(Ext.Component.INVALID_ID_CHARS_Re, '-') : 'ext-comp';
+            me.id = xtype + '-' + me.getAutoId();
+        }
+        return me.id;
+    },
+
+    onEnable: function() {
+        var actionEl = this.getActionEl();
+        actionEl.dom.removeAttribute('aria-disabled');
+        actionEl.dom.disabled = false;
+        this.callParent();
+    },
+
+    onDisable: function() {
+        var actionEl = this.getActionEl();
+        actionEl.dom.setAttribute('aria-disabled', true);
+        actionEl.dom.disabled = true;
+        this.callParent();
+    },
+
+    
+    show: function(animateTarget, cb, scope) {
+        var me = this;
+
+        if (me.rendered && me.isVisible()) {
+            if (me.toFrontOnShow && me.floating) {
+                me.toFront();
+            }
+        } else if (me.fireEvent('beforeshow', me) !== false) {
+            me.hidden = false;
+
+            
+            if (!me.rendered && (me.autoRender || me.floating)) {
+                me.doAutoRender();
+            }
+            if (me.rendered) {
+                me.beforeShow();
+                me.onShow.apply(me, arguments);
+
+                
+                
+                if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
+                    me.ownerCt.doLayout();
+                }
+                me.afterShow.apply(me, arguments);
+            }
+        }
+        return me;
+    },
+
+    beforeShow: Ext.emptyFn,
+
+    
+    onShow: function() {
+        var me = this;
+
+        me.el.show();
+        me.callParent(arguments);
+        if (me.floating && me.constrain) {
+            me.doConstrain();
+        }
+    },
+
+    afterShow: function(animateTarget, cb, scope) {
+        var me = this,
+            fromBox,
+            toBox,
+            ghostPanel;
+
+        
+        animateTarget = animateTarget || me.animateTarget;
+
+        
+        if (!me.ghost) {
+            animateTarget = null;
+        }
+        
+        if (animateTarget) {
+            animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
+            toBox = me.el.getBox();
+            fromBox = animateTarget.getBox();
+            me.el.addCls(Ext.baseCSSPrefix + 'hide-offsets');
+            ghostPanel = me.ghost();
+            ghostPanel.el.stopAnimation();
+
+            
+            ghostPanel.el.setX(-10000);
+
+            ghostPanel.el.animate({
+                from: fromBox,
+                to: toBox,
+                listeners: {
+                    afteranimate: function() {
+                        delete ghostPanel.componentLayout.lastComponentSize;
+                        me.unghost();
+                        me.el.removeCls(Ext.baseCSSPrefix + 'hide-offsets');
+                        me.onShowComplete(cb, scope);
+                    }
+                }
+            });
+        }
+        else {
+            me.onShowComplete(cb, scope);
+        }
+    },
+
+    onShowComplete: function(cb, scope) {
+        var me = this;
+        if (me.floating) {
+            me.toFront();
+        }
+        Ext.callback(cb, scope || me);
+        me.fireEvent('show', me);
+    },
+
+    
+    hide: function() {
+        var me = this;
+
+        
+        
+        me.showOnParentShow = false;
+
+        if (!(me.rendered && !me.isVisible()) && me.fireEvent('beforehide', me) !== false) {
+            me.hidden = true;
+            if (me.rendered) {
+                me.onHide.apply(me, arguments);
+
+                
+                
+                if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
+                    me.ownerCt.doLayout();
+                }
+            }
+        }
+        return me;
+    },
+
+    
+    onHide: function(animateTarget, cb, scope) {
+        var me = this,
+            ghostPanel,
+            toBox;
+
+        
+        animateTarget = animateTarget || me.animateTarget;
+
+        
+        if (!me.ghost) {
+            animateTarget = null;
+        }
+        
+        if (animateTarget) {
+            animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
+            ghostPanel = me.ghost();
+            ghostPanel.el.stopAnimation();
+            toBox = animateTarget.getBox();
+            toBox.width += 'px';
+            toBox.height += 'px';
+            ghostPanel.el.animate({
+                to: toBox,
+                listeners: {
+                    afteranimate: function() {
+                        delete ghostPanel.componentLayout.lastComponentSize;
+                        ghostPanel.el.hide();
+                        me.afterHide(cb, scope);
+                    }
+                }
+            });
+        }
+        me.el.hide();
+        if (!animateTarget) {
+            me.afterHide(cb, scope);
+        }
+    },
+
+    afterHide: function(cb, scope) {
+        Ext.callback(cb, scope || this);
+        this.fireEvent('hide', this);
+    },
+
+    
+    onDestroy: function() {
+        var me = this;
+
+        
+        if (me.rendered) {
+            Ext.destroy(
+                me.proxy,
+                me.proxyWrap,
+                me.resizer
+            );
+            
+            if (me.actionMode == 'container' || me.removeMode == 'container') {
+                me.container.remove();
+            }
+        }
+        delete me.focusTask;
+        me.callParent();
+    },
+
+    deleteMembers: function() {
+        var args = arguments,
+            len = args.length,
+            i = 0;
+        for (; i < len; ++i) {
+            delete this[args[i]];
+        }
+    },
+
+    
+    focus: function(selectText, delay) {
+        var me = this,
+                focusEl;
+
+        if (delay) {
+            if (!me.focusTask) {
+                me.focusTask = Ext.create('Ext.util.DelayedTask', me.focus);
+            }
+            me.focusTask.delay(Ext.isNumber(delay) ? delay : 10, null, me, [selectText, false]);
+            return me;
+        }
+
+        if (me.rendered && !me.isDestroyed) {
+            
+            focusEl = me.getFocusEl();
+            focusEl.focus();
+            if (focusEl.dom && selectText === true) {
+                focusEl.dom.select();
+            }
+
+            
+            
+            if (me.floating) {
+                me.toFront(true);
+            }
+        }
+        return me;
+    },
+
+    
+    getFocusEl: function() {
+        return this.el;
+    },
+
+    
+    blur: function() {
+        if (this.rendered) {
+            this.getFocusEl().blur();
+        }
+        return this;
+    },
+
+    getEl: function() {
+        return this.el;
+    },
+
+    
+    getResizeEl: function() {
+        return this.el;
+    },
+
+    
+    getPositionEl: function() {
+        return this.el;
+    },
+
+    
+    getActionEl: function() {
+        return this.el;
+    },
+
+    
+    getVisibilityEl: function() {
+        return this.el;
+    },
+
+    
+    onResize: Ext.emptyFn,
+
+    
+    getBubbleTarget: function() {
+        return this.ownerCt;
+    },
+
+    
+    getContentTarget: function() {
+        return this.el;
+    },
+
+    
+    cloneConfig: function(overrides) {
+        overrides = overrides || {};
+        var id = overrides.id || Ext.id(),
+            cfg = Ext.applyIf(overrides, this.initialConfig),
+            self;
+
+        cfg.id = id;
+
+        self = Ext.getClass(this);
+
+        
+        return new self(cfg);
+    },
+
+    
+    getXType: function() {
+        return this.self.xtype;
+    },
+
+    
+    findParentBy: function(fn) {
+        var p;
+
+        
+        for (p = this.ownerCt; p && !fn(p, this); p = p.ownerCt);
+        return p || null;
+    },
+
+    
+    findParentByType: function(xtype) {
+        return Ext.isFunction(xtype) ?
+            this.findParentBy(function(p) {
+                return p.constructor === xtype;
+            })
+        :
+            this.up(xtype);
+    },
+
+    
+    bubble: function(fn, scope, args) {
+        var p = this;
+        while (p) {
+            if (fn.apply(scope || p, args || [p]) === false) {
+                break;
+            }
+            p = p.ownerCt;
+        }
+        return this;
+    },
+
+    getProxy: function() {
+        var me = this,
+            target;
+
+        if (!me.proxy) {
+            target = Ext.getBody();
+            if (Ext.scopeResetCSS) {
+                me.proxyWrap = target = Ext.getBody().createChild({
+                    cls: Ext.baseCSSPrefix + 'reset'
+                });
+            }
+            me.proxy = me.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', target, true);
+        }
+        return me.proxy;
+    }
+
+});
+
+
+Ext.define('Ext.layout.container.AbstractContainer', {
+
+    
+
+    extend: 'Ext.layout.Layout',
+
+    
+
+    type: 'container',
+
+    
+    bindToOwnerCtComponent: false,
+
+    
+    bindToOwnerCtContainer: false,
+
+    
+
+    
+    setItemSize: function(item, width, height) {
+        if (Ext.isObject(width)) {
+            height = width.height;
+            width = width.width;
+        }
+        item.setCalculatedSize(width, height, this.owner);
+    },
+
+    
+    getLayoutItems: function() {
+        return this.owner && this.owner.items && this.owner.items.items || [];
+    },
+
+    
+    beforeLayout: function() {
+        return !this.owner.collapsed && this.callParent(arguments);
+    },
+
+    afterLayout: function() {
+        this.owner.afterLayout(this);
+    },
+    
+     getTarget: function() {
+         return this.owner.getTargetEl();
+     },
+    
+     getRenderTarget: function() {
+         return this.owner.getTargetEl();
+     }
+});
+
+
+Ext.define('Ext.layout.container.Container', {
+
+    
+
+    extend: 'Ext.layout.container.AbstractContainer',
+    alternateClassName: 'Ext.layout.ContainerLayout',
+
+    
+
+    layoutItem: function(item, box) {
+        if (box) {
+            item.doComponentLayout(box.width, box.height);
+        } else {
+            item.doComponentLayout();
+        }
+    },
+
+    getLayoutTargetSize : function() {
+        var target = this.getTarget(),
+            ret;
+
+        if (target) {
+            ret = target.getViewSize();
+
+            
+            
+            
+            if (Ext.isIE && ret.width == 0){
+                ret = target.getStyleSize();
+            }
+
+            ret.width -= target.getPadding('lr');
+            ret.height -= target.getPadding('tb');
+        }
+        return ret;
+    },
+
+    beforeLayout: function() {
+        if (this.owner.beforeLayout(arguments) !== false) {
+            return this.callParent(arguments);
+        }
+        else {
+            return false;
+        }
+    },
+
+    
+    getRenderedItems: function() {
+        var me = this,
+            target = me.getTarget(),
+            items = me.getLayoutItems(),
+            ln = items.length,
+            renderedItems = [],
+            i, item;
+
+        for (i = 0; i < ln; i++) {
+            item = items[i];
+            if (item.rendered && me.isValidParent(item, target, i)) {
+                renderedItems.push(item);
+            }
+        }
+
+        return renderedItems;
+    },
+
+    
+    getVisibleItems: function() {
+        var target   = this.getTarget(),
+            items = this.getLayoutItems(),
+            ln = items.length,
+            visibleItems = [],
+            i, item;
+
+        for (i = 0; i < ln; i++) {
+            item = items[i];
+            if (item.rendered && this.isValidParent(item, target, i) && item.hidden !== true) {
+                visibleItems.push(item);
+            }
+        }
+
+        return visibleItems;
+    }
+});
+
+Ext.define('Ext.layout.container.Auto', {
+
+    
+
+    alias: ['layout.auto', 'layout.autocontainer'],
+
+    extend: 'Ext.layout.container.Container',
+
+    
+
+    type: 'autocontainer',
+
+    bindToOwnerCtComponent: true,
+
+    
+    onLayout : function(owner, target) {
+        var me = this,
+            items = me.getLayoutItems(),
+            ln = items.length,
+            i;
+
+        
+        if (ln) {
+            
+            
+            
+            if (!me.clearEl) {
+                me.clearEl = me.getRenderTarget().createChild({
+                    cls: Ext.baseCSSPrefix + 'clear',
+                    role: 'presentation'
+                });
+            }
+
+            
+            for (i = 0; i < ln; i++) {
+                me.setItemSize(items[i]);
+            }
+        }
+    },
+
+    configureItem: function(item) {
+        this.callParent(arguments);
+
+        
+        item.layoutManagedHeight = 2;
+        item.layoutManagedWidth = 2;
+    }
+});
+
+Ext.define('Ext.container.AbstractContainer', {
+
+    
+
+    extend: 'Ext.Component',
+
+    requires: [
+        'Ext.util.MixedCollection',
+        'Ext.layout.container.Auto',
+        'Ext.ZIndexManager'
+    ],
+
+    
+    
+
+    
+    
+    
+
+    
+    suspendLayout : false,
+
+    
+    autoDestroy : true,
+
+     
+    defaultType: 'panel',
+
+    isContainer : true,
+
+    
+    layoutCounter : 0,
+
+    baseCls: Ext.baseCSSPrefix + 'container',
+
+    
+    bubbleEvents: ['add', 'remove'],
+
+    
+    initComponent : function(){
+        var me = this;
+        me.addEvents(
+            
+            'afterlayout',
+            
+            'beforeadd',
+            
+            'beforeremove',
+            
+            'add',
+            
+            'remove'
+        );
+
+        
+        me.layoutOnShow = Ext.create('Ext.util.MixedCollection');
+        me.callParent();
+        me.initItems();
+    },
+
+    
+    initItems : function() {
+        var me = this,
+            items = me.items;
+
+        
+        me.items = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
+
+        if (items) {
+            if (!Ext.isArray(items)) {
+                items = [items];
+            }
+
+            me.add(items);
+        }
+    },
+
+    
+    afterRender : function() {
+        this.getLayout();
+        this.callParent();
+    },
+
+    renderChildren: function () {
+        var me = this,
+            layout = me.getLayout();
+
+        me.callParent();
+        
+
+        if (layout) {
+            me.suspendLayout = true;
+            layout.renderChildren();
+            delete me.suspendLayout;
+        }
+    },
+
+    
+    setLayout : function(layout) {
+        var currentLayout = this.layout;
+
+        if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
+            currentLayout.setOwner(null);
+        }
+
+        this.layout = layout;
+        layout.setOwner(this);
+    },
+
+    
+    getLayout : function() {
+        var me = this;
+        if (!me.layout || !me.layout.isLayout) {
+            me.setLayout(Ext.layout.Layout.create(me.layout, 'autocontainer'));
+        }
+
+        return me.layout;
+    },
+
+    
+    doLayout : function() {
+        var me = this,
+            layout = me.getLayout();
+
+        if (me.rendered && layout && !me.suspendLayout) {
+            
+            if (!me.isFixedWidth() || !me.isFixedHeight()) {
+                
+                if (me.componentLayout.layoutBusy !== true) {
+                    me.doComponentLayout();
+                    if (me.componentLayout.layoutCancelled === true) {
+                        layout.layout();
+                    }
+                }
+            }
+            
+            else {
+                
+                if (layout.layoutBusy !== true) {
+                    layout.layout();
+                }
+            }
+        }
+
+        return me;
+    },
+
+    
+    afterLayout : function(layout) {
+        ++this.layoutCounter;
+        this.fireEvent('afterlayout', this, layout);
+    },
+
+    
+    prepareItems : function(items, applyDefaults) {
+        if (!Ext.isArray(items)) {
+            items = [items];
+        }
+
+        
+        var i = 0,
+            len = items.length,
+            item;
+
+        for (; i < len; i++) {
+            item = items[i];
+            if (applyDefaults) {
+                item = this.applyDefaults(item);
+            }
+            items[i] = this.lookupComponent(item);
+        }
+        return items;
+    },
+
+    
+    applyDefaults : function(config) {
+        var defaults = this.defaults;
+
+        if (defaults) {
+            if (Ext.isFunction(defaults)) {
+                defaults = defaults.call(this, config);
+            }
+
+            if (Ext.isString(config)) {
+                config = Ext.ComponentManager.get(config);
+            }
+            Ext.applyIf(config, defaults);
+        }
+
+        return config;
+    },
+
+    
+    lookupComponent : function(comp) {
+        return Ext.isString(comp) ? Ext.ComponentManager.get(comp) : this.createComponent(comp);
+    },
+
+    
+    createComponent : function(config, defaultType) {
+        
+        
+        
+        
+        
+        
+
+        return Ext.ComponentManager.create(config, defaultType || this.defaultType);
+    },
+
+    
+    getComponentId : function(comp) {
+        return comp.getItemId();
+    },
+
+    
+    add : function() {
+        var me = this,
+            args = Array.prototype.slice.call(arguments),
+            hasMultipleArgs,
+            items,
+            results = [],
+            i,
+            ln,
+            item,
+            index = -1,
+            cmp;
+
+        if (typeof args[0] == 'number') {
+            index = args.shift();
+        }
+
+        hasMultipleArgs = args.length > 1;
+        if (hasMultipleArgs || Ext.isArray(args[0])) {
+
+            items = hasMultipleArgs ? args : args[0];
+            
+            me.suspendLayout = true;
+            for (i = 0, ln = items.length; i < ln; i++) {
+                item = items[i];
+
+
+                if (index != -1) {
+                    item = me.add(index + i, item);
+                } else {
+                    item = me.add(item);
+                }
+                results.push(item);
+            }
+            
+            me.suspendLayout = false;
+            me.doLayout();
+            return results;
+        }
+
+        cmp = me.prepareItems(args[0], true)[0];
+
+        
+        
+        
+        if (cmp.floating) {
+            cmp.onAdded(me, index);
+        } else {
+            index = (index !== -1) ? index : me.items.length;
+            if (me.fireEvent('beforeadd', me, cmp, index) !== false && me.onBeforeAdd(cmp) !== false) {
+                me.items.insert(index, cmp);
+                cmp.onAdded(me, index);
+                me.onAdd(cmp, index);
+                me.fireEvent('add', me, cmp, index);
+            }
+            me.doLayout();
+        }
+        return cmp;
+    },
+
+    onAdd : Ext.emptyFn,
+    onRemove : Ext.emptyFn,
+
+    
+    insert : function(index, comp) {
+        return this.add(index, comp);
+    },
+
+    
+    move : function(fromIdx, toIdx) {
+        var items = this.items,
+            item;
+        item = items.removeAt(fromIdx);
+        if (item === false) {
+            return false;
+        }
+        items.insert(toIdx, item);
+        this.doLayout();
+        return item;
+    },
+
+    
+    onBeforeAdd : function(item) {
+        var me = this;
+
+        if (item.ownerCt) {
+            item.ownerCt.remove(item, false);
+        }
+
+        if (me.border === false || me.border === 0) {
+            item.border = (item.border === true);
+        }
+    },
+
+    
+    remove : function(comp, autoDestroy) {
+        var me = this,
+            c = me.getComponent(comp);
+
+        if (c && me.fireEvent('beforeremove', me, c) !== false) {
+            me.doRemove(c, autoDestroy);
+            me.fireEvent('remove', me, c);
+        }
+
+        return c;
+    },
+
+    
+    doRemove : function(component, autoDestroy) {
+        var me = this,
+            layout = me.layout,
+            hasLayout = layout && me.rendered;
+
+        me.items.remove(component);
+        component.onRemoved();
+
+        if (hasLayout) {
+            layout.onRemove(component);
+        }
+
+        me.onRemove(component, autoDestroy);
+
+        if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
+            component.destroy();
+        }
+
+        if (hasLayout && !autoDestroy) {
+            layout.afterRemove(component);
+        }
+
+        if (!me.destroying) {
+            me.doLayout();
+        }
+    },
+
+    
+    removeAll : function(autoDestroy) {
+        var me = this,
+            removeItems = me.items.items.slice(),
+            items = [],
+            i = 0,
+            len = removeItems.length,
+            item;
+
+        
+        me.suspendLayout = true;
+        for (; i < len; i++) {
+            item = removeItems[i];
+            me.remove(item, autoDestroy);
+
+            if (item.ownerCt !== me) {
+                items.push(item);
+            }
+        }
+
+        
+        me.suspendLayout = false;
+        if (len) {
+            me.doLayout();
+        }
+        return items;
+    },
+
+    
+    
+    
+    
+    
+    
+    
+    
+    getRefItems : function(deep) {
+        var me = this,
+            items = me.items.items,
+            len = items.length,
+            i = 0,
+            item,
+            result = [];
+
+        for (; i < len; i++) {
+            item = items[i];
+            result.push(item);
+            if (deep && item.getRefItems) {
+                result.push.apply(result, item.getRefItems(true));
+            }
+        }
+
+        
+        
+        if (me.floatingItems && me.floatingItems.accessList) {
+            result.push.apply(result, me.floatingItems.accessList);
+        }
+
+        return result;
+    },
+
+    
+    cascade : function(fn, scope, origArgs){
+        var me = this,
+            cs = me.items ? me.items.items : [],
+            len = cs.length,
+            i = 0,
+            c,
+            args = origArgs ? origArgs.concat(me) : [me],
+            componentIndex = args.length - 1;
+
+        if (fn.apply(scope || me, args) !== false) {
+            for(; i < len; i++){
+                c = cs[i];
+                if (c.cascade) {
+                    c.cascade(fn, scope, origArgs);
+                } else {
+                    args[componentIndex] = c;
+                    fn.apply(scope || cs, args);
+                }
+            }
+        }
+        return this;
+    },
+
+    
+    getComponent : function(comp) {
+        if (Ext.isObject(comp)) {
+            comp = comp.getItemId();
+        }
+
+        return this.items.get(comp);
+    },
+
+    
+    query : function(selector) {
+        selector = selector || '*';
+        return Ext.ComponentQuery.query(selector, this);
+    },
+
+    
+    child : function(selector) {
+        selector = selector || '';
+        return this.query('> ' + selector)[0] || null;
+    },
+
+    
+    down : function(selector) {
+        return this.query(selector)[0] || null;
+    },
+
+    
+    show : function() {
+        this.callParent(arguments);
+        this.performDeferredLayouts();
+        return this;
+    },
+
+    
+    
+    performDeferredLayouts: function() {
+        var layoutCollection = this.layoutOnShow,
+            ln = layoutCollection.getCount(),
+            i = 0,
+            needsLayout,
+            item;
+
+        for (; i < ln; i++) {
+            item = layoutCollection.get(i);
+            needsLayout = item.needsLayout;
+
+            if (Ext.isObject(needsLayout)) {
+                item.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
+            }
+        }
+        layoutCollection.clear();
+    },
+
+    //@private
+
+    
+    onEnable: function() {
+        Ext.Array.each(this.query('[isFormField]'), function(item) {
+            if (item.resetDisable) {
+                item.enable();
+                delete item.resetDisable;
+            }
+        });
+        this.callParent();
+    },
+
+    
+    
+    onDisable: function() {
+        Ext.Array.each(this.query('[isFormField]'), function(item) {
+            if (item.resetDisable !== false && !item.disabled) {
+                item.disable();
+                item.resetDisable = true;
+            }
+        });
+        this.callParent();
+    },
+
+    
+    beforeLayout: function() {
+        return true;
+    },
+
+    
+    beforeDestroy : function() {
+        var me = this,
+            items = me.items,
+            c;
+
+        if (items) {
+            while ((c = items.first())) {
+                me.doRemove(c, true);
+            }
+        }
+
+        Ext.destroy(
+            me.layout
+        );
+        me.callParent();
+    }
+});
+
+
+Ext.define('Ext.container.Container', {
+    extend: 'Ext.container.AbstractContainer',
+    alias: 'widget.container',
+    alternateClassName: 'Ext.Container',
+
+    
+    getChildByElement: function(el) {
+        var item,
+            itemEl,
+            i = 0,
+            it = this.items.items,
+            ln = it.length;
+
+        el = Ext.getDom(el);
+        for (; i < ln; i++) {
+            item = it[i];
+            itemEl = item.getEl();
+            if ((itemEl.dom === el) || itemEl.contains(el)) {
+                return item;
+            }
+        }
+        return null;
+    }
+});
+
+
+Ext.define('Ext.toolbar.Fill', {
+    extend: 'Ext.Component',
+    alias: 'widget.tbfill',
+    alternateClassName: 'Ext.Toolbar.Fill',
+    isFill : true,
+    flex: 1
+});
+
+Ext.define('Ext.toolbar.Item', {
+    extend: 'Ext.Component',
+    alias: 'widget.tbitem',
+    alternateClassName: 'Ext.Toolbar.Item',
+    enable:Ext.emptyFn,
+    disable:Ext.emptyFn,
+    focus:Ext.emptyFn
+    
+});
+
+Ext.define('Ext.toolbar.Separator', {
+    extend: 'Ext.toolbar.Item',
+    alias: 'widget.tbseparator',
+    alternateClassName: 'Ext.Toolbar.Separator',
+    baseCls: Ext.baseCSSPrefix + 'toolbar-separator',
+    focusable: false
+});
+
+Ext.define('Ext.menu.Manager', {
+    singleton: true,
+    requires: [
+        'Ext.util.MixedCollection',
+        'Ext.util.KeyMap'
+    ],
+    alternateClassName: 'Ext.menu.MenuMgr',
+
+    uses: ['Ext.menu.Menu'],
+
+    menus: {},
+    groups: {},
+    attached: false,
+    lastShow: new Date(),
+
+    init: function() {
+        var me = this;
+        
+        me.active = Ext.create('Ext.util.MixedCollection');
+        Ext.getDoc().addKeyListener(27, function() {
+            if (me.active.length > 0) {
+                me.hideAll();
+            }
+        }, me);
+    },
+
+    
+    hideAll: function() {
+        var active = this.active,
+            c;
+        if (active && active.length > 0) {
+            c = active.clone();
+            c.each(function(m) {
+                m.hide();
+            });
+            return true;
+        }
+        return false;
+    },
+
+    onHide: function(m) {
+        var me = this,
+            active = me.active;
+        active.remove(m);
+        if (active.length < 1) {
+            Ext.getDoc().un('mousedown', me.onMouseDown, me);
+            me.attached = false;
+        }
+    },
+
+    onShow: function(m) {
+        var me = this,
+            active   = me.active,
+            last     = active.last(),
+            attached = me.attached,
+            menuEl   = m.getEl(),
+            zIndex;
+
+        me.lastShow = new Date();
+        active.add(m);
+        if (!attached) {
+            Ext.getDoc().on('mousedown', me.onMouseDown, me);
+            me.attached = true;
+        }
+        m.toFront();
+    },
+
+    onBeforeHide: function(m) {
+        if (m.activeChild) {
+            m.activeChild.hide();
+        }
+        if (m.autoHideTimer) {
+            clearTimeout(m.autoHideTimer);
+            delete m.autoHideTimer;
+        }
+    },
+
+    onBeforeShow: function(m) {
+        var active = this.active,
+            parentMenu = m.parentMenu;
+            
+        active.remove(m);
+        if (!parentMenu && !m.allowOtherMenus) {
+            this.hideAll();
+        }
+        else if (parentMenu && parentMenu.activeChild && m != parentMenu.activeChild) {
+            parentMenu.activeChild.hide();
+        }
+    },
+
+    
+    onMouseDown: function(e) {
+        var me = this,
+            active = me.active,
+            lastShow = me.lastShow,
+            target = e.target;
+
+        if (Ext.Date.getElapsed(lastShow) > 50 && active.length > 0 && !e.getTarget('.' + Ext.baseCSSPrefix + 'menu')) {
+            me.hideAll();
+            
+            
+            if (Ext.isIE && Ext.fly(target).focusable()) {
+                target.focus();
+            }
+        }
+    },
+
+    
+    register: function(menu) {
+        var me = this;
+
+        if (!me.active) {
+            me.init();
+        }
+
+        if (menu.floating) {
+            me.menus[menu.id] = menu;
+            menu.on({
+                beforehide: me.onBeforeHide,
+                hide: me.onHide,
+                beforeshow: me.onBeforeShow,
+                show: me.onShow,
+                scope: me
+            });
+        }
+    },
+
+    
+    get: function(menu) {
+        var menus = this.menus;
+        
+        if (typeof menu == 'string') { 
+            if (!menus) {  
+                return null;
+            }
+            return menus[menu];
+        } else if (menu.isMenu) {  
+            return menu;
+        } else if (Ext.isArray(menu)) { 
+            return Ext.create('Ext.menu.Menu', {items:menu});
+        } else { 
+            return Ext.ComponentManager.create(menu, 'menu');
+        }
+    },
+
+    
+    unregister: function(menu) {
+        var me = this,
+            menus = me.menus,
+            active = me.active;
+
+        delete menus[menu.id];
+        active.remove(menu);
+        menu.un({
+            beforehide: me.onBeforeHide,
+            hide: me.onHide,
+            beforeshow: me.onBeforeShow,
+            show: me.onShow,
+            scope: me
+        });
+    },
+
+    
+    registerCheckable: function(menuItem) {
+        var groups  = this.groups,
+            groupId = menuItem.group;
+
+        if (groupId) {
+            if (!groups[groupId]) {
+                groups[groupId] = [];
+            }
+
+            groups[groupId].push(menuItem);
+        }
+    },
+
+    
+    unregisterCheckable: function(menuItem) {
+        var groups  = this.groups,
+            groupId = menuItem.group;
+
+        if (groupId) {
+            Ext.Array.remove(groups[groupId], menuItem);
+        }
+    },
+
+    onCheckChange: function(menuItem, state) {
+        var groups  = this.groups,
+            groupId = menuItem.group,
+            i       = 0,
+            group, ln, curr;
+
+        if (groupId && state) {
+            group = groups[groupId];
+            ln = group.length;
+            for (; i < ln; i++) {
+                curr = group[i];
+                if (curr != menuItem) {
+                    curr.setChecked(false);
+                }
+            }
+        }
+    }
+});
+
+Ext.define('Ext.layout.component.Button', {
+
+    
+
+    alias: ['layout.button'],
+
+    extend: 'Ext.layout.component.Component',
+
+    
+
+    type: 'button',
+
+    cellClsRE: /-btn-(tl|br)\b/,
+    htmlRE: /<.*>/,
+
+    beforeLayout: function() {
+        return this.callParent(arguments) || this.lastText !== this.owner.text;
+    },
+
+    
+    onLayout: function(width, height) {
+        var me = this,
+            isNum = Ext.isNumber,
+            owner = me.owner,
+            ownerEl = owner.el,
+            btnEl = owner.btnEl,
+            btnInnerEl = owner.btnInnerEl,
+            btnIconEl = owner.btnIconEl,
+            sizeIconEl = (owner.icon || owner.iconCls) && (owner.iconAlign == "top" || owner.iconAlign == "bottom"),
+            minWidth = owner.minWidth,
+            maxWidth = owner.maxWidth,
+            ownerWidth, btnFrameWidth, metrics;
+
+        me.getTargetInfo();
+        me.callParent(arguments);
+
+        btnInnerEl.unclip();
+        me.setTargetSize(width, height);
+
+        if (!isNum(width)) {
+            
+            
+            
+            if (owner.text && (Ext.isIE6 || Ext.isIE7) && Ext.isStrict && btnEl && btnEl.getWidth() > 20) {
+                btnFrameWidth = me.btnFrameWidth;
+                metrics = Ext.util.TextMetrics.measure(btnInnerEl, owner.text);
+                ownerEl.setWidth(metrics.width + btnFrameWidth + me.adjWidth);
+                btnEl.setWidth(metrics.width + btnFrameWidth);
+                btnInnerEl.setWidth(metrics.width + btnFrameWidth);
+
+                if (sizeIconEl) {
+                    btnIconEl.setWidth(metrics.width + btnFrameWidth);
+                }
+            } else {
+                
+                ownerEl.setWidth(null);
+                btnEl.setWidth(null);
+                btnInnerEl.setWidth(null);
+                btnIconEl.setWidth(null);
+            }
+
+            
+            if (minWidth || maxWidth) {
+                ownerWidth = ownerEl.getWidth();
+                if (minWidth && (ownerWidth < minWidth)) {
+                    me.setTargetSize(minWidth, height);
+                }
+                else if (maxWidth && (ownerWidth > maxWidth)) {
+                    btnInnerEl.clip();
+                    me.setTargetSize(maxWidth, height);
+                }
+            }
+        }
+
+        this.lastText = owner.text;
+    },
+
+    setTargetSize: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            isNum = Ext.isNumber,
+            btnInnerEl = owner.btnInnerEl,
+            btnWidth = (isNum(width) ? width - me.adjWidth : width),
+            btnHeight = (isNum(height) ? height - me.adjHeight : height),
+            btnFrameHeight = me.btnFrameHeight,
+            text = owner.getText(),
+            textHeight;
+
+        me.callParent(arguments);
+        me.setElementSize(owner.btnEl, btnWidth, btnHeight);
+        me.setElementSize(btnInnerEl, btnWidth, btnHeight);
+        if (btnHeight >= 0) {
+            btnInnerEl.setStyle('line-height', btnHeight - btnFrameHeight + 'px');
+        }
+
+        
+        
+        
+        
+        
+        if (text && this.htmlRE.test(text)) {
+            btnInnerEl.setStyle('line-height', 'normal');
+            textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
+            btnInnerEl.setStyle('padding-top', me.btnFrameTop + Math.max(btnInnerEl.getHeight() - btnFrameHeight - textHeight, 0) / 2 + 'px');
+            me.setElementSize(btnInnerEl, btnWidth, btnHeight);
+        }
+    },
+
+    getTargetInfo: function() {
+        var me = this,
+            owner = me.owner,
+            ownerEl = owner.el,
+            frameSize = me.frameSize,
+            frameBody = owner.frameBody,
+            btnWrap = owner.btnWrap,
+            innerEl = owner.btnInnerEl;
+
+        if (!('adjWidth' in me)) {
+            Ext.apply(me, {
+                
+                adjWidth: frameSize.left + frameSize.right + ownerEl.getBorderWidth('lr') + ownerEl.getPadding('lr') +
+                          btnWrap.getPadding('lr') + (frameBody ? frameBody.getFrameWidth('lr') : 0),
+                adjHeight: frameSize.top + frameSize.bottom + ownerEl.getBorderWidth('tb') + ownerEl.getPadding('tb') +
+                           btnWrap.getPadding('tb') + (frameBody ? frameBody.getFrameWidth('tb') : 0),
+                btnFrameWidth: innerEl.getFrameWidth('lr'),
+                btnFrameHeight: innerEl.getFrameWidth('tb'),
+                btnFrameTop: innerEl.getFrameWidth('t')
+            });
+        }
+
+        return me.callParent();
+    }
+});
+
+Ext.define('Ext.button.Button', {
+
+    
+    alias: 'widget.button',
+    extend: 'Ext.Component',
+
+    requires: [
+        'Ext.menu.Manager',
+        'Ext.util.ClickRepeater',
+        'Ext.layout.component.Button',
+        'Ext.util.TextMetrics',
+        'Ext.util.KeyMap'
+    ],
+
+    alternateClassName: 'Ext.Button',
+    
+
+    isButton: true,
+    componentLayout: 'button',
+
+    
+    hidden: false,
+
+    
+    disabled: false,
+
+    
+    pressed: false,
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    enableToggle: false,
+
+    
+
+    
+
+    
+    menuAlign: 'tl-bl?',
+
+    
+    textAlign: 'center',
+
+    
+
+    
+
+    
+    type: 'button',
+
+    
+    clickEvent: 'click',
+
+    
+    preventDefault: true,
+
+    
+    handleMouseEvents: true,
+
+    
+    tooltipType: 'qtip',
+
+    
+    baseCls: Ext.baseCSSPrefix + 'btn',
+
+    
+    pressedCls: 'pressed',
+
+    
+    overCls: 'over',
+
+    
+    focusCls: 'focus',
+
+    
+    menuActiveCls: 'menu-active',
+
+    
+
+    
+
+    
+
+    ariaRole: 'button',
+
+    
+    renderTpl:
+        '<em id="{id}-btnWrap" class="{splitCls}">' +
+            '<tpl if="href">' +
+                '<a id="{id}-btnEl" href="{href}" target="{target}"<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="link">' +
+                    '<span id="{id}-btnInnerEl" class="{baseCls}-inner">' +
+                        '{text}' +
+                    '</span>' +
+                        '<span id="{id}-btnIconEl" class="{baseCls}-icon"></span>' +
+                '</a>' +
+            '</tpl>' +
+            '<tpl if="!href">' +
+                '<button id="{id}-btnEl" type="{type}" hidefocus="true"' +
+                    
+                    
+                    '<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="button" autocomplete="off">' +
+                    '<span id="{id}-btnInnerEl" class="{baseCls}-inner" style="{innerSpanStyle}">' +
+                        '{text}' +
+                    '</span>' +
+                    '<span id="{id}-btnIconEl" class="{baseCls}-icon {iconCls}">&#160;</span>' +
+                '</button>' +
+            '</tpl>' +
+        '</em>' ,
+
+    
+    scale: 'small',
+
+    
+    allowedScales: ['small', 'medium', 'large'],
+
+    
+
+    
+    iconAlign: 'left',
+
+    
+    arrowAlign: 'right',
+
+    
+    arrowCls: 'arrow',
+
+    
+
+    
+
+    
+
+    
+
+    maskOnDisable: false,
+
+    
+    initComponent: function() {
+        var me = this;
+        me.callParent(arguments);
+
+        me.addEvents(
+            
+            'click',
+
+            
+            'toggle',
+
+            
+            'mouseover',
+
+            
+            'mouseout',
+
+            
+            'menushow',
+
+            
+            'menuhide',
+
+            
+            'menutriggerover',
+
+            
+            'menutriggerout'
+        );
+
+        if (me.menu) {
+            
+            me.split = true;
+
+            
+            me.menu = Ext.menu.Manager.get(me.menu);
+            me.menu.ownerCt = me;
+        }
+
+        
+        if (me.url) {
+            me.href = me.url;
+        }
+
+        
+        if (me.href && !me.hasOwnProperty('preventDefault')) {
+            me.preventDefault = false;
+        }
+
+        if (Ext.isString(me.toggleGroup)) {
+            me.enableToggle = true;
+        }
+
+    },
+
+    
+    initAria: function() {
+        this.callParent();
+        var actionEl = this.getActionEl();
+        if (this.menu) {
+            actionEl.dom.setAttribute('aria-haspopup', true);
+        }
+    },
+
+    
+    getActionEl: function() {
+        return this.btnEl;
+    },
+
+    
+    getFocusEl: function() {
+        return this.btnEl;
+    },
+
+    
+    setButtonCls: function() {
+        var me = this,
+            cls = [],
+            btnIconEl = me.btnIconEl,
+            hide = 'x-hide-display';
+
+        if (me.useSetClass) {
+            if (!Ext.isEmpty(me.oldCls)) {
+                me.removeClsWithUI(me.oldCls);
+                me.removeClsWithUI(me.pressedCls);
+            }
+
+            
+            if (me.iconCls || me.icon) {
+                if (me.text) {
+                    cls.push('icon-text-' + me.iconAlign);
+                } else {
+                    cls.push('icon');
+                }
+                if (btnIconEl) {
+                    btnIconEl.removeCls(hide);
+                }
+            } else {
+                if (me.text) {
+                    cls.push('noicon');
+                }
+                if (btnIconEl) {
+                    btnIconEl.addCls(hide);
+                }
+            }
+
+            me.oldCls = cls;
+            me.addClsWithUI(cls);
+            me.addClsWithUI(me.pressed ? me.pressedCls : null);
+        }
+    },
+
+    
+    onRender: function(ct, position) {
+        
+        var me = this,
+            repeater, btn;
+
+        
+        Ext.applyIf(me.renderData, me.getTemplateArgs());
+
+        me.addChildEls('btnEl', 'btnWrap', 'btnInnerEl', 'btnIconEl');
+
+        if (me.scale) {
+            me.ui = me.ui + '-' + me.scale;
+        }
+
+        
+        me.callParent(arguments);
+
+        
+        if (me.split && me.arrowTooltip) {
+            me.arrowEl.dom.setAttribute(me.getTipAttr(), me.arrowTooltip);
+        }
+
+        
+        me.mon(me.btnEl, {
+            scope: me,
+            focus: me.onFocus,
+            blur : me.onBlur
+        });
+
+        
+        btn = me.el;
+
+        if (me.icon) {
+            me.setIcon(me.icon);
+        }
+
+        if (me.iconCls) {
+            me.setIconCls(me.iconCls);
+        }
+
+        if (me.tooltip) {
+            me.setTooltip(me.tooltip, true);
+        }
+
+        if (me.textAlign) {
+            me.setTextAlign(me.textAlign);
+        }
+
+        
+        if (me.handleMouseEvents) {
+            me.mon(btn, {
+                scope: me,
+                mouseover: me.onMouseOver,
+                mouseout: me.onMouseOut,
+                mousedown: me.onMouseDown
+            });
+
+            if (me.split) {
+                me.mon(btn, {
+                    mousemove: me.onMouseMove,
+                    scope: me
+                });
+            }
+        }
+
+        
+        if (me.menu) {
+            me.mon(me.menu, {
+                scope: me,
+                show: me.onMenuShow,
+                hide: me.onMenuHide
+            });
+
+            me.keyMap = Ext.create('Ext.util.KeyMap', me.el, {
+                key: Ext.EventObject.DOWN,
+                handler: me.onDownKey,
+                scope: me
+            });
+        }
+
+        
+        if (me.repeat) {
+            repeater = Ext.create('Ext.util.ClickRepeater', btn, Ext.isObject(me.repeat) ? me.repeat: {});
+            me.mon(repeater, 'click', me.onRepeatClick, me);
+        } else {
+            me.mon(btn, me.clickEvent, me.onClick, me);
+        }
+
+        
+        Ext.ButtonToggleManager.register(me);
+    },
+
+    
+    getTemplateArgs: function() {
+        var me = this,
+            persistentPadding = me.getPersistentBtnPadding(),
+            innerSpanStyle = '';
+
+        
+        if (Math.max.apply(Math, persistentPadding) > 0) {
+            innerSpanStyle = 'margin:' + Ext.Array.map(persistentPadding, function(pad) {
+                return -pad + 'px';
+            }).join(' ');
+        }
+
+        return {
+            href     : me.getHref(),
+            target   : me.target || '_blank',
+            type     : me.type,
+            splitCls : me.getSplitCls(),
+            cls      : me.cls,
+            iconCls  : me.iconCls || '',
+            text     : me.text || '&#160;',
+            tabIndex : me.tabIndex,
+            innerSpanStyle: innerSpanStyle
+        };
+    },
+
+    
+    getHref: function() {
+        var me = this,
+            params = Ext.apply({}, me.baseParams);
+
+        
+        params = Ext.apply(params, me.params);
+        return me.href ? Ext.urlAppend(me.href, Ext.Object.toQueryString(params)) : false;
+    },
+
+    
+    setParams: function(params) {
+        this.params = params;
+        this.btnEl.dom.href = this.getHref();
+    },
+
+    getSplitCls: function() {
+        var me = this;
+        return me.split ? (me.baseCls + '-' + me.arrowCls) + ' ' + (me.baseCls + '-' + me.arrowCls + '-' + me.arrowAlign) : '';
+    },
+
+    
+    afterRender: function() {
+        var me = this;
+        me.useSetClass = true;
+        me.setButtonCls();
+        me.doc = Ext.getDoc();
+        this.callParent(arguments);
+    },
+
+    
+    setIconCls: function(cls) {
+        var me = this,
+            btnIconEl = me.btnIconEl,
+            oldCls = me.iconCls;
+            
+        me.iconCls = cls;
+        if (btnIconEl) {
+            
+            btnIconEl.removeCls(oldCls);
+            btnIconEl.addCls(cls || '');
+            me.setButtonCls();
+        }
+        return me;
+    },
+
+    
+    setTooltip: function(tooltip, initial) {
+        var me = this;
+
+        if (me.rendered) {
+            if (!initial) {
+                me.clearTip();
+            }
+            if (Ext.isObject(tooltip)) {
+                Ext.tip.QuickTipManager.register(Ext.apply({
+                    target: me.btnEl.id
+                },
+                tooltip));
+                me.tooltip = tooltip;
+            } else {
+                me.btnEl.dom.setAttribute(me.getTipAttr(), tooltip);
+            }
+        } else {
+            me.tooltip = tooltip;
+        }
+        return me;
+    },
+
+    
+    setTextAlign: function(align) {
+        var me = this,
+            btnEl = me.btnEl;
+
+        if (btnEl) {
+            btnEl.removeCls(me.baseCls + '-' + me.textAlign);
+            btnEl.addCls(me.baseCls + '-' + align);
+        }
+        me.textAlign = align;
+        return me;
+    },
+
+    getTipAttr: function(){
+        return this.tooltipType == 'qtip' ? 'data-qtip' : 'title';
+    },
+
+    
+    getRefItems: function(deep){
+        var menu = this.menu,
+            items;
+        
+        if (menu) {
+            items = menu.getRefItems(deep);
+            items.unshift(menu);
+        }
+        return items || [];
+    },
+
+    
+    clearTip: function() {
+        if (Ext.isObject(this.tooltip)) {
+            Ext.tip.QuickTipManager.unregister(this.btnEl);
+        }
+    },
+
+    
+    beforeDestroy: function() {
+        var me = this;
+        if (me.rendered) {
+            me.clearTip();
+        }
+        if (me.menu && me.destroyMenu !== false) {
+            Ext.destroy(me.menu);
+        }
+        Ext.destroy(me.btnInnerEl, me.repeater);
+        me.callParent();
+    },
+
+    
+    onDestroy: function() {
+        var me = this;
+        if (me.rendered) {
+            me.doc.un('mouseover', me.monitorMouseOver, me);
+            me.doc.un('mouseup', me.onMouseUp, me);
+            delete me.doc;
+            Ext.ButtonToggleManager.unregister(me);
+
+            Ext.destroy(me.keyMap);
+            delete me.keyMap;
+        }
+        me.callParent();
+    },
+
+    
+    setHandler: function(handler, scope) {
+        this.handler = handler;
+        this.scope = scope;
+        return this;
+    },
+
+    
+    setText: function(text) {
+        var me = this;
+        me.text = text;
+        if (me.el) {
+            me.btnInnerEl.update(text || '&#160;');
+            me.setButtonCls();
+        }
+        me.doComponentLayout();
+        return me;
+    },
+
+    
+    setIcon: function(icon) {
+        var me = this,
+            iconEl = me.btnIconEl;
+            
+        me.icon = icon;
+        if (iconEl) {
+            iconEl.setStyle('background-image', icon ? 'url(' + icon + ')': '');
+            me.setButtonCls();
+        }
+        return me;
+    },
+
+    
+    getText: function() {
+        return this.text;
+    },
+
+    
+    toggle: function(state, suppressEvent) {
+        var me = this;
+        state = state === undefined ? !me.pressed : !!state;
+        if (state !== me.pressed) {
+            if (me.rendered) {
+                me[state ? 'addClsWithUI': 'removeClsWithUI'](me.pressedCls);
+            }
+            me.btnEl.dom.setAttribute('aria-pressed', state);
+            me.pressed = state;
+            if (!suppressEvent) {
+                me.fireEvent('toggle', me, state);
+                Ext.callback(me.toggleHandler, me.scope || me, [me, state]);
+            }
+        }
+        return me;
+    },
+    
+    maybeShowMenu: function(){
+        var me = this;
+        if (me.menu && !me.hasVisibleMenu() && !me.ignoreNextClick) {
+            me.showMenu();
+        }
+    },
+
+    
+    showMenu: function() {
+        var me = this;
+        if (me.rendered && me.menu) {
+            if (me.tooltip && me.getTipAttr() != 'title') {
+                Ext.tip.QuickTipManager.getQuickTip().cancelShow(me.btnEl);
+            }
+            if (me.menu.isVisible()) {
+                me.menu.hide();
+            }
+
+            me.menu.showBy(me.el, me.menuAlign);
+        }
+        return me;
+    },
+
+    
+    hideMenu: function() {
+        if (this.hasVisibleMenu()) {
+            this.menu.hide();
+        }
+        return this;
+    },
+
+    
+    hasVisibleMenu: function() {
+        var menu = this.menu;
+        return menu && menu.rendered && menu.isVisible();
+    },
+
+    
+    onRepeatClick: function(repeat, e) {
+        this.onClick(e);
+    },
+
+    
+    onClick: function(e) {
+        var me = this;
+        if (me.preventDefault || (me.disabled && me.getHref()) && e) {
+            e.preventDefault();
+        }
+        if (e.button !== 0) {
+            return;
+        }
+        if (!me.disabled) {
+            me.doToggle();
+            me.maybeShowMenu();
+            me.fireHandler(e);
+        }
+    },
+    
+    fireHandler: function(e){
+        var me = this,
+            handler = me.handler;
+            
+        me.fireEvent('click', me, e);
+        if (handler) {
+            handler.call(me.scope || me, me, e);
+        }
+        me.onBlur();
+    },
+    
+    doToggle: function(){
+        var me = this;
+        if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) {
+            me.toggle();
+        }
+    },
+
+    
+    onMouseOver: function(e) {
+        var me = this;
+        if (!me.disabled && !e.within(me.el, true, true)) {
+            me.onMouseEnter(e);
+        }
+    },
+
+    
+    onMouseOut: function(e) {
+        var me = this;
+        if (!e.within(me.el, true, true)) {
+            if (me.overMenuTrigger) {
+                me.onMenuTriggerOut(e);
+            }
+            me.onMouseLeave(e);
+        }
+    },
+
+    
+    onMouseMove: function(e) {
+        var me = this,
+            el = me.el,
+            over = me.overMenuTrigger,
+            overlap, btnSize;
+
+        if (me.split) {
+            if (me.arrowAlign === 'right') {
+                overlap = e.getX() - el.getX();
+                btnSize = el.getWidth();
+            } else {
+                overlap = e.getY() - el.getY();
+                btnSize = el.getHeight();
+            }
+
+            if (overlap > (btnSize - me.getTriggerSize())) {
+                if (!over) {
+                    me.onMenuTriggerOver(e);
+                }
+            } else {
+                if (over) {
+                    me.onMenuTriggerOut(e);
+                }
+            }
+        }
+    },
+
+    
+    getTriggerSize: function() {
+        var me = this,
+            size = me.triggerSize,
+            side, sideFirstLetter, undef;
+
+        if (size === undef) {
+            side = me.arrowAlign;
+            sideFirstLetter = side.charAt(0);
+            size = me.triggerSize = me.el.getFrameWidth(sideFirstLetter) + me.btnWrap.getFrameWidth(sideFirstLetter) + (me.frameSize && me.frameSize[side] || 0);
+        }
+        return size;
+    },
+
+    
+    onMouseEnter: function(e) {
+        var me = this;
+        me.addClsWithUI(me.overCls);
+        me.fireEvent('mouseover', me, e);
+    },
+
+    
+    onMouseLeave: function(e) {
+        var me = this;
+        me.removeClsWithUI(me.overCls);
+        me.fireEvent('mouseout', me, e);
+    },
+
+    
+    onMenuTriggerOver: function(e) {
+        var me = this;
+        me.overMenuTrigger = true;
+        me.fireEvent('menutriggerover', me, me.menu, e);
+    },
+
+    
+    onMenuTriggerOut: function(e) {
+        var me = this;
+        delete me.overMenuTrigger;
+        me.fireEvent('menutriggerout', me, me.menu, e);
+    },
+
+    
+    enable : function(silent) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        me.removeClsWithUI('disabled');
+
+        return me;
+    },
+
+    
+    disable : function(silent) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        me.addClsWithUI('disabled');
+        me.removeClsWithUI(me.overCls);
+
+        return me;
+    },
+
+    
+    setScale: function(scale) {
+        var me = this,
+            ui = me.ui.replace('-' + me.scale, '');
+
+        
+        if (!Ext.Array.contains(me.allowedScales, scale)) {
+            throw('#setScale: scale must be an allowed scale (' + me.allowedScales.join(', ') + ')');
+        }
+
+        me.scale = scale;
+        me.setUI(ui);
+    },
+
+    
+    setUI: function(ui) {
+        var me = this;
+
+        
+        if (me.scale && !ui.match(me.scale)) {
+            ui = ui + '-' + me.scale;
+        }
+
+        me.callParent([ui]);
+
+        
+        
+    },
+
+    
+    onFocus: function(e) {
+        var me = this;
+        if (!me.disabled) {
+            me.addClsWithUI(me.focusCls);
+        }
+    },
+
+    
+    onBlur: function(e) {
+        var me = this;
+        me.removeClsWithUI(me.focusCls);
+    },
+
+    
+    onMouseDown: function(e) {
+        var me = this;
+        if (!me.disabled && e.button === 0) {
+            me.addClsWithUI(me.pressedCls);
+            me.doc.on('mouseup', me.onMouseUp, me);
+        }
+    },
+    
+    onMouseUp: function(e) {
+        var me = this;
+        if (e.button === 0) {
+            if (!me.pressed) {
+                me.removeClsWithUI(me.pressedCls);
+            }
+            me.doc.un('mouseup', me.onMouseUp, me);
+        }
+    },
+    
+    onMenuShow: function(e) {
+        var me = this;
+        me.ignoreNextClick = 0;
+        me.addClsWithUI(me.menuActiveCls);
+        me.fireEvent('menushow', me, me.menu);
+    },
+
+    
+    onMenuHide: function(e) {
+        var me = this;
+        me.removeClsWithUI(me.menuActiveCls);
+        me.ignoreNextClick = Ext.defer(me.restoreClick, 250, me);
+        me.fireEvent('menuhide', me, me.menu);
+    },
+
+    
+    restoreClick: function() {
+        this.ignoreNextClick = 0;
+    },
+
+    
+    onDownKey: function() {
+        var me = this;
+
+        if (!me.disabled) {
+            if (me.menu) {
+                me.showMenu();
+            }
+        }
+    },
+
+    
+    getPersistentBtnPadding: function() {
+        var cls = Ext.button.Button,
+            padding = cls.persistentPadding,
+            btn, leftTop, btnEl, btnInnerEl;
+
+        if (!padding) {
+            padding = cls.persistentPadding = [0, 0, 0, 0]; 
+
+            if (!Ext.isIE) { 
+                
+                btn = Ext.create('Ext.button.Button', {
+                    renderTo: Ext.getBody(),
+                    text: 'test',
+                    style: 'position:absolute;top:-999px;'
+                });
+                btnEl = btn.btnEl;
+                btnInnerEl = btn.btnInnerEl;
+                btnEl.setSize(null, null); 
+
+                leftTop = btnInnerEl.getOffsetsTo(btnEl);
+                padding[0] = leftTop[1];
+                padding[1] = btnEl.getWidth() - btnInnerEl.getWidth() - leftTop[0];
+                padding[2] = btnEl.getHeight() - btnInnerEl.getHeight() - leftTop[1];
+                padding[3] = leftTop[0];
+
+                btn.destroy();
+            }
+        }
+
+        return padding;
+    }
+
+}, function() {
+    var groups = {};
+
+    function toggleGroup(btn, state) {
+        var g, i, l;
+        if (state) {
+            g = groups[btn.toggleGroup];
+            for (i = 0, l = g.length; i < l; i++) {
+                if (g[i] !== btn) {
+                    g[i].toggle(false);
+                }
+            }
+        }
+    }
+
+    
+    Ext.ButtonToggleManager = {
+        register: function(btn) {
+            if (!btn.toggleGroup) {
+                return;
+            }
+            var group = groups[btn.toggleGroup];
+            if (!group) {
+                group = groups[btn.toggleGroup] = [];
+            }
+            group.push(btn);
+            btn.on('toggle', toggleGroup);
+        },
+
+        unregister: function(btn) {
+            if (!btn.toggleGroup) {
+                return;
+            }
+            var group = groups[btn.toggleGroup];
+            if (group) {
+                Ext.Array.remove(group, btn);
+                btn.un('toggle', toggleGroup);
+            }
+        },
+
+        
+        getPressed: function(group) {
+            var g = groups[group],
+                i = 0,
+                len;
+            if (g) {
+                for (len = g.length; i < len; i++) {
+                    if (g[i].pressed === true) {
+                        return g[i];
+                    }
+                }
+            }
+            return null;
+        }
+    };
+});
+
+
+Ext.define('Ext.layout.container.boxOverflow.Menu', {
+
+    
+
+    extend: 'Ext.layout.container.boxOverflow.None',
+    requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
+    alternateClassName: 'Ext.layout.boxOverflow.Menu',
+    
+    
+
+    
+
+    
+    noItemsMenuText : '<div class="' + Ext.baseCSSPrefix + 'toolbar-no-items">(None)</div>',
+
+    constructor: function(layout) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        
+        layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);
+
+        me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
+        
+        me.menuItems = [];
+    },
+    
+    onRemove: function(comp){
+        Ext.Array.remove(this.menuItems, comp);
+    },
+
+    handleOverflow: function(calculations, targetSize) {
+        var me = this,
+            layout = me.layout,
+            methodName = 'get' + layout.parallelPrefixCap,
+            newSize = {},
+            posArgs = [null, null];
+
+        me.callParent(arguments);
+        this.createMenu(calculations, targetSize);
+        newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
+        newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();
+
+        
+        
+        posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
+        me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);
+
+        return { targetSize: newSize };
+    },
+
+    
+    clearOverflow: function(calculations, targetSize) {
+        var me = this,
+            newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
+            items = me.menuItems,
+            i = 0,
+            length = items.length,
+            item;
+
+        me.hideTrigger();
+        for (; i < length; i++) {
+            items[i].show();
+        }
+        items.length = 0;
+
+        return targetSize ? {
+            targetSize: {
+                height: targetSize.height,
+                width : newWidth
+            }
+        } : null;
+    },
+
+    
+    showTrigger: function() {
+        this.menuTrigger.show();
+    },
+
+    
+    hideTrigger: function() {
+        if (this.menuTrigger !== undefined) {
+            this.menuTrigger.hide();
+        }
+    },
+
+    
+    beforeMenuShow: function(menu) {
+        var me = this,
+            items = me.menuItems,
+            i = 0,
+            len   = items.length,
+            item,
+            prev;
+
+        var needsSep = function(group, prev){
+            return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator);
+        };
+
+        me.clearMenu();
+        menu.removeAll();
+
+        for (; i < len; i++) {
+            item = items[i];
+
+            
+            if (!i && (item instanceof Ext.toolbar.Separator)) {
+                continue;
+            }
+            if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
+                menu.add('-');
+            }
+
+            me.addComponentToMenu(menu, item);
+            prev = item;
+        }
+
+        
+        if (menu.items.length < 1) {
+            menu.add(me.noItemsMenuText);
+        }
+    },
+    
+    
+    createMenuConfig : function(component, hideOnClick) {
+        var config = Ext.apply({}, component.initialConfig),
+            group  = component.toggleGroup;
+
+        Ext.copyTo(config, component, [
+            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
+        ]);
+
+        Ext.apply(config, {
+            text       : component.overflowText || component.text,
+            hideOnClick: hideOnClick,
+            destroyMenu: false
+        });
+
+        if (group || component.enableToggle) {
+            Ext.apply(config, {
+                group  : group,
+                checked: component.pressed,
+                listeners: {
+                    checkchange: function(item, checked){
+                        component.toggle(checked);
+                    }
+                }
+            });
+        }
+
+        delete config.ownerCt;
+        delete config.xtype;
+        delete config.id;
+        return config;
+    },
+
+    
+    addComponentToMenu : function(menu, component) {
+        var me = this;
+        if (component instanceof Ext.toolbar.Separator) {
+            menu.add('-');
+        } else if (component.isComponent) {
+            if (component.isXType('splitbutton')) {
+                menu.add(me.createMenuConfig(component, true));
+
+            } else if (component.isXType('button')) {
+                menu.add(me.createMenuConfig(component, !component.menu));
+
+            } else if (component.isXType('buttongroup')) {
+                component.items.each(function(item){
+                     me.addComponentToMenu(menu, item);
+                });
+            } else {
+                menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
+            }
+        }
+    },
+
+    
+    clearMenu : function() {
+        var menu = this.moreMenu;
+        if (menu && menu.items) {
+            menu.items.each(function(item) {
+                if (item.menu) {
+                    delete item.menu;
+                }
+            });
+        }
+    },
+
+    
+    createMenu: function(calculations, targetSize) {
+        var me = this,
+            layout = me.layout,
+            startProp = layout.parallelBefore,
+            sizeProp = layout.parallelPrefix,
+            available = targetSize[sizeProp],
+            boxes = calculations.boxes,
+            i = 0,
+            len = boxes.length,
+            box;
+
+        if (!me.menuTrigger) {
+            me.createInnerElements();
+
+            
+            me.menu = Ext.create('Ext.menu.Menu', {
+                listeners: {
+                    scope: me,
+                    beforeshow: me.beforeMenuShow
+                }
+            });
+
+            
+            me.menuTrigger = Ext.create('Ext.button.Button', {
+                ownerCt : me.layout.owner, 
+                iconCls : me.layout.owner.menuTriggerCls,
+                ui      : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
+                menu    : me.menu,
+                getSplitCls: function() { return '';},
+                renderTo: me.afterCt
+            });
+        }
+        me.showTrigger();
+        available -= me.afterCt.getWidth();
+
+        
+        
+        me.menuItems.length = 0;
+        for (; i < len; i++) {
+            box = boxes[i];
+            if (box[startProp] + box[sizeProp] > available) {
+                me.menuItems.push(box.component);
+                box.component.hide();
+            }
+        }
+    },
+
+    
+    createInnerElements: function() {
+        var me = this,
+            target = me.layout.getRenderTarget();
+
+        if (!this.afterCt) {
+            target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
+            this.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
+        }
+    },
+
+    
+    destroy: function() {
+        Ext.destroy(this.menu, this.menuTrigger);
+    }
+});
+
+Ext.define('Ext.util.Region', {
+
+    
+
+    requires: ['Ext.util.Offset'],
+
+    statics: {
+        
+        getRegion: function(el) {
+            return Ext.fly(el).getPageBox(true);
+        },
+
+        
+        from: function(o) {
+            return new this(o.top, o.right, o.bottom, o.left);
+        }
+    },
+
+    
+
+    
+    constructor : function(t, r, b, l) {
+        var me = this;
+        me.y = me.top = me[1] = t;
+        me.right = r;
+        me.bottom = b;
+        me.x = me.left = me[0] = l;
+    },
+
+    
+    contains : function(region) {
+        var me = this;
+        return (region.x >= me.x &&
+                region.right <= me.right &&
+                region.y >= me.y &&
+                region.bottom <= me.bottom);
+
+    },
+
+    
+    intersect : function(region) {
+        var me = this,
+            t = Math.max(me.y, region.y),
+            r = Math.min(me.right, region.right),
+            b = Math.min(me.bottom, region.bottom),
+            l = Math.max(me.x, region.x);
+
+        if (b > t && r > l) {
+            return new this.self(t, r, b, l);
+        }
+        else {
+            return false;
+        }
+    },
+
+    
+    union : function(region) {
+        var me = this,
+            t = Math.min(me.y, region.y),
+            r = Math.max(me.right, region.right),
+            b = Math.max(me.bottom, region.bottom),
+            l = Math.min(me.x, region.x);
+
+        return new this.self(t, r, b, l);
+    },
+
+    
+    constrainTo : function(r) {
+        var me = this,
+            constrain = Ext.Number.constrain;
+        me.top = me.y = constrain(me.top, r.y, r.bottom);
+        me.bottom = constrain(me.bottom, r.y, r.bottom);
+        me.left = me.x = constrain(me.left, r.x, r.right);
+        me.right = constrain(me.right, r.x, r.right);
+        return me;
+    },
+
+    
+    adjust : function(t, r, b, l) {
+        var me = this;
+        me.top = me.y += t;
+        me.left = me.x += l;
+        me.right += r;
+        me.bottom += b;
+        return me;
+    },
+
+    
+    getOutOfBoundOffset: function(axis, p) {
+        if (!Ext.isObject(axis)) {
+            if (axis == 'x') {
+                return this.getOutOfBoundOffsetX(p);
+            } else {
+                return this.getOutOfBoundOffsetY(p);
+            }
+        } else {
+            p = axis;
+            var d = Ext.create('Ext.util.Offset');
+            d.x = this.getOutOfBoundOffsetX(p.x);
+            d.y = this.getOutOfBoundOffsetY(p.y);
+            return d;
+        }
+
+    },
+
+    
+    getOutOfBoundOffsetX: function(p) {
+        if (p <= this.x) {
+            return this.x - p;
+        } else if (p >= this.right) {
+            return this.right - p;
+        }
+
+        return 0;
+    },
+
+    
+    getOutOfBoundOffsetY: function(p) {
+        if (p <= this.y) {
+            return this.y - p;
+        } else if (p >= this.bottom) {
+            return this.bottom - p;
+        }
+
+        return 0;
+    },
+
+    
+    isOutOfBound: function(axis, p) {
+        if (!Ext.isObject(axis)) {
+            if (axis == 'x') {
+                return this.isOutOfBoundX(p);
+            } else {
+                return this.isOutOfBoundY(p);
+            }
+        } else {
+            p = axis;
+            return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y));
+        }
+    },
+
+    
+    isOutOfBoundX: function(p) {
+        return (p < this.x || p > this.right);
+    },
+
+    
+    isOutOfBoundY: function(p) {
+        return (p < this.y || p > this.bottom);
+    },
+
+    
+    restrict: function(axis, p, factor) {
+        if (Ext.isObject(axis)) {
+            var newP;
+
+            factor = p;
+            p = axis;
+
+            if (p.copy) {
+                newP = p.copy();
+            }
+            else {
+                newP = {
+                    x: p.x,
+                    y: p.y
+                };
+            }
+
+            newP.x = this.restrictX(p.x, factor);
+            newP.y = this.restrictY(p.y, factor);
+            return newP;
+        } else {
+            if (axis == 'x') {
+                return this.restrictX(p, factor);
+            } else {
+                return this.restrictY(p, factor);
+            }
+        }
+    },
+
+    
+    restrictX : function(p, factor) {
+        if (!factor) {
+            factor = 1;
+        }
+
+        if (p <= this.x) {
+            p -= (p - this.x) * factor;
+        }
+        else if (p >= this.right) {
+            p -= (p - this.right) * factor;
+        }
+        return p;
+    },
+
+    
+    restrictY : function(p, factor) {
+        if (!factor) {
+            factor = 1;
+        }
+
+        if (p <= this.y) {
+            p -= (p - this.y) * factor;
+        }
+        else if (p >= this.bottom) {
+            p -= (p - this.bottom) * factor;
+        }
+        return p;
+    },
+
+    
+    getSize: function() {
+        return {
+            width: this.right - this.x,
+            height: this.bottom - this.y
+        };
+    },
+
+    
+    copy: function() {
+        return new this.self(this.y, this.right, this.bottom, this.x);
+    },
+
+    
+    copyFrom: function(p) {
+        var me = this;
+        me.top = me.y = me[1] = p.y;
+        me.right = p.right;
+        me.bottom = p.bottom;
+        me.left = me.x = me[0] = p.x;
+
+        return this;
+    },
+
+    
+    toString: function() {
+        return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]";
+    },
+
+    
+    translateBy: function(x, y) {
+        if (arguments.length == 1) {
+            y = x.y;
+            x = x.x;
+        }
+        var me = this;
+        me.top = me.y += y;
+        me.right += x;
+        me.bottom += y;
+        me.left = me.x += x;
+
+        return me;
+    },
+
+    
+    round: function() {
+        var me = this;
+        me.top = me.y = Math.round(me.y);
+        me.right = Math.round(me.right);
+        me.bottom = Math.round(me.bottom);
+        me.left = me.x = Math.round(me.x);
+
+        return me;
+    },
+
+    
+    equals: function(region) {
+        return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left);
+    }
+});
+
+
+
+
+
+Ext.define('Ext.dd.DragDropManager', {
+    singleton: true,
+
+    requires: ['Ext.util.Region'],
+
+    uses: ['Ext.tip.QuickTipManager'],
+
+    
+    alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
+
+    
+    ids: {},
+
+    
+    handleIds: {},
+
+    
+    dragCurrent: null,
+
+    
+    dragOvers: {},
+
+    
+    deltaX: 0,
+
+    
+    deltaY: 0,
+
+    
+    preventDefault: true,
+
+    
+    stopPropagation: true,
+
+    
+    initialized: false,
+
+    
+    locked: false,
+
+    
+    init: function() {
+        this.initialized = true;
+    },
+
+    
+    POINT: 0,
+
+    
+    INTERSECT: 1,
+
+    
+    mode: 0,
+
+    
+    _execOnAll: function(sMethod, args) {
+        for (var i in this.ids) {
+            for (var j in this.ids[i]) {
+                var oDD = this.ids[i][j];
+                if (! this.isTypeOfDD(oDD)) {
+                    continue;
+                }
+                oDD[sMethod].apply(oDD, args);
+            }
+        }
+    },
+
+    
+    _onLoad: function() {
+
+        this.init();
+
+        var Event = Ext.EventManager;
+        Event.on(document, "mouseup",   this.handleMouseUp, this, true);
+        Event.on(document, "mousemove", this.handleMouseMove, this, true);
+        Event.on(window,   "unload",    this._onUnload, this, true);
+        Event.on(window,   "resize",    this._onResize, this, true);
+        
+
+    },
+
+    
+    _onResize: function(e) {
+        this._execOnAll("resetConstraints", []);
+    },
+
+    
+    lock: function() { this.locked = true; },
+
+    
+    unlock: function() { this.locked = false; },
+
+    
+    isLocked: function() { return this.locked; },
+
+    
+    locationCache: {},
+
+    
+    useCache: true,
+
+    
+    clickPixelThresh: 3,
+
+    
+    clickTimeThresh: 350,
+
+    
+    dragThreshMet: false,
+
+    
+    clickTimeout: null,
+
+    
+    startX: 0,
+
+    
+    startY: 0,
+
+    
+    regDragDrop: function(oDD, sGroup) {
+        if (!this.initialized) { this.init(); }
+
+        if (!this.ids[sGroup]) {
+            this.ids[sGroup] = {};
+        }
+        this.ids[sGroup][oDD.id] = oDD;
+    },
+
+    
+    removeDDFromGroup: function(oDD, sGroup) {
+        if (!this.ids[sGroup]) {
+            this.ids[sGroup] = {};
+        }
+
+        var obj = this.ids[sGroup];
+        if (obj && obj[oDD.id]) {
+            delete obj[oDD.id];
+        }
+    },
+
+    
+    _remove: function(oDD) {
+        for (var g in oDD.groups) {
+            if (g && this.ids[g] && this.ids[g][oDD.id]) {
+                delete this.ids[g][oDD.id];
+            }
+        }
+        delete this.handleIds[oDD.id];
+    },
+
+    
+    regHandle: function(sDDId, sHandleId) {
+        if (!this.handleIds[sDDId]) {
+            this.handleIds[sDDId] = {};
+        }
+        this.handleIds[sDDId][sHandleId] = sHandleId;
+    },
+
+    
+    isDragDrop: function(id) {
+        return ( this.getDDById(id) ) ? true : false;
+    },
+
+    
+    getRelated: function(p_oDD, bTargetsOnly) {
+        var oDDs = [];
+        for (var i in p_oDD.groups) {
+            for (var j in this.ids[i]) {
+                var dd = this.ids[i][j];
+                if (! this.isTypeOfDD(dd)) {
+                    continue;
+                }
+                if (!bTargetsOnly || dd.isTarget) {
+                    oDDs[oDDs.length] = dd;
+                }
+            }
+        }
+
+        return oDDs;
+    },
+
+    
+    isLegalTarget: function (oDD, oTargetDD) {
+        var targets = this.getRelated(oDD, true);
+        for (var i=0, len=targets.length;i<len;++i) {
+            if (targets[i].id == oTargetDD.id) {
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+    
+    isTypeOfDD: function (oDD) {
+        return (oDD && oDD.__ygDragDrop);
+    },
+
+    
+    isHandle: function(sDDId, sHandleId) {
+        return ( this.handleIds[sDDId] &&
+                        this.handleIds[sDDId][sHandleId] );
+    },
+
+    
+    getDDById: function(id) {
+        for (var i in this.ids) {
+            if (this.ids[i][id]) {
+                return this.ids[i][id];
+            }
+        }
+        return null;
+    },
+
+    
+    handleMouseDown: function(e, oDD) {
+        if(Ext.tip.QuickTipManager){
+            Ext.tip.QuickTipManager.ddDisable();
+        }
+        if(this.dragCurrent){
+            
+            
+            this.handleMouseUp(e);
+        }
+
+        this.currentTarget = e.getTarget();
+        this.dragCurrent = oDD;
+
+        var el = oDD.getEl();
+
+        
+        this.startX = e.getPageX();
+        this.startY = e.getPageY();
+
+        this.deltaX = this.startX - el.offsetLeft;
+        this.deltaY = this.startY - el.offsetTop;
+
+        this.dragThreshMet = false;
+
+        this.clickTimeout = setTimeout(
+                function() {
+                    var DDM = Ext.dd.DragDropManager;
+                    DDM.startDrag(DDM.startX, DDM.startY);
+                },
+                this.clickTimeThresh );
+    },
+
+    
+    startDrag: function(x, y) {
+        clearTimeout(this.clickTimeout);
+        if (this.dragCurrent) {
+            this.dragCurrent.b4StartDrag(x, y);
+            this.dragCurrent.startDrag(x, y);
+        }
+        this.dragThreshMet = true;
+    },
+
+    
+    handleMouseUp: function(e) {
+
+        if(Ext.tip && Ext.tip.QuickTipManager){
+            Ext.tip.QuickTipManager.ddEnable();
+        }
+        if (! this.dragCurrent) {
+            return;
+        }
+
+        clearTimeout(this.clickTimeout);
+
+        if (this.dragThreshMet) {
+            this.fireEvents(e, true);
+        } else {
+        }
+
+        this.stopDrag(e);
+
+        this.stopEvent(e);
+    },
+
+    
+    stopEvent: function(e){
+        if(this.stopPropagation) {
+            e.stopPropagation();
+        }
+
+        if (this.preventDefault) {
+            e.preventDefault();
+        }
+    },
+
+    
+    stopDrag: function(e) {
+        
+        if (this.dragCurrent) {
+            if (this.dragThreshMet) {
+                this.dragCurrent.b4EndDrag(e);
+                this.dragCurrent.endDrag(e);
+            }
+
+            this.dragCurrent.onMouseUp(e);
+        }
+
+        this.dragCurrent = null;
+        this.dragOvers = {};
+    },
+
+    
+    handleMouseMove: function(e) {
+        if (! this.dragCurrent) {
+            return true;
+        }
+        
+
+        
+        if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
+            this.stopEvent(e);
+            return this.handleMouseUp(e);
+        }
+
+        if (!this.dragThreshMet) {
+            var diffX = Math.abs(this.startX - e.getPageX());
+            var diffY = Math.abs(this.startY - e.getPageY());
+            if (diffX > this.clickPixelThresh ||
+                        diffY > this.clickPixelThresh) {
+                this.startDrag(this.startX, this.startY);
+            }
+        }
+
+        if (this.dragThreshMet) {
+            this.dragCurrent.b4Drag(e);
+            this.dragCurrent.onDrag(e);
+            if(!this.dragCurrent.moveOnly){
+                this.fireEvents(e, false);
+            }
+        }
+
+        this.stopEvent(e);
+
+        return true;
+    },
+
+    
+    fireEvents: function(e, isDrop) {
+        var dc = this.dragCurrent;
+
+        
+        
+        if (!dc || dc.isLocked()) {
+            return;
+        }
+
+        var pt = e.getPoint();
+
+        
+        var oldOvers = [];
+
+        var outEvts   = [];
+        var overEvts  = [];
+        var dropEvts  = [];
+        var enterEvts = [];
+
+        
+        
+        for (var i in this.dragOvers) {
+
+            var ddo = this.dragOvers[i];
+
+            if (! this.isTypeOfDD(ddo)) {
+                continue;
+            }
+
+            if (! this.isOverTarget(pt, ddo, this.mode)) {
+                outEvts.push( ddo );
+            }
+
+            oldOvers[i] = true;
+            delete this.dragOvers[i];
+        }
+
+        for (var sGroup in dc.groups) {
+
+            if ("string" != typeof sGroup) {
+                continue;
+            }
+
+            for (i in this.ids[sGroup]) {
+                var oDD = this.ids[sGroup][i];
+                if (! this.isTypeOfDD(oDD)) {
+                    continue;
+                }
+
+                if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
+                    if (this.isOverTarget(pt, oDD, this.mode)) {
+                        
+                        if (isDrop) {
+                            dropEvts.push( oDD );
+                        
+                        } else {
+
+                            
+                            if (!oldOvers[oDD.id]) {
+                                enterEvts.push( oDD );
+                            
+                            } else {
+                                overEvts.push( oDD );
+                            }
+
+                            this.dragOvers[oDD.id] = oDD;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (this.mode) {
+            if (outEvts.length) {
+                dc.b4DragOut(e, outEvts);
+                dc.onDragOut(e, outEvts);
+            }
+
+            if (enterEvts.length) {
+                dc.onDragEnter(e, enterEvts);
+            }
+
+            if (overEvts.length) {
+                dc.b4DragOver(e, overEvts);
+                dc.onDragOver(e, overEvts);
+            }
+
+            if (dropEvts.length) {
+                dc.b4DragDrop(e, dropEvts);
+                dc.onDragDrop(e, dropEvts);
+            }
+
+        } else {
+            
+            var len = 0;
+            for (i=0, len=outEvts.length; i<len; ++i) {
+                dc.b4DragOut(e, outEvts[i].id);
+                dc.onDragOut(e, outEvts[i].id);
+            }
+
+            
+            for (i=0,len=enterEvts.length; i<len; ++i) {
+                
+                dc.onDragEnter(e, enterEvts[i].id);
+            }
+
+            
+            for (i=0,len=overEvts.length; i<len; ++i) {
+                dc.b4DragOver(e, overEvts[i].id);
+                dc.onDragOver(e, overEvts[i].id);
+            }
+
+            
+            for (i=0, len=dropEvts.length; i<len; ++i) {
+                dc.b4DragDrop(e, dropEvts[i].id);
+                dc.onDragDrop(e, dropEvts[i].id);
+            }
+
+        }
+
+        
+        if (isDrop && !dropEvts.length) {
+            dc.onInvalidDrop(e);
+        }
+
+    },
+
+    
+    getBestMatch: function(dds) {
+        var winner = null;
+        
+        
+           
+        
+        
+
+        var len = dds.length;
+
+        if (len == 1) {
+            winner = dds[0];
+        } else {
+            
+            for (var i=0; i<len; ++i) {
+                var dd = dds[i];
+                
+                
+                
+                if (dd.cursorIsOver) {
+                    winner = dd;
+                    break;
+                
+                } else {
+                    if (!winner ||
+                        winner.overlap.getArea() < dd.overlap.getArea()) {
+                        winner = dd;
+                    }
+                }
+            }
+        }
+
+        return winner;
+    },
+
+    
+    refreshCache: function(groups) {
+        for (var sGroup in groups) {
+            if ("string" != typeof sGroup) {
+                continue;
+            }
+            for (var i in this.ids[sGroup]) {
+                var oDD = this.ids[sGroup][i];
+
+                if (this.isTypeOfDD(oDD)) {
+                
+                    var loc = this.getLocation(oDD);
+                    if (loc) {
+                        this.locationCache[oDD.id] = loc;
+                    } else {
+                        delete this.locationCache[oDD.id];
+                        
+                        
+                        
+                    }
+                }
+            }
+        }
+    },
+
+    
+    verifyEl: function(el) {
+        if (el) {
+            var parent;
+            if(Ext.isIE){
+                try{
+                    parent = el.offsetParent;
+                }catch(e){}
+            }else{
+                parent = el.offsetParent;
+            }
+            if (parent) {
+                return true;
+            }
+        }
+
+        return false;
+    },
+
+    
+    getLocation: function(oDD) {
+        if (! this.isTypeOfDD(oDD)) {
+            return null;
+        }
+
+        
+        
+        if (oDD.getRegion) {
+            return oDD.getRegion();
+        }
+
+        var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
+
+        try {
+            pos= Ext.Element.getXY(el);
+        } catch (e) { }
+
+        if (!pos) {
+            return null;
+        }
+
+        x1 = pos[0];
+        x2 = x1 + el.offsetWidth;
+        y1 = pos[1];
+        y2 = y1 + el.offsetHeight;
+
+        t = y1 - oDD.padding[0];
+        r = x2 + oDD.padding[1];
+        b = y2 + oDD.padding[2];
+        l = x1 - oDD.padding[3];
+
+        return Ext.create('Ext.util.Region', t, r, b, l);
+    },
+
+    
+    isOverTarget: function(pt, oTarget, intersect) {
+        
+        var loc = this.locationCache[oTarget.id];
+        if (!loc || !this.useCache) {
+            loc = this.getLocation(oTarget);
+            this.locationCache[oTarget.id] = loc;
+
+        }
+
+        if (!loc) {
+            return false;
+        }
+
+        oTarget.cursorIsOver = loc.contains( pt );
+
+        
+        
+        
+        
+        
+        var dc = this.dragCurrent;
+        if (!dc || !dc.getTargetCoord ||
+                (!intersect && !dc.constrainX && !dc.constrainY)) {
+            return oTarget.cursorIsOver;
+        }
+
+        oTarget.overlap = null;
+
+        
+        
+        
+        
+        var pos = dc.getTargetCoord(pt.x, pt.y);
+
+        var el = dc.getDragEl();
+        var curRegion = Ext.create('Ext.util.Region', pos.y,
+                                               pos.x + el.offsetWidth,
+                                               pos.y + el.offsetHeight,
+                                               pos.x );
+
+        var overlap = curRegion.intersect(loc);
+
+        if (overlap) {
+            oTarget.overlap = overlap;
+            return (intersect) ? true : oTarget.cursorIsOver;
+        } else {
+            return false;
+        }
+    },
+
+    
+    _onUnload: function(e, me) {
+        Ext.dd.DragDropManager.unregAll();
+    },
+
+    
+    unregAll: function() {
+
+        if (this.dragCurrent) {
+            this.stopDrag();
+            this.dragCurrent = null;
+        }
+
+        this._execOnAll("unreg", []);
+
+        for (var i in this.elementCache) {
+            delete this.elementCache[i];
+        }
+
+        this.elementCache = {};
+        this.ids = {};
+    },
+
+    
+    elementCache: {},
+
+    
+    getElWrapper: function(id) {
+        var oWrapper = this.elementCache[id];
+        if (!oWrapper || !oWrapper.el) {
+            oWrapper = this.elementCache[id] =
+                new this.ElementWrapper(Ext.getDom(id));
+        }
+        return oWrapper;
+    },
+
+    
+    getElement: function(id) {
+        return Ext.getDom(id);
+    },
+
+    
+    getCss: function(id) {
+        var el = Ext.getDom(id);
+        return (el) ? el.style : null;
+    },
+
+    
+    ElementWrapper: function(el) {
+        
+        this.el = el || null;
+        
+        this.id = this.el && el.id;
+        
+        this.css = this.el && el.style;
+    },
+
+    
+    
+
+    
+    getPosX: function(el) {
+        return Ext.Element.getX(el);
+    },
+
+    
+    getPosY: function(el) {
+        return Ext.Element.getY(el);
+    },
+
+    
+    swapNode: function(n1, n2) {
+        if (n1.swapNode) {
+            n1.swapNode(n2);
+        } else {
+            var p = n2.parentNode;
+            var s = n2.nextSibling;
+
+            if (s == n1) {
+                p.insertBefore(n1, n2);
+            } else if (n2 == n1.nextSibling) {
+                p.insertBefore(n2, n1);
+            } else {
+                n1.parentNode.replaceChild(n2, n1);
+                p.insertBefore(n1, s);
+            }
+        }
+    },
+
+    
+    getScroll: function () {
+        var doc   = window.document,
+            docEl = doc.documentElement,
+            body  = doc.body,
+            top   = 0,
+            left  = 0;
+
+        if (Ext.isGecko4) {
+            top  = window.scrollYOffset;
+            left = window.scrollXOffset;
+        } else {
+            if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
+                top  = docEl.scrollTop;
+                left = docEl.scrollLeft;
+            } else if (body) {
+                top  = body.scrollTop;
+                left = body.scrollLeft;
+            }
+        }
+        return {
+            top: top,
+            left: left
+        };
+    },
+
+    
+    getStyle: function(el, styleProp) {
+        return Ext.fly(el).getStyle(styleProp);
+    },
+
+    
+    getScrollTop: function () {
+        return this.getScroll().top;
+    },
+
+    
+    getScrollLeft: function () {
+        return this.getScroll().left;
+    },
+
+    
+    moveToEl: function (moveEl, targetEl) {
+        var aCoord = Ext.Element.getXY(targetEl);
+        Ext.Element.setXY(moveEl, aCoord);
+    },
+
+    
+    numericSort: function(a, b) {
+        return (a - b);
+    },
+
+    
+    _timeoutCount: 0,
+
+    
+    _addListeners: function() {
+        if ( document ) {
+            this._onLoad();
+        } else {
+            if (this._timeoutCount > 2000) {
+            } else {
+                setTimeout(this._addListeners, 10);
+                if (document && document.body) {
+                    this._timeoutCount += 1;
+                }
+            }
+        }
+    },
+
+    
+    handleWasClicked: function(node, id) {
+        if (this.isHandle(id, node.id)) {
+            return true;
+        } else {
+            
+            var p = node.parentNode;
+
+            while (p) {
+                if (this.isHandle(id, p.id)) {
+                    return true;
+                } else {
+                    p = p.parentNode;
+                }
+            }
+        }
+
+        return false;
+    }
+}, function() {
+    this._addListeners();
+});
+
+
+
+Ext.define('Ext.layout.container.Box', {
+
+    
+
+    alias: ['layout.box'],
+    extend: 'Ext.layout.container.Container',
+    alternateClassName: 'Ext.layout.BoxLayout',
+
+    requires: [
+        'Ext.layout.container.boxOverflow.None',
+        'Ext.layout.container.boxOverflow.Menu',
+        'Ext.layout.container.boxOverflow.Scroller',
+        'Ext.util.Format',
+        'Ext.dd.DragDropManager'
+    ],
+
+    
+
+    
+
+    
+    defaultMargins: {
+        top: 0,
+        right: 0,
+        bottom: 0,
+        left: 0
+    },
+
+    
+    padding: '0',
+    
+    pack: 'start',
+
+    
+    
+
+    type: 'box',
+    scrollOffset: 0,
+    itemCls: Ext.baseCSSPrefix + 'box-item',
+    targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
+    innerCls: Ext.baseCSSPrefix + 'box-inner',
+
+    bindToOwnerCtContainer: true,
+
+    
+    
+    availableSpaceOffset: 0,
+
+    
+    reserveOffset: true,
+
+    
+    shrinkToFit: true,
+
+    
+    clearInnerCtOnLayout: false,
+
+    flexSortFn: function (a, b) {
+        var maxParallelPrefix = 'max' + this.parallelPrefixCap,
+            infiniteValue = Infinity;
+        a = a.component[maxParallelPrefix] || infiniteValue;
+        b = b.component[maxParallelPrefix] || infiniteValue;
+        
+        if (!isFinite(a) && !isFinite(b)) {
+            return false;
+        }
+        return a - b;
+    },
+
+    
+    minSizeSortFn: function(a, b) {
+        return b.available - a.available;
+    },
+
+    constructor: function(config) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        
+        me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
+
+        me.initOverflowHandler();
+    },
+
+    
+    getChildBox: function(child) {
+        child = child.el || this.owner.getComponent(child).el;
+        var size = child.getBox(false, true);
+        return {
+            left: size.left,
+            top: size.top,
+            width: size.width,
+            height: size.height
+        };
+    },
+
+    
+    calculateChildBox: function(child) {
+        var me = this,
+            boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
+            ln = boxes.length,
+            i = 0;
+
+        child = me.owner.getComponent(child);
+        for (; i < ln; i++) {
+            if (boxes[i].component === child) {
+                return boxes[i];
+            }
+        }
+    },
+
+    
+    calculateChildBoxes: function(visibleItems, targetSize) {
+        var me = this,
+            math = Math,
+            mmax = math.max,
+            infiniteValue = Infinity,
+            undefinedValue,
+
+            parallelPrefix = me.parallelPrefix,
+            parallelPrefixCap = me.parallelPrefixCap,
+            perpendicularPrefix = me.perpendicularPrefix,
+            perpendicularPrefixCap = me.perpendicularPrefixCap,
+            parallelMinString = 'min' + parallelPrefixCap,
+            perpendicularMinString = 'min' + perpendicularPrefixCap,
+            perpendicularMaxString = 'max' + perpendicularPrefixCap,
+
+            parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
+            perpendicularSize = targetSize[perpendicularPrefix],
+            padding = me.padding,
+            parallelOffset = padding[me.parallelBefore],
+            paddingParallel = parallelOffset + padding[me.parallelAfter],
+            perpendicularOffset = padding[me.perpendicularLeftTop],
+            paddingPerpendicular =  perpendicularOffset + padding[me.perpendicularRightBottom],
+            availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
+
+            innerCtBorderWidth = me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB),
+
+            isStart = me.pack == 'start',
+            isCenter = me.pack == 'center',
+            isEnd = me.pack == 'end',
+
+            constrain = Ext.Number.constrain,
+            visibleCount = visibleItems.length,
+            nonFlexSize = 0,
+            totalFlex = 0,
+            desiredSize = 0,
+            minimumSize = 0,
+            maxSize = 0,
+            boxes = [],
+            minSizes = [],
+            calculatedWidth,
+
+            i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall,
+            tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff,
+            flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset,
+            perpendicularMargins, stretchSize;
+
+        
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            childPerpendicular = child[perpendicularPrefix];
+            if (!child.flex || !(me.align == 'stretch' || me.align == 'stretchmax')) {
+                if (child.componentLayout.initialized !== true) {
+                    me.layoutItem(child);
+                }
+            }
+
+            childMargins = child.margins;
+            parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
+
+            
+            tmpObj = {
+                component: child,
+                margins: childMargins
+            };
+
+            
+            if (child.flex) {
+                totalFlex += child.flex;
+                childParallel = undefinedValue;
+            }
+            
+            else {
+                if (!(child[parallelPrefix] && childPerpendicular)) {
+                    childSize = child.getSize();
+                }
+                childParallel = child[parallelPrefix] || childSize[parallelPrefix];
+                childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
+            }
+
+            nonFlexSize += parallelMargins + (childParallel || 0);
+            desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
+            minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
+
+            
+            if (typeof childPerpendicular != 'number') {
+                
+                
+                childPerpendicular = child['get' + perpendicularPrefixCap]();
+            }
+
+            
+            
+            maxSize = mmax(maxSize, mmax(childPerpendicular, child[perpendicularMinString]||0) + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
+
+            tmpObj[parallelPrefix] = childParallel || undefinedValue;
+            tmpObj.dirtySize = child.componentLayout.lastComponentSize ? (tmpObj[parallelPrefix] !== child.componentLayout.lastComponentSize[parallelPrefix]) : false;
+            tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
+            boxes.push(tmpObj);
+        }
+
+        
+        if (!me.autoSize) {
+            shortfall = desiredSize - parallelSize;
+            tooNarrow = minimumSize > parallelSize;
+        }
+
+        
+        availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
+
+        if (tooNarrow) {
+            for (i = 0; i < visibleCount; i++) {
+                box = boxes[i];
+                minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
+                box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
+                box[parallelPrefix] = minSize;
+            }
+        }
+        else {
+            
+            
+            if (shortfall > 0) {
+                
+                for (i = 0; i < visibleCount; i++) {
+                    item = visibleItems[i];
+                    minSize = item[parallelMinString] || 0;
+
+                    
+                    
+                    if (item.flex) {
+                        box = boxes[i];
+                        box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
+                        box[parallelPrefix] = minSize;
+                    } else if (me.shrinkToFit) {
+                        minSizes.push({
+                            minSize: minSize,
+                            available: boxes[i][parallelPrefix] - minSize,
+                            index: i
+                        });
+                    }
+                }
+
+                
+                Ext.Array.sort(minSizes, me.minSizeSortFn);
+
+                
+                for (i = 0, length = minSizes.length; i < length; i++) {
+                    itemIndex = minSizes[i].index;
+
+                    if (itemIndex == undefinedValue) {
+                        continue;
+                    }
+                    item = visibleItems[itemIndex];
+                    minSize = minSizes[i].minSize;
+
+                    box = boxes[itemIndex];
+                    oldSize = box[parallelPrefix];
+                    newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
+                    reduction = oldSize - newSize;
+
+                    box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
+                    box[parallelPrefix] = newSize;
+                    shortfall -= reduction;
+                }
+                tooNarrow = (shortfall > 0);
+            }
+            else {
+                remainingSpace = availableSpace;
+                remainingFlex = totalFlex;
+                flexedBoxes = [];
+
+                
+                for (i = 0; i < visibleCount; i++) {
+                    child = visibleItems[i];
+                    if (isStart && child.flex) {
+                        flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
+                    }
+                }
+                
+                
+                
+                Ext.Array.sort(flexedBoxes, me.flexSortFn);
+
+                
+                for (i = 0; i < flexedBoxes.length; i++) {
+                    calcs = flexedBoxes[i];
+                    child = calcs.component;
+                    childMargins = calcs.margins;
+
+                    flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
+
+                    
+                    flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
+
+                    
+                    remainingSpace -= flexedSize;
+                    remainingFlex -= child.flex;
+
+                    calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
+                    calcs[parallelPrefix] = flexedSize;
+                }
+            }
+        }
+
+        if (isCenter) {
+            parallelOffset += availableSpace / 2;
+        }
+        else if (isEnd) {
+            parallelOffset += availableSpace;
+        }
+
+        
+        
+        
+        
+        if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
+
+            calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
+            if (me.owner.frameSize) {
+                calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
+            }
+            
+            availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
+        }
+
+        
+        for (i = 0; i < visibleCount; i++) {
+            child = visibleItems[i];
+            calcs = boxes[i];
+
+            childMargins = calcs.margins;
+
+            perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
+
+            
+            parallelOffset += childMargins[me.parallelBefore];
+
+            calcs[me.parallelBefore] = parallelOffset;
+            calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
+
+            if (me.align == 'stretch') {
+                stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
+                calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
+                calcs[perpendicularPrefix] = stretchSize;
+            }
+            else if (me.align == 'stretchmax') {
+                stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
+                calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
+                calcs[perpendicularPrefix] = stretchSize;
+            }
+            else if (me.align == me.alignCenteringString) {
+                
+                
+                
+                diff = mmax(availPerpendicularSize, maxSize) - innerCtBorderWidth - calcs[perpendicularPrefix];
+                if (diff > 0) {
+                    calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
+                }
+            }
+
+            
+            parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
+        }
+
+        return {
+            boxes: boxes,
+            meta : {
+                calculatedWidth: calculatedWidth,
+                maxSize: maxSize,
+                nonFlexSize: nonFlexSize,
+                desiredSize: desiredSize,
+                minimumSize: minimumSize,
+                shortfall: shortfall,
+                tooNarrow: tooNarrow
+            }
+        };
+    },
+
+    onRemove: function(comp){
+        this.callParent(arguments);
+        if (this.overflowHandler) {
+            this.overflowHandler.onRemove(comp);
+        }
+    },
+
+    
+    initOverflowHandler: function() {
+        var handler = this.overflowHandler;
+
+        if (typeof handler == 'string') {
+            handler = {
+                type: handler
+            };
+        }
+
+        var handlerType = 'None';
+        if (handler && handler.type !== undefined) {
+            handlerType = handler.type;
+        }
+
+        var constructor = Ext.layout.container.boxOverflow[handlerType];
+        if (constructor[this.type]) {
+            constructor = constructor[this.type];
+        }
+
+        this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
+    },
+
+    
+    onLayout: function() {
+        this.callParent();
+        
+        if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
+            this.innerCt.setSize(null, null);
+        }
+
+        var me = this,
+            targetSize = me.getLayoutTargetSize(),
+            items = me.getVisibleItems(),
+            calcs = me.calculateChildBoxes(items, targetSize),
+            boxes = calcs.boxes,
+            meta = calcs.meta,
+            handler, method, results;
+
+        if (me.autoSize && calcs.meta.desiredSize) {
+            targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
+        }
+
+        
+        if (meta.shortfall > 0) {
+            handler = me.overflowHandler;
+            method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
+
+            results = handler[method](calcs, targetSize);
+
+            if (results) {
+                if (results.targetSize) {
+                    targetSize = results.targetSize;
+                }
+
+                if (results.recalculate) {
+                    items = me.getVisibleItems();
+                    calcs = me.calculateChildBoxes(items, targetSize);
+                    boxes = calcs.boxes;
+                }
+            }
+        } else {
+            me.overflowHandler.clearOverflow();
+        }
+
+        
+        me.layoutTargetLastSize = targetSize;
+
+        
+        me.childBoxCache = calcs;
+
+        me.updateInnerCtSize(targetSize, calcs);
+        me.updateChildBoxes(boxes);
+        me.handleTargetOverflow(targetSize);
+    },
+    
+    animCallback: Ext.emptyFn,
+
+    
+    updateChildBoxes: function(boxes) {
+        var me = this,
+            i = 0,
+            length = boxes.length,
+            animQueue = [],
+            dd = Ext.dd.DDM.getDDById(me.innerCt.id), 
+            oldBox, newBox, changed, comp, boxAnim, animCallback;
+
+        for (; i < length; i++) {
+            newBox = boxes[i];
+            comp = newBox.component;
+
+            
+            
+            if (dd && (dd.getDragEl() === comp.el.dom)) {
+                continue;
+            }
+
+            changed = false;
+
+            oldBox = me.getChildBox(comp);
+
+            
+            
+            
+            if (me.animate) {
+                
+                animCallback = me.animate.callback || me.animate;
+                boxAnim = {
+                    layoutAnimation: true,  
+                    target: comp,
+                    from: {},
+                    to: {},
+                    listeners: {}
+                };
+                
+                
+                
+                
+                if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
+                    changed = true;
+                    
+                    boxAnim.to.width = newBox.width;
+                }
+                if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
+                    changed = true;
+                    
+                    boxAnim.to.height = newBox.height;
+                }
+                if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
+                    changed = true;
+                    
+                    boxAnim.to.left = newBox.left;
+                }
+                if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
+                    changed = true;
+                    
+                    boxAnim.to.top = newBox.top;
+                }
+                if (changed) {
+                    animQueue.push(boxAnim);
+                }
+            } else {
+                if (newBox.dirtySize) {
+                    if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
+                        me.setItemSize(comp, newBox.width, newBox.height);
+                    }
+                }
+                
+                if (isNaN(newBox.left) || isNaN(newBox.top)) {
+                    continue;
+                }
+                comp.setPosition(newBox.left, newBox.top);
+            }
+        }
+
+        
+        length = animQueue.length;
+        if (length) {
+
+            
+            
+            var afterAnimate = function(anim) {
+                
+                length -= 1;
+                if (!length) {
+                    me.animCallback(anim);
+                    me.layoutBusy = false;
+                    if (Ext.isFunction(animCallback)) {
+                        animCallback();
+                    }
+                }
+            };
+
+            var beforeAnimate = function() {
+                me.layoutBusy = true;
+            };
+
+            
+            for (i = 0, length = animQueue.length; i < length; i++) {
+                boxAnim = animQueue[i];
+
+                
+                boxAnim.listeners.afteranimate = afterAnimate;
+
+                
+                if (!i) {
+                    boxAnim.listeners.beforeanimate = beforeAnimate;
+                }
+                if (me.animate.duration) {
+                    boxAnim.duration = me.animate.duration;
+                }
+                comp = boxAnim.target;
+                delete boxAnim.target;
+                
+                comp.stopAnimation();
+                comp.animate(boxAnim);
+            }
+        }
+    },
+
+    
+    updateInnerCtSize: function(tSize, calcs) {
+        var me = this,
+            mmax = Math.max,
+            align = me.align,
+            padding = me.padding,
+            width = tSize.width,
+            height = tSize.height,
+            meta = calcs.meta,
+            innerCtWidth,
+            innerCtHeight;
+
+        if (me.direction == 'horizontal') {
+            innerCtWidth = width;
+            innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
+
+            if (align == 'stretch') {
+                innerCtHeight = height;
+            }
+            else if (align == 'middle') {
+                innerCtHeight = mmax(height, innerCtHeight);
+            }
+        } else {
+            innerCtHeight = height;
+            innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
+
+            if (align == 'stretch') {
+                innerCtWidth = width;
+            }
+            else if (align == 'center') {
+                innerCtWidth = mmax(width, innerCtWidth);
+            }
+        }
+        me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
+
+        
+        
+        if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
+            me.owner.el.setWidth(meta.calculatedWidth);
+        }
+
+        if (me.innerCt.dom.scrollTop) {
+            me.innerCt.dom.scrollTop = 0;
+        }
+    },
+
+    
+    handleTargetOverflow: function(previousTargetSize) {
+        var target = this.getTarget(),
+            overflow = target.getStyle('overflow'),
+            newTargetSize;
+
+        if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
+            newTargetSize = this.getLayoutTargetSize();
+            if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
+                this.adjustmentPass = true;
+                this.onLayout();
+                return true;
+            }
+        }
+
+        delete this.adjustmentPass;
+    },
+
+    
+    isValidParent : function(item, target, position) {
+        
+        
+        var itemEl = item.el ? item.el.dom : Ext.getDom(item);
+        return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
+    },
+
+    
+    
+    getRenderTarget: function() {
+        if (!this.innerCt) {
+            
+            this.innerCt = this.getTarget().createChild({
+                cls: this.innerCls,
+                role: 'presentation'
+            });
+            this.padding = Ext.util.Format.parseBox(this.padding);
+        }
+        return this.innerCt;
+    },
+
+    
+    renderItem: function(item, target) {
+        this.callParent(arguments);
+        var me = this,
+            itemEl = item.getEl(),
+            style = itemEl.dom.style,
+            margins = item.margins || item.margin;
+
+        
+        if (margins) {
+            if (Ext.isString(margins) || Ext.isNumber(margins)) {
+                margins = Ext.util.Format.parseBox(margins);
+            } else {
+                Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
+            }
+        } else {
+            margins = Ext.apply({}, me.defaultMargins);
+        }
+
+        
+        margins.top    += itemEl.getMargin('t');
+        margins.right  += itemEl.getMargin('r');
+        margins.bottom += itemEl.getMargin('b');
+        margins.left   += itemEl.getMargin('l');
+        margins.height  = margins.top  + margins.bottom;
+        margins.width   = margins.left + margins.right;
+        style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
+
+        
+        item.margins = margins;
+    },
+
+    
+    destroy: function() {
+        Ext.destroy(this.innerCt, this.overflowHandler);
+        this.callParent(arguments);
+    }
+});
+
+Ext.define('Ext.layout.container.HBox', {
+
+    
+
+    alias: ['layout.hbox'],
+    extend: 'Ext.layout.container.Box',
+    alternateClassName: 'Ext.layout.HBoxLayout',
+
+    
+
+    
+    align: 'top', 
+
+    //@private
+
+    alignCenteringString: 'middle',
+
+    type : 'hbox',
+
+    direction: 'horizontal',
+
+    
+    parallelSizeIndex: 0,
+    perpendicularSizeIndex: 1,
+
+    parallelPrefix: 'width',
+    parallelPrefixCap: 'Width',
+    parallelLT: 'l',
+    parallelRB: 'r',
+    parallelBefore: 'left',
+    parallelBeforeCap: 'Left',
+    parallelAfter: 'right',
+    parallelPosition: 'x',
+
+    perpendicularPrefix: 'height',
+    perpendicularPrefixCap: 'Height',
+    perpendicularLT: 't',
+    perpendicularRB: 'b',
+    perpendicularLeftTop: 'top',
+    perpendicularRightBottom: 'bottom',
+    perpendicularPosition: 'y',
+    configureItem: function(item) {
+        if (item.flex) {
+            item.layoutManagedWidth = 1;
+        } else {
+            item.layoutManagedWidth = 2;
+        }
+
+        if (this.align === 'stretch' || this.align === 'stretchmax') {
+            item.layoutManagedHeight = 1;
+        } else {
+            item.layoutManagedHeight = 2;
+        }
+        this.callParent(arguments);
+    }
+});
+
+Ext.define('Ext.layout.container.VBox', {
+
+    
+
+    alias: ['layout.vbox'],
+    extend: 'Ext.layout.container.Box',
+    alternateClassName: 'Ext.layout.VBoxLayout',
+
+    
+
+    
+    align : 'left', 
+
+    //@private
+
+    alignCenteringString: 'center',
+
+    type: 'vbox',
+
+    direction: 'vertical',
+
+    
+    parallelSizeIndex: 1,
+    perpendicularSizeIndex: 0,
+
+    parallelPrefix: 'height',
+    parallelPrefixCap: 'Height',
+    parallelLT: 't',
+    parallelRB: 'b',
+    parallelBefore: 'top',
+    parallelBeforeCap: 'Top',
+    parallelAfter: 'bottom',
+    parallelPosition: 'y',
+
+    perpendicularPrefix: 'width',
+    perpendicularPrefixCap: 'Width',
+    perpendicularLT: 'l',
+    perpendicularRB: 'r',
+    perpendicularLeftTop: 'left',
+    perpendicularRightBottom: 'right',
+    perpendicularPosition: 'x',
+    configureItem: function(item) {
+        if (item.flex) {
+            item.layoutManagedHeight = 1;
+        } else {
+            item.layoutManagedHeight = 2;
+        }
+
+        if (this.align === 'stretch' || this.align === 'stretchmax') {
+            item.layoutManagedWidth = 1;
+        } else {
+            item.layoutManagedWidth = 2;
+        }
+        this.callParent(arguments);
+    }
+});
+
+Ext.define('Ext.FocusManager', {
+    singleton: true,
+    alternateClassName: 'Ext.FocusMgr',
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: [
+        'Ext.ComponentManager',
+        'Ext.ComponentQuery',
+        'Ext.util.HashMap',
+        'Ext.util.KeyNav'
+    ],
+
+    
+    enabled: false,
+
+    
+
+    focusElementCls: Ext.baseCSSPrefix + 'focus-element',
+
+    focusFrameCls: Ext.baseCSSPrefix + 'focus-frame',
+
+    
+    whitelist: [
+        'textfield'
+    ],
+
+    tabIndexWhitelist: [
+        'a',
+        'button',
+        'embed',
+        'frame',
+        'iframe',
+        'img',
+        'input',
+        'object',
+        'select',
+        'textarea'
+    ],
+
+    constructor: function() {
+        var me = this,
+            CQ = Ext.ComponentQuery;
+
+        me.addEvents(
+            
+            'beforecomponentfocus',
+
+            
+            'componentfocus',
+
+            
+            'disable',
+
+            
+            'enable'
+        );
+
+        
+        
+        me.keyNav = Ext.create('Ext.util.KeyNav', Ext.getDoc(), {
+            disabled: true,
+            scope: me,
+
+            backspace: me.focusLast,
+            enter: me.navigateIn,
+            esc: me.navigateOut,
+            tab: me.navigateSiblings
+
+            
+            
+            
+            
+            
+            
+        });
+
+        me.focusData = {};
+        me.subscribers = Ext.create('Ext.util.HashMap');
+        me.focusChain = {};
+
+        
+        Ext.apply(CQ.pseudos, {
+            focusable: function(cmps) {
+                var len = cmps.length,
+                    results = [],
+                    i = 0,
+                    c,
+
+                    isFocusable = function(x) {
+                        return x && x.focusable !== false && CQ.is(x, '[rendered]:not([destroying]):not([isDestroyed]):not([disabled]){isVisible(true)}{el && c.el.dom && c.el.isVisible()}');
+                    };
+
+                for (; i < len; i++) {
+                    c = cmps[i];
+                    if (isFocusable(c)) {
+                        results.push(c);
+                    }
+                }
+
+                return results;
+            },
+
+            nextFocus: function(cmps, idx, step) {
+                step = step || 1;
+                idx = parseInt(idx, 10);
+
+                var len = cmps.length,
+                    i = idx + step,
+                    c;
+
+                for (; i != idx; i += step) {
+                    if (i >= len) {
+                        i = 0;
+                    } else if (i < 0) {
+                        i = len - 1;
+                    }
+
+                    c = cmps[i];
+                    if (CQ.is(c, ':focusable')) {
+                        return [c];
+                    } else if (c.placeholder && CQ.is(c.placeholder, ':focusable')) {
+                        return [c.placeholder];
+                    }
+                }
+
+                return [];
+            },
+
+            prevFocus: function(cmps, idx) {
+                return this.nextFocus(cmps, idx, -1);
+            },
+
+            root: function(cmps) {
+                var len = cmps.length,
+                    results = [],
+                    i = 0,
+                    c;
+
+                for (; i < len; i++) {
+                    c = cmps[i];
+                    if (!c.ownerCt) {
+                        results.push(c);
+                    }
+                }
+
+                return results;
+            }
+        });
+    },
+
+    
+    addXTypeToWhitelist: function(xtype) {
+        var me = this;
+
+        if (Ext.isArray(xtype)) {
+            Ext.Array.forEach(xtype, me.addXTypeToWhitelist, me);
+            return;
+        }
+
+        if (!Ext.Array.contains(me.whitelist, xtype)) {
+            me.whitelist.push(xtype);
+        }
+    },
+
+    clearComponent: function(cmp) {
+        clearTimeout(this.cmpFocusDelay);
+        if (!cmp.isDestroyed) {
+            cmp.blur();
+        }
+    },
+
+    
+    disable: function() {
+        var me = this;
+
+        if (!me.enabled) {
+            return;
+        }
+
+        delete me.options;
+        me.enabled = false;
+
+        Ext.ComponentManager.all.un('add', me.onComponentCreated, me);
+
+        me.removeDOM();
+
+        
+        me.keyNav.disable();
+
+        
+        me.setFocusAll(false);
+
+        me.fireEvent('disable', me);
+    },
+
+    
+    enable: function(options) {
+        var me = this;
+
+        if (options === true) {
+            options = { focusFrame: true };
+        }
+        me.options = options = options || {};
+
+        if (me.enabled) {
+            return;
+        }
+
+        
+        Ext.ComponentManager.all.on('add', me.onComponentCreated, me);
+
+        me.initDOM(options);
+
+        
+        me.keyNav.enable();
+
+        
+        me.setFocusAll(true, options);
+
+        
+        me.focusEl.focus();
+        delete me.focusedCmp;
+
+        me.enabled = true;
+        me.fireEvent('enable', me);
+    },
+
+    focusLast: function(e) {
+        var me = this;
+
+        if (me.isWhitelisted(me.focusedCmp)) {
+            return true;
+        }
+
+        
+        if (me.previousFocusedCmp) {
+            me.previousFocusedCmp.focus();
+        }
+    },
+
+    getRootComponents: function() {
+        var me = this,
+            CQ = Ext.ComponentQuery,
+            inline = CQ.query(':focusable:root:not([floating])'),
+            floating = CQ.query(':focusable:root[floating]');
+
+        
+        
+        floating.sort(function(a, b) {
+            return a.el.getZIndex() > b.el.getZIndex();
+        });
+
+        return floating.concat(inline);
+    },
+
+    initDOM: function(options) {
+        var me = this,
+            sp = '&#160',
+            cls = me.focusFrameCls;
+
+        if (!Ext.isReady) {
+            Ext.onReady(me.initDOM, me);
+            return;
+        }
+
+        
+        if (!me.focusEl) {
+            me.focusEl = Ext.getBody().createChild({
+                tabIndex: '-1',
+                cls: me.focusElementCls,
+                html: sp
+            });
+        }
+
+        
+        if (!me.focusFrame && options.focusFrame) {
+            me.focusFrame = Ext.getBody().createChild({
+                cls: cls,
+                children: [
+                    { cls: cls + '-top' },
+                    { cls: cls + '-bottom' },
+                    { cls: cls + '-left' },
+                    { cls: cls + '-right' }
+                ],
+                style: 'top: -100px; left: -100px;'
+            });
+            me.focusFrame.setVisibilityMode(Ext.Element.DISPLAY);
+            me.focusFrameWidth = 2;
+            me.focusFrame.hide().setLeftTop(0, 0);
+        }
+    },
+
+    isWhitelisted: function(cmp) {
+        return cmp && Ext.Array.some(this.whitelist, function(x) {
+            return cmp.isXType(x);
+        });
+    },
+
+    navigateIn: function(e) {
+        var me = this,
+            focusedCmp = me.focusedCmp,
+            rootCmps,
+            firstChild;
+
+        if (!focusedCmp) {
+            
+            rootCmps = me.getRootComponents();
+            if (rootCmps.length) {
+                rootCmps[0].focus();
+            }
+        } else {
+            
+            
+            firstChild = Ext.ComponentQuery.query('>:focusable', focusedCmp)[0];
+            if (firstChild) {
+                firstChild.focus();
+            } else {
+                
+                if (Ext.isFunction(focusedCmp.onClick)) {
+                    e.button = 0;
+                    focusedCmp.onClick(e);
+                    focusedCmp.focus();
+                }
+            }
+        }
+    },
+
+    navigateOut: function(e) {
+        var me = this,
+            parent;
+
+        if (!me.focusedCmp || !(parent = me.focusedCmp.up(':focusable'))) {
+            me.focusEl.focus();
+        } else {
+            parent.focus();
+        }
+
+        
+        
+        
+        return true;
+    },
+
+    navigateSiblings: function(e, source, parent) {
+        var me = this,
+            src = source || me,
+            key = e.getKey(),
+            EO = Ext.EventObject,
+            goBack = e.shiftKey || key == EO.LEFT || key == EO.UP,
+            checkWhitelist = key == EO.LEFT || key == EO.RIGHT || key == EO.UP || key == EO.DOWN,
+            nextSelector = goBack ? 'prev' : 'next',
+            idx, next, focusedCmp;
+
+        focusedCmp = (src.focusedCmp && src.focusedCmp.comp) || src.focusedCmp;
+        if (!focusedCmp && !parent) {
+            return;
+        }
+
+        if (checkWhitelist && me.isWhitelisted(focusedCmp)) {
+            return true;
+        }
+
+        parent = parent || focusedCmp.up();
+        if (parent) {
+            idx = focusedCmp ? Ext.Array.indexOf(parent.getRefItems(), focusedCmp) : -1;
+            next = Ext.ComponentQuery.query('>:' + nextSelector + 'Focus(' + idx + ')', parent)[0];
+            if (next && focusedCmp !== next) {
+                next.focus();
+                return next;
+            }
+        }
+    },
+
+    onComponentBlur: function(cmp, e) {
+        var me = this;
+
+        if (me.focusedCmp === cmp) {
+            me.previousFocusedCmp = cmp;
+            delete me.focusedCmp;
+        }
+
+        if (me.focusFrame) {
+            me.focusFrame.hide();
+        }
+    },
+
+    onComponentCreated: function(hash, id, cmp) {
+        this.setFocus(cmp, true, this.options);
+    },
+
+    onComponentDestroy: function(cmp) {
+        this.setFocus(cmp, false);
+    },
+
+    onComponentFocus: function(cmp, e) {
+        var me = this,
+            chain = me.focusChain;
+
+        if (!Ext.ComponentQuery.is(cmp, ':focusable')) {
+            me.clearComponent(cmp);
+
+            
+            
+            
+            
+            if (chain[cmp.id]) {
+                return;
+            }
+
+            
+            var parent = cmp.up();
+            if (parent) {
+                
+                
+                
+                chain[cmp.id] = true;
+                parent.focus();
+            }
+
+            return;
+        }
+
+        
+        me.focusChain = {};
+
+        
+        
+        clearTimeout(me.cmpFocusDelay);
+        if (arguments.length !== 2) {
+            me.cmpFocusDelay = Ext.defer(me.onComponentFocus, 90, me, [cmp, e]);
+            return;
+        }
+
+        if (me.fireEvent('beforecomponentfocus', me, cmp, me.previousFocusedCmp) === false) {
+            me.clearComponent(cmp);
+            return;
+        }
+
+        me.focusedCmp = cmp;
+
+        
+        if (me.shouldShowFocusFrame(cmp)) {
+            var cls = '.' + me.focusFrameCls + '-',
+                ff = me.focusFrame,
+                fw = me.focusFrameWidth,
+                box = cmp.el.getPageBox(),
+
+            
+            
+            
+                bt = box.top,
+                bl = box.left,
+                bw = box.width,
+                bh = box.height,
+                ft = ff.child(cls + 'top'),
+                fb = ff.child(cls + 'bottom'),
+                fl = ff.child(cls + 'left'),
+                fr = ff.child(cls + 'right');
+
+            ft.setWidth(bw).setLeftTop(bl, bt);
+            fb.setWidth(bw).setLeftTop(bl, bt + bh - fw);
+            fl.setHeight(bh - fw - fw).setLeftTop(bl, bt + fw);
+            fr.setHeight(bh - fw - fw).setLeftTop(bl + bw - fw, bt + fw);
+
+            ff.show();
+        }
+
+        me.fireEvent('componentfocus', me, cmp, me.previousFocusedCmp);
+    },
+
+    onComponentHide: function(cmp) {
+        var me = this,
+            CQ = Ext.ComponentQuery,
+            cmpHadFocus = false,
+            focusedCmp,
+            parent;
+
+        if (me.focusedCmp) {
+            focusedCmp = CQ.query('[id=' + me.focusedCmp.id + ']', cmp)[0];
+            cmpHadFocus = me.focusedCmp.id === cmp.id || focusedCmp;
+
+            if (focusedCmp) {
+                me.clearComponent(focusedCmp);
+            }
+        }
+
+        me.clearComponent(cmp);
+
+        if (cmpHadFocus) {
+            parent = CQ.query('^:focusable', cmp)[0];
+            if (parent) {
+                parent.focus();
+            }
+        }
+    },
+
+    removeDOM: function() {
+        var me = this;
+
+        
+        
+        if (me.enabled || me.subscribers.length) {
+            return;
+        }
+
+        Ext.destroy(
+            me.focusEl,
+            me.focusFrame
+        );
+        delete me.focusEl;
+        delete me.focusFrame;
+        delete me.focusFrameWidth;
+    },
+
+    
+    removeXTypeFromWhitelist: function(xtype) {
+        var me = this;
+
+        if (Ext.isArray(xtype)) {
+            Ext.Array.forEach(xtype, me.removeXTypeFromWhitelist, me);
+            return;
+        }
+
+        Ext.Array.remove(me.whitelist, xtype);
+    },
+
+    setFocus: function(cmp, focusable, options) {
+        var me = this,
+            el, dom, data,
+
+            needsTabIndex = function(n) {
+                return !Ext.Array.contains(me.tabIndexWhitelist, n.tagName.toLowerCase())
+                    && n.tabIndex <= 0;
+            };
+
+        options = options || {};
+
+        
+        if (!cmp.rendered) {
+            cmp.on('afterrender', Ext.pass(me.setFocus, arguments, me), me, { single: true });
+            return;
+        }
+
+        el = cmp.getFocusEl();
+        dom = el.dom;
+
+        
+        if ((focusable && !me.focusData[cmp.id]) || (!focusable && me.focusData[cmp.id])) {
+            if (focusable) {
+                data = {
+                    focusFrame: options.focusFrame
+                };
+
+                
+                
+                
+                
+                if (needsTabIndex(dom)) {
+                    data.tabIndex = dom.tabIndex;
+                    dom.tabIndex = -1;
+                }
+
+                el.on({
+                    focus: data.focusFn = Ext.bind(me.onComponentFocus, me, [cmp], 0),
+                    blur: data.blurFn = Ext.bind(me.onComponentBlur, me, [cmp], 0),
+                    scope: me
+                });
+                cmp.on({
+                    hide: me.onComponentHide,
+                    close: me.onComponentHide,
+                    beforedestroy: me.onComponentDestroy,
+                    scope: me
+                });
+
+                me.focusData[cmp.id] = data;
+            } else {
+                data = me.focusData[cmp.id];
+                if ('tabIndex' in data) {
+                    dom.tabIndex = data.tabIndex;
+                }
+                el.un('focus', data.focusFn, me);
+                el.un('blur', data.blurFn, me);
+                cmp.un('hide', me.onComponentHide, me);
+                cmp.un('close', me.onComponentHide, me);
+                cmp.un('beforedestroy', me.onComponentDestroy, me);
+
+                delete me.focusData[cmp.id];
+            }
+        }
+    },
+
+    setFocusAll: function(focusable, options) {
+        var me = this,
+            cmps = Ext.ComponentManager.all.getArray(),
+            len = cmps.length,
+            cmp,
+            i = 0;
+
+        for (; i < len; i++) {
+            me.setFocus(cmps[i], focusable, options);
+        }
+    },
+
+    setupSubscriberKeys: function(container, keys) {
+        var me = this,
+            el = container.getFocusEl(),
+            scope = keys.scope,
+            handlers = {
+                backspace: me.focusLast,
+                enter: me.navigateIn,
+                esc: me.navigateOut,
+                scope: me
+            },
+
+            navSiblings = function(e) {
+                if (me.focusedCmp === container) {
+                    
+                    
+                    
+                    return me.navigateSiblings(e, me, container);
+                } else {
+                    return me.navigateSiblings(e);
+                }
+            };
+
+        Ext.iterate(keys, function(key, cb) {
+            handlers[key] = function(e) {
+                var ret = navSiblings(e);
+
+                if (Ext.isFunction(cb) && cb.call(scope || container, e, ret) === true) {
+                    return true;
+                }
+
+                return ret;
+            };
+        }, me);
+
+        return Ext.create('Ext.util.KeyNav', el, handlers);
+    },
+
+    shouldShowFocusFrame: function(cmp) {
+        var me = this,
+            opts = me.options || {};
+
+        if (!me.focusFrame || !cmp) {
+            return false;
+        }
+
+        
+        if (opts.focusFrame) {
+            return true;
+        }
+
+        if (me.focusData[cmp.id].focusFrame) {
+            return true;
+        }
+
+        return false;
+    },
+
+    
+    subscribe: function(container, options) {
+        var me = this,
+            EA = Ext.Array,
+            data = {},
+            subs = me.subscribers,
+
+            
+            
+            
+            safeSetFocus = function(cmp) {
+                if (cmp.isContainer && !subs.containsKey(cmp.id)) {
+                    EA.forEach(cmp.query('>'), safeSetFocus);
+                    me.setFocus(cmp, true, options);
+                    cmp.on('add', data.onAdd, me);
+                } else if (!cmp.isContainer) {
+                    me.setFocus(cmp, true, options);
+                }
+            };
+
+        
+        if (!container || !container.isContainer) {
+            return;
+        }
+
+        if (!container.rendered) {
+            container.on('afterrender', Ext.pass(me.subscribe, arguments, me), me, { single: true });
+            return;
+        }
+
+        
+        me.initDOM(options);
+
+        
+        data.keyNav = me.setupSubscriberKeys(container, options.keys);
+
+        
+        
+        
+        
+        data.onAdd = function(ct, cmp, idx) {
+            safeSetFocus(cmp);
+        };
+        container.on('beforedestroy', me.unsubscribe, me);
+
+        
+        safeSetFocus(container);
+
+        
+        subs.add(container.id, data);
+    },
+
+    
+    unsubscribe: function(container) {
+        var me = this,
+            EA = Ext.Array,
+            subs = me.subscribers,
+            data,
+
+            
+            
+            
+            safeSetFocus = function(cmp) {
+                if (cmp.isContainer && !subs.containsKey(cmp.id)) {
+                    EA.forEach(cmp.query('>'), safeSetFocus);
+                    me.setFocus(cmp, false);
+                    cmp.un('add', data.onAdd, me);
+                } else if (!cmp.isContainer) {
+                    me.setFocus(cmp, false);
+                }
+            };
+
+        if (!container || !subs.containsKey(container.id)) {
+            return;
+        }
+
+        data = subs.get(container.id);
+        data.keyNav.destroy();
+        container.un('beforedestroy', me.unsubscribe, me);
+        subs.removeAtKey(container.id);
+        safeSetFocus(container);
+        me.removeDOM();
+    }
+});
+
+Ext.define('Ext.toolbar.Toolbar', {
+    extend: 'Ext.container.Container',
+    requires: [
+        'Ext.toolbar.Fill',
+        'Ext.layout.container.HBox',
+        'Ext.layout.container.VBox',
+        'Ext.FocusManager'
+    ],
+    uses: [
+        'Ext.toolbar.Separator'
+    ],
+    alias: 'widget.toolbar',
+    alternateClassName: 'Ext.Toolbar',
+
+    isToolbar: true,
+    baseCls  : Ext.baseCSSPrefix + 'toolbar',
+    ariaRole : 'toolbar',
+
+    defaultType: 'button',
+
+    
+    vertical: false,
+
+    
+
+    
+    enableOverflow: false,
+
+    
+    menuTriggerCls: Ext.baseCSSPrefix + 'toolbar-more-icon',
+    
+    
+    trackMenus: true,
+
+    itemCls: Ext.baseCSSPrefix + 'toolbar-item',
+
+    initComponent: function() {
+        var me = this,
+            keys;
+
+        
+        if (!me.layout && me.enableOverflow) {
+            me.layout = { overflowHandler: 'Menu' };
+        }
+
+        if (me.dock === 'right' || me.dock === 'left') {
+            me.vertical = true;
+        }
+
+        me.layout = Ext.applyIf(Ext.isString(me.layout) ? {
+            type: me.layout
+        } : me.layout || {}, {
+            type: me.vertical ? 'vbox' : 'hbox',
+            align: me.vertical ? 'stretchmax' : 'middle',
+            clearInnerCtOnLayout: true
+        });
+
+        if (me.vertical) {
+            me.addClsWithUI('vertical');
+        }
+
+        
+        if (me.ui === 'footer') {
+            me.ignoreBorderManagement = true;
+        }
+
+        me.callParent();
+
+        
+        me.addEvents('overflowchange');
+
+        
+        keys = me.vertical ? ['up', 'down'] : ['left', 'right'];
+        Ext.FocusManager.subscribe(me, {
+            keys: keys
+        });
+    },
+
+    getRefItems: function(deep) {
+        var me = this,
+            items = me.callParent(arguments),
+            layout = me.layout,
+            handler;
+
+        if (deep && me.enableOverflow) {
+            handler = layout.overflowHandler;
+            if (handler && handler.menu) {
+                items = items.concat(handler.menu.getRefItems(deep));
+            }
+        }
+        return items;
+    },
+
+    
+
+    
+    lookupComponent: function(c) {
+        if (Ext.isString(c)) {
+            var shortcut = Ext.toolbar.Toolbar.shortcuts[c];
+            if (shortcut) {
+                c = {
+                    xtype: shortcut
+                };
+            } else {
+                c = {
+                    xtype: 'tbtext',
+                    text: c
+                };
+            }
+            this.applyDefaults(c);
+        }
+        return this.callParent(arguments);
+    },
+
+    
+    applyDefaults: function(c) {
+        if (!Ext.isString(c)) {
+            c = this.callParent(arguments);
+            var d = this.internalDefaults;
+            if (c.events) {
+                Ext.applyIf(c.initialConfig, d);
+                Ext.apply(c, d);
+            } else {
+                Ext.applyIf(c, d);
+            }
+        }
+        return c;
+    },
+
+    
+    trackMenu: function(item, remove) {
+        if (this.trackMenus && item.menu) {
+            var method = remove ? 'mun' : 'mon',
+                me = this;
+
+            me[method](item, 'mouseover', me.onButtonOver, me);
+            me[method](item, 'menushow', me.onButtonMenuShow, me);
+            me[method](item, 'menuhide', me.onButtonMenuHide, me);
+        }
+    },
+
+    
+    constructButton: function(item) {
+        return item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
+    },
+
+    
+    onBeforeAdd: function(component) {
+        if (component.is('field') || (component.is('button') && this.ui != 'footer')) {
+            component.ui = component.ui + '-toolbar';
+        }
+
+        
+        if (component instanceof Ext.toolbar.Separator) {
+            component.setUI((this.vertical) ? 'vertical' : 'horizontal');
+        }
+
+        this.callParent(arguments);
+    },
+
+    
+    onAdd: function(component) {
+        this.callParent(arguments);
+
+        this.trackMenu(component);
+        if (this.disabled) {
+            component.disable();
+        }
+    },
+
+    
+    onRemove: function(c) {
+        this.callParent(arguments);
+        this.trackMenu(c, true);
+    },
+
+    
+    onButtonOver: function(btn){
+        if (this.activeMenuBtn && this.activeMenuBtn != btn) {
+            this.activeMenuBtn.hideMenu();
+            btn.showMenu();
+            this.activeMenuBtn = btn;
+        }
+    },
+
+    
+    onButtonMenuShow: function(btn) {
+        this.activeMenuBtn = btn;
+    },
+
+    
+    onButtonMenuHide: function(btn) {
+        delete this.activeMenuBtn;
+    }
+}, function() {
+    this.shortcuts = {
+        '-' : 'tbseparator',
+        ' ' : 'tbspacer',
+        '->': 'tbfill'
+    };
+});
+
+Ext.define('Ext.panel.AbstractPanel', {
+
+    
+
+    extend: 'Ext.container.Container',
+
+    requires: ['Ext.util.MixedCollection', 'Ext.Element', 'Ext.toolbar.Toolbar'],
+
+    
+
+    
+    baseCls : Ext.baseCSSPrefix + 'panel',
+
+    
+
+    
+
+    
+
+    
+
+    isPanel: true,
+
+    componentLayout: 'dock',
+
+    
+    defaultDockWeights: { top: 1, left: 3, right: 5, bottom: 7 },
+
+    renderTpl: [
+        '<div id="{id}-body" class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl>',
+            ' {baseCls}-body-{ui}<tpl if="uiCls">',
+                '<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',
+            '</tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>>',
+        '</div>'
+    ],
+
+    
+    
+
+    border: true,
+
+    initComponent : function() {
+        var me = this;
+
+        me.addEvents(
+            
+            'bodyresize'
+            
+            
+            
+            
+        );
+
+        me.addChildEls('body');
+
+        
+        
+
+        if (me.frame && me.border && me.bodyBorder === undefined) {
+            me.bodyBorder = false;
+        }
+        if (me.frame && me.border && (me.bodyBorder === false || me.bodyBorder === 0)) {
+            me.manageBodyBorders = true;
+        }
+
+        me.callParent();
+    },
+
+    
+    initItems : function() {
+        var me = this,
+            items = me.dockedItems;
+
+        me.callParent();
+        me.dockedItems = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
+        if (items) {
+            me.addDocked(items);
+        }
+    },
+
+    
+    getDockedComponent: function(comp) {
+        if (Ext.isObject(comp)) {
+            comp = comp.getItemId();
+        }
+        return this.dockedItems.get(comp);
+    },
+
+    
+    getComponent: function(comp) {
+        var component = this.callParent(arguments);
+        if (component === undefined && !Ext.isNumber(comp)) {
+            
+            component = this.getDockedComponent(comp);
+        }
+        return component;
+    },
+
+    
+    initBodyStyles: function() {
+        var me = this,
+            bodyStyle = me.bodyStyle,
+            styles = [],
+            Element = Ext.Element,
+            prop;
+
+        if (Ext.isFunction(bodyStyle)) {
+            bodyStyle = bodyStyle();
+        }
+        if (Ext.isString(bodyStyle)) {
+            styles = bodyStyle.split(';');
+        } else {
+            for (prop in bodyStyle) {
+                if (bodyStyle.hasOwnProperty(prop)) {
+                    styles.push(prop + ':' + bodyStyle[prop]);
+                }
+            }
+        }
+
+        if (me.bodyPadding !== undefined) {
+            styles.push('padding: ' + Element.unitizeBox((me.bodyPadding === true) ? 5 : me.bodyPadding));
+        }
+        if (me.frame && me.bodyBorder) {
+            if (!Ext.isNumber(me.bodyBorder)) {
+                me.bodyBorder = 1;
+            }
+            styles.push('border-width: ' + Element.unitizeBox(me.bodyBorder));
+        }
+        delete me.bodyStyle;
+        return styles.length ? styles.join(';') : undefined;
+    },
+
+    
+    initBodyCls: function() {
+        var me = this,
+            cls = '',
+            bodyCls = me.bodyCls;
+
+        if (bodyCls) {
+            Ext.each(bodyCls, function(v) {
+                cls += " " + v;
+            });
+            delete me.bodyCls;
+        }
+        return cls.length > 0 ? cls : undefined;
+    },
+
+    
+    initRenderData: function() {
+        return Ext.applyIf(this.callParent(), {
+            bodyStyle: this.initBodyStyles(),
+            bodyCls: this.initBodyCls()
+        });
+    },
+
+    
+    addDocked : function(items, pos) {
+        var me = this,
+            i = 0,
+            item, length;
+
+        items = me.prepareItems(items);
+        length = items.length;
+
+        for (; i < length; i++) {
+            item = items[i];
+            item.dock = item.dock || 'top';
+
+            
+            if (me.border === false) {
+                
+            }
+
+            if (pos !== undefined) {
+                me.dockedItems.insert(pos + i, item);
+            }
+            else {
+                me.dockedItems.add(item);
+            }
+            item.onAdded(me, i);
+            me.onDockedAdd(item);
+        }
+
+        
+        me.componentLayout.childrenChanged = true;
+        if (me.rendered && !me.suspendLayout) {
+            me.doComponentLayout();
+        }
+        return items;
+    },
+
+    
+    onDockedAdd : Ext.emptyFn,
+    onDockedRemove : Ext.emptyFn,
+
+    
+    insertDocked : function(pos, items) {
+        this.addDocked(items, pos);
+    },
+
+    
+    removeDocked : function(item, autoDestroy) {
+        var me = this,
+            layout,
+            hasLayout;
+
+        if (!me.dockedItems.contains(item)) {
+            return item;
+        }
+
+        layout = me.componentLayout;
+        hasLayout = layout && me.rendered;
+
+        if (hasLayout) {
+            layout.onRemove(item);
+        }
+
+        me.dockedItems.remove(item);
+        item.onRemoved();
+        me.onDockedRemove(item);
+
+        if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
+            item.destroy();
+        } else if (hasLayout) {
+            
+            layout.afterRemove(item);    
+        }
+
+
+        
+        me.componentLayout.childrenChanged = true;
+        if (!me.destroying && !me.suspendLayout) {
+            me.doComponentLayout();
+        }
+
+        return item;
+    },
+
+    
+    getDockedItems : function(cqSelector) {
+        var me = this,
+            defaultWeight = me.defaultDockWeights,
+            dockedItems;
+
+        if (me.dockedItems && me.dockedItems.items.length) {
+            
+            if (cqSelector) {
+                dockedItems = Ext.ComponentQuery.query(cqSelector, me.dockedItems.items);
+            } else {
+                dockedItems = me.dockedItems.items.slice();
+            }
+
+            Ext.Array.sort(dockedItems, function(a, b) {
+                
+                var aw = a.weight || defaultWeight[a.dock],
+                    bw = b.weight || defaultWeight[b.dock];
+                if (Ext.isNumber(aw) && Ext.isNumber(bw)) {
+                    return aw - bw;
+                }
+                return 0;
+            });
+
+            return dockedItems;
+        }
+        return [];
+    },
+
+    
+    addUIClsToElement: function(cls, force) {
+        var me = this,
+            result = me.callParent(arguments),
+            classes = [Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
+            array, i;
+
+        if (!force && me.rendered) {
+            if (me.bodyCls) {
+                me.body.addCls(me.bodyCls);
+            } else {
+                me.body.addCls(classes);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+
+                for (i = 0; i < classes.length; i++) {
+                    if (!Ext.Array.contains(array, classes[i])) {
+                        array.push(classes[i]);
+                    }
+                }
+
+                me.bodyCls = array.join(' ');
+            } else {
+                me.bodyCls = classes.join(' ');
+            }
+        }
+
+        return result;
+    },
+
+    
+    removeUIClsFromElement: function(cls, force) {
+        var me = this,
+            result = me.callParent(arguments),
+            classes = [Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
+            array, i;
+
+        if (!force && me.rendered) {
+            if (me.bodyCls) {
+                me.body.removeCls(me.bodyCls);
+            } else {
+                me.body.removeCls(classes);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+
+                for (i = 0; i < classes.length; i++) {
+                    Ext.Array.remove(array, classes[i]);
+                }
+
+                me.bodyCls = array.join(' ');
+            }
+        }
+
+        return result;
+    },
+
+    
+    addUIToElement: function(force) {
+        var me = this,
+            cls = me.baseCls + '-body-' + me.ui,
+            array;
+
+        me.callParent(arguments);
+
+        if (!force && me.rendered) {
+            if (me.bodyCls) {
+                me.body.addCls(me.bodyCls);
+            } else {
+                me.body.addCls(cls);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+
+                if (!Ext.Array.contains(array, cls)) {
+                    array.push(cls);
+                }
+
+                me.bodyCls = array.join(' ');
+            } else {
+                me.bodyCls = cls;
+            }
+        }
+    },
+
+    
+    removeUIFromElement: function() {
+        var me = this,
+            cls = me.baseCls + '-body-' + me.ui,
+            array;
+
+        me.callParent(arguments);
+
+        if (me.rendered) {
+            if (me.bodyCls) {
+                me.body.removeCls(me.bodyCls);
+            } else {
+                me.body.removeCls(cls);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+                Ext.Array.remove(array, cls);
+                me.bodyCls = array.join(' ');
+            } else {
+                me.bodyCls = cls;
+            }
+        }
+    },
+
+    
+    getTargetEl : function() {
+        return this.body;
+    },
+
+    getRefItems: function(deep) {
+        var items = this.callParent(arguments),
+            
+            dockedItems = this.getDockedItems(deep ? '*,* *' : undefined),
+            ln = dockedItems.length,
+            i = 0,
+            item;
+
+        
+        for (; i < ln; i++) {
+            item = dockedItems[i];
+            if (item.dock === 'right' || item.dock === 'bottom') {
+                break;
+            }
+        }
+
+        
+        
+        
+        return Ext.Array.splice(dockedItems, 0, i).concat(items).concat(dockedItems);
+    },
+
+    beforeDestroy: function(){
+        var docked = this.dockedItems,
+            c;
+
+        if (docked) {
+            while ((c = docked.first())) {
+                this.removeDocked(c, true);
+            }
+        }
+        this.callParent();
+    },
+
+    setBorder: function(border) {
+        var me = this;
+        me.border = (border !== undefined) ? border : true;
+        if (me.rendered) {
+            me.doComponentLayout();
+        }
+    }
+});
+
+Ext.define('Ext.panel.Header', {
+    extend: 'Ext.container.Container',
+    uses: ['Ext.panel.Tool', 'Ext.draw.Component', 'Ext.util.CSS'],
+    alias: 'widget.header',
+
+    isHeader       : true,
+    defaultType    : 'tool',
+    indicateDrag   : false,
+    weight         : -1,
+
+    renderTpl: [
+        '<div id="{id}-body" class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl>',
+        '<tpl if="uiCls">',
+            '<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',
+        '</tpl>"',
+        '<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>'],
+
+    
+
+    
+
+    initComponent: function() {
+        var me = this,
+            ruleStyle,
+            rule,
+            style,
+            titleTextEl,
+            ui;
+
+        me.indicateDragCls = me.baseCls + '-draggable';
+        me.title = me.title || '&#160;';
+        me.tools = me.tools || [];
+        me.items = me.items || [];
+        me.orientation = me.orientation || 'horizontal';
+        me.dock = (me.dock) ? me.dock : (me.orientation == 'horizontal') ? 'top' : 'left';
+
+        
+        
+        me.addClsWithUI(me.orientation);
+        me.addClsWithUI(me.dock);
+
+        me.addChildEls('body');
+
+        
+        if (!Ext.isEmpty(me.iconCls)) {
+            me.initIconCmp();
+            me.items.push(me.iconCmp);
+        }
+
+        
+        if (me.orientation == 'vertical') {
+            
+            if (Ext.isIE6 || Ext.isIE7) {
+                me.width = this.width || 24;
+            } else if (Ext.isIEQuirks) {
+                me.width = this.width || 25;
+            }
+
+            me.layout = {
+                type : 'vbox',
+                align: 'center',
+                clearInnerCtOnLayout: true,
+                bindToOwnerCtContainer: false
+            };
+            me.textConfig = {
+                cls: me.baseCls + '-text',
+                type: 'text',
+                text: me.title,
+                rotate: {
+                    degrees: 90
+                }
+            };
+            ui = me.ui;
+            if (Ext.isArray(ui)) {
+                ui = ui[0];
+            }
+            ruleStyle = '.' + me.baseCls + '-text-' + ui;
+            if (Ext.scopeResetCSS) {
+                ruleStyle = '.' + Ext.baseCSSPrefix + 'reset ' + ruleStyle;
+            }
+            rule = Ext.util.CSS.getRule(ruleStyle);
+            if (rule) {
+                style = rule.style;
+            }
+            if (style) {
+                Ext.apply(me.textConfig, {
+                    'font-family': style.fontFamily,
+                    'font-weight': style.fontWeight,
+                    'font-size': style.fontSize,
+                    fill: style.color
+                });
+            }
+            me.titleCmp = Ext.create('Ext.draw.Component', {
+                ariaRole  : 'heading',
+                focusable: false,
+                viewBox: false,
+                flex : 1,
+                autoSize: true,
+                margins: '5 0 0 0',
+                items: [ me.textConfig ],
+                
+                
+                renderSelectors: {
+                    textEl: '.' + me.baseCls + '-text'
+                }
+            });
+        } else {
+            me.layout = {
+                type : 'hbox',
+                align: 'middle',
+                clearInnerCtOnLayout: true,
+                bindToOwnerCtContainer: false
+            };
+            me.titleCmp = Ext.create('Ext.Component', {
+                xtype     : 'component',
+                ariaRole  : 'heading',
+                focusable: false,
+                flex : 1,
+                cls: me.baseCls + '-text-container',
+                renderTpl : [
+                    '<span id="{id}-textEl" class="{cls}-text {cls}-text-{ui}">{title}</span>'
+                ],
+                renderData: {
+                    title: me.title,
+                    cls  : me.baseCls,
+                    ui   : me.ui
+                },
+                childEls: ['textEl']
+            });
+        }
+        me.items.push(me.titleCmp);
+
+        
+        me.items = me.items.concat(me.tools);
+        this.callParent();
+    },
+
+    initIconCmp: function() {
+        this.iconCmp = Ext.create('Ext.Component', {
+            focusable: false,
+            renderTpl : [
+                '<img id="{id}-iconEl" alt="" src="{blank}" class="{cls}-icon {iconCls}"/>'
+            ],
+            renderData: {
+                blank  : Ext.BLANK_IMAGE_URL,
+                cls    : this.baseCls,
+                iconCls: this.iconCls,
+                orientation: this.orientation
+            },
+            childEls: ['iconEl'],
+            iconCls: this.iconCls
+        });
+    },
+
+    afterRender: function() {
+        var me = this;
+
+        me.el.unselectable();
+        if (me.indicateDrag) {
+            me.el.addCls(me.indicateDragCls);
+        }
+        me.mon(me.el, {
+            click: me.onClick,
+            scope: me
+        });
+        me.callParent();
+    },
+
+    afterLayout: function() {
+        var me = this;
+        me.callParent(arguments);
+
+        
+        if (Ext.isIE7) {
+            me.el.repaint();
+        }
+    },
+
+    
+    addUIClsToElement: function(cls, force) {
+        var me = this,
+            result = me.callParent(arguments),
+            classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
+            array, i;
+
+        if (!force && me.rendered) {
+            if (me.bodyCls) {
+                me.body.addCls(me.bodyCls);
+            } else {
+                me.body.addCls(classes);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+
+                for (i = 0; i < classes.length; i++) {
+                    if (!Ext.Array.contains(array, classes[i])) {
+                        array.push(classes[i]);
+                    }
+                }
+
+                me.bodyCls = array.join(' ');
+            } else {
+                me.bodyCls = classes.join(' ');
+            }
+        }
+
+        return result;
+    },
+
+    
+    removeUIClsFromElement: function(cls, force) {
+        var me = this,
+            result = me.callParent(arguments),
+            classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
+            array, i;
+
+        if (!force && me.rendered) {
+            if (me.bodyCls) {
+                me.body.removeCls(me.bodyCls);
+            } else {
+                me.body.removeCls(classes);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+
+                for (i = 0; i < classes.length; i++) {
+                    Ext.Array.remove(array, classes[i]);
+                }
+
+                me.bodyCls = array.join(' ');
+            }
+        }
+
+       return result;
+    },
+
+    
+    addUIToElement: function(force) {
+        var me = this,
+            array, cls;
+
+        me.callParent(arguments);
+
+        cls = me.baseCls + '-body-' + me.ui;
+        if (!force && me.rendered) {
+            if (me.bodyCls) {
+                me.body.addCls(me.bodyCls);
+            } else {
+                me.body.addCls(cls);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+
+                if (!Ext.Array.contains(array, cls)) {
+                    array.push(cls);
+                }
+
+                me.bodyCls = array.join(' ');
+            } else {
+                me.bodyCls = cls;
+            }
+        }
+
+        if (!force && me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
+            me.titleCmp.textEl.addCls(me.baseCls + '-text-' + me.ui);
+        }
+    },
+
+    
+    removeUIFromElement: function() {
+        var me = this,
+            array, cls;
+
+        me.callParent(arguments);
+
+        cls = me.baseCls + '-body-' + me.ui;
+        if (me.rendered) {
+            if (me.bodyCls) {
+                me.body.removeCls(me.bodyCls);
+            } else {
+                me.body.removeCls(cls);
+            }
+        } else {
+            if (me.bodyCls) {
+                array = me.bodyCls.split(' ');
+                Ext.Array.remove(array, cls);
+                me.bodyCls = array.join(' ');
+            } else {
+                me.bodyCls = cls;
+            }
+        }
+
+        if (me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
+            me.titleCmp.textEl.removeCls(me.baseCls + '-text-' + me.ui);
+        }
+    },
+
+    onClick: function(e) {
+        if (!e.getTarget(Ext.baseCSSPrefix + 'tool')) {
+            this.fireEvent('click', e);
+        }
+    },
+
+    getTargetEl: function() {
+        return this.body || this.frameBody || this.el;
+    },
+
+    
+    setTitle: function(title) {
+        var me = this;
+        if (me.rendered) {
+            if (me.titleCmp.rendered) {
+                if (me.titleCmp.surface) {
+                    me.title = title || '';
+                    var sprite = me.titleCmp.surface.items.items[0],
+                        surface = me.titleCmp.surface;
+
+                    surface.remove(sprite);
+                    me.textConfig.type = 'text';
+                    me.textConfig.text = title;
+                    sprite = surface.add(me.textConfig);
+                    sprite.setAttributes({
+                        rotate: {
+                            degrees: 90
+                        }
+                    }, true);
+                    me.titleCmp.autoSizeSurface();
+                } else {
+                    me.title = title || '&#160;';
+                    me.titleCmp.textEl.update(me.title);
+                }
+            } else {
+                me.titleCmp.on({
+                    render: function() {
+                        me.setTitle(title);
+                    },
+                    single: true
+                });
+            }
+        } else {
+            me.on({
+                render: function() {
+                    me.layout.layout();
+                    me.setTitle(title);
+                },
+                single: true
+            });
+        }
+    },
+
+    
+    setIconCls: function(cls) {
+        var me = this,
+            isEmpty = !cls || !cls.length,
+            iconCmp = me.iconCmp,
+            el;
+        
+        me.iconCls = cls;
+        if (!me.iconCmp && !isEmpty) {
+            me.initIconCmp();
+            me.insert(0, me.iconCmp);
+        } else if (iconCmp) {
+            if (isEmpty) {
+                me.iconCmp.destroy();
+            } else {
+                el = iconCmp.iconEl;
+                el.removeCls(iconCmp.iconCls);
+                el.addCls(cls);
+                iconCmp.iconCls = cls;
+            }
+        }
+    },
+
+    
+    addTool: function(tool) {
+        this.tools.push(this.add(tool));
+    },
+
+    
+    onAdd: function(component, index) {
+        this.callParent([arguments]);
+        if (component instanceof Ext.panel.Tool) {
+            component.bindTo(this.ownerCt);
+            this.tools[component.type] = component;
+        }
+    }
+});
+
+
+Ext.define('Ext.fx.target.Element', {
+
+    
+    
+    extend: 'Ext.fx.target.Target',
+    
+    
+
+    type: 'element',
+
+    getElVal: function(el, attr, val) {
+        if (val == undefined) {
+            if (attr === 'x') {
+                val = el.getX();
+            }
+            else if (attr === 'y') {
+                val = el.getY();
+            }
+            else if (attr === 'scrollTop') {
+                val = el.getScroll().top;
+            }
+            else if (attr === 'scrollLeft') {
+                val = el.getScroll().left;
+            }
+            else if (attr === 'height') {
+                val = el.getHeight();
+            }
+            else if (attr === 'width') {
+                val = el.getWidth();
+            }
+            else {
+                val = el.getStyle(attr);
+            }
+        }
+        return val;
+    },
+
+    getAttr: function(attr, val) {
+        var el = this.target;
+        return [[ el, this.getElVal(el, attr, val)]];
+    },
+
+    setAttr: function(targetData) {
+        var target = this.target,
+            ln = targetData.length,
+            attrs, attr, o, i, j, ln2, element, value;
+        for (i = 0; i < ln; i++) {
+            attrs = targetData[i].attrs;
+            for (attr in attrs) {
+                if (attrs.hasOwnProperty(attr)) {
+                    ln2 = attrs[attr].length;
+                    for (j = 0; j < ln2; j++) {
+                        o = attrs[attr][j];
+                        element = o[0];
+                        value = o[1];
+                        if (attr === 'x') {
+                            element.setX(value);
+                        }
+                        else if (attr === 'y') {
+                            element.setY(value);
+                        }
+                        else if (attr === 'scrollTop') {
+                            element.scrollTo('top', value);
+                        }
+                        else if (attr === 'scrollLeft') {
+                            element.scrollTo('left',value);
+                        }
+                        else {
+                            element.setStyle(attr, value);
+                        }
+                    }
+                }
+            }
+        }
+    }
+});
+
+
+Ext.define('Ext.fx.target.CompositeElement', {
+
+    
+
+    extend: 'Ext.fx.target.Element',
+
+    
+
+    isComposite: true,
+    
+    constructor: function(target) {
+        target.id = target.id || Ext.id(null, 'ext-composite-');
+        this.callParent([target]);
+    },
+
+    getAttr: function(attr, val) {
+        var out = [],
+            target = this.target;
+        target.each(function(el) {
+            out.push([el, this.getElVal(el, attr, val)]);
+        }, this);
+        return out;
+    }
+});
+
+
+
+Ext.define('Ext.fx.Manager', {
+
+    
+
+    singleton: true,
+
+    requires: ['Ext.util.MixedCollection',
+               'Ext.fx.target.Element',
+               'Ext.fx.target.CompositeElement',
+               'Ext.fx.target.Sprite',
+               'Ext.fx.target.CompositeSprite',
+               'Ext.fx.target.Component'],
+
+    mixins: {
+        queue: 'Ext.fx.Queue'
+    },
+
+    
+
+    constructor: function() {
+        this.items = Ext.create('Ext.util.MixedCollection');
+        this.mixins.queue.constructor.call(this);
+
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+    },
+
+    
+    interval: 16,
+
+    
+    forceJS: true,
+
+    
+    createTarget: function(target) {
+        var me = this,
+            useCSS3 = !me.forceJS && Ext.supports.Transitions,
+            targetObj;
+
+        me.useCSS3 = useCSS3;
+
+        
+        if (Ext.isString(target)) {
+            target = Ext.get(target);
+        }
+        
+        if (target && target.tagName) {
+            target = Ext.get(target);
+            targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
+            me.targets.add(targetObj);
+            return targetObj;
+        }
+        if (Ext.isObject(target)) {
+            
+            if (target.dom) {
+                targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
+            }
+            
+            else if (target.isComposite) {
+                targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
+            }
+            
+            else if (target.isSprite) {
+                targetObj = Ext.create('Ext.fx.target.Sprite', target);
+            }
+            
+            else if (target.isCompositeSprite) {
+                targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
+            }
+            
+            else if (target.isComponent) {
+                targetObj = Ext.create('Ext.fx.target.Component', target);
+            }
+            else if (target.isAnimTarget) {
+                return target;
+            }
+            else {
+                return null;
+            }
+            me.targets.add(targetObj);
+            return targetObj;
+        }
+        else {
+            return null;
+        }
+    },
+
+    
+    addAnim: function(anim) {
+        var items = this.items,
+            task = this.task;
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+
+        items.add(anim);
+
+        
+        if (!task && items.length) {
+            task = this.task = {
+                run: this.runner,
+                interval: this.interval,
+                scope: this
+            };
+            Ext.TaskManager.start(task);
+        }
+
+        
+        
+        
+        
+    },
+
+    
+    removeAnim: function(anim) {
+        
+        var items = this.items,
+            task = this.task;
+        items.remove(anim);
+        
+        if (task && !items.length) {
+            Ext.TaskManager.stop(task);
+            delete this.task;
+        }
+    },
+
+    
+    startingFilter: function(o) {
+        return o.paused === false && o.running === false && o.iterations > 0;
+    },
+
+    
+    runningFilter: function(o) {
+        return o.paused === false && o.running === true && o.isAnimator !== true;
+    },
+
+    
+    runner: function() {
+        var me = this,
+            items = me.items;
+
+        me.targetData = {};
+        me.targetArr = {};
+
+        
+        me.timestamp = new Date();
+
+        
+        items.filterBy(me.startingFilter).each(me.startAnim, me);
+
+        
+        items.filterBy(me.runningFilter).each(me.runAnim, me);
+
+        
+        me.applyPendingAttrs();
+    },
+
+    
+    startAnim: function(anim) {
+        anim.start(this.timestamp);
+    },
+
+    
+    runAnim: function(anim) {
+        if (!anim) {
+            return;
+        }
+        var me = this,
+            targetId = anim.target.getId(),
+            useCSS3 = me.useCSS3 && anim.target.type == 'element',
+            elapsedTime = me.timestamp - anim.startTime,
+            target, o;
+
+        this.collectTargetData(anim, elapsedTime, useCSS3);
+
+        
+        
+        if (useCSS3) {
+            
+            anim.target.setAttr(me.targetData[targetId], true);
+
+            
+            me.targetData[targetId] = [];
+            me.collectTargetData(anim, anim.duration, useCSS3);
+
+            
+            anim.paused = true;
+
+            target = anim.target.target;
+            
+            if (anim.target.isComposite) {
+                target = anim.target.target.last();
+            }
+
+            
+            o = {};
+            o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
+            o.scope = anim;
+            o.single = true;
+            target.on(o);
+        }
+        
+        else if (elapsedTime >= anim.duration) {
+            me.applyPendingAttrs(true);
+            delete me.targetData[targetId];
+            delete me.targetArr[targetId];
+            anim.lastFrame();
+        }
+    },
+
+    
+    collectTargetData: function(anim, elapsedTime, useCSS3) {
+        var targetId = anim.target.getId(),
+            targetData = this.targetData[targetId],
+            data;
+        
+        if (!targetData) {
+            targetData = this.targetData[targetId] = [];
+            this.targetArr[targetId] = anim.target;
+        }
+
+        data = {
+            duration: anim.duration,
+            easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
+            attrs: {}
+        };
+        Ext.apply(data.attrs, anim.runAnim(elapsedTime));
+        targetData.push(data);
+    },
+
+    
+    applyPendingAttrs: function(isLastFrame) {
+        var targetData = this.targetData,
+            targetArr = this.targetArr,
+            targetId;
+        for (targetId in targetData) {
+            if (targetData.hasOwnProperty(targetId)) {
+                targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);
+            }
+        }
+    }
+});
+
+
+Ext.define('Ext.fx.Animator', {
+
+    
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: ['Ext.fx.Manager'],
+
+    
+
+    isAnimator: true,
+
+    
+    duration: 250,
+
+    
+    delay: 0,
+
+    
+    delayStart: 0,
+
+    
+    dynamic: false,
+
+    
+    easing: 'ease',
+
+    
+    running: false,
+
+    
+    paused: false,
+
+    
+    damper: 1,
+
+    
+    iterations: 1,
+
+    
+    currentIteration: 0,
+
+    
+    keyframeStep: 0,
+
+    
+    animKeyFramesRE: /^(from|to|\d+%?)$/,
+
+    
+
+     
+    constructor: function(config) {
+        var me = this;
+        config = Ext.apply(me, config || {});
+        me.config = config;
+        me.id = Ext.id(null, 'ext-animator-');
+        me.addEvents(
+            
+            'beforeanimate',
+            
+            'keyframe',
+            
+            'afteranimate'
+        );
+        me.mixins.observable.constructor.call(me, config);
+        me.timeline = [];
+        me.createTimeline(me.keyframes);
+        if (me.target) {
+            me.applyAnimator(me.target);
+            Ext.fx.Manager.addAnim(me);
+        }
+    },
+
+    
+    sorter: function (a, b) {
+        return a.pct - b.pct;
+    },
+
+    
+    createTimeline: function(keyframes) {
+        var me = this,
+            attrs = [],
+            to = me.to || {},
+            duration = me.duration,
+            prevMs, ms, i, ln, pct, anim, nextAnim, attr;
+
+        for (pct in keyframes) {
+            if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
+                attr = {attrs: Ext.apply(keyframes[pct], to)};
+                
+                if (pct == "from") {
+                    pct = 0;
+                }
+                else if (pct == "to") {
+                    pct = 100;
+                }
+                
+                attr.pct = parseInt(pct, 10);
+                attrs.push(attr);
+            }
+        }
+        
+        Ext.Array.sort(attrs, me.sorter);
+        
+        
+        
+        
+
+        ln = attrs.length;
+        for (i = 0; i < ln; i++) {
+            prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
+            ms = duration * (attrs[i].pct / 100);
+            me.timeline.push({
+                duration: ms - prevMs,
+                attrs: attrs[i].attrs
+            });
+        }
+    },
+
+    
+    applyAnimator: function(target) {
+        var me = this,
+            anims = [],
+            timeline = me.timeline,
+            reverse = me.reverse,
+            ln = timeline.length,
+            anim, easing, damper, initial, attrs, lastAttrs, i;
+
+        if (me.fireEvent('beforeanimate', me) !== false) {
+            for (i = 0; i < ln; i++) {
+                anim = timeline[i];
+                attrs = anim.attrs;
+                easing = attrs.easing || me.easing;
+                damper = attrs.damper || me.damper;
+                delete attrs.easing;
+                delete attrs.damper;
+                anim = Ext.create('Ext.fx.Anim', {
+                    target: target,
+                    easing: easing,
+                    damper: damper,
+                    duration: anim.duration,
+                    paused: true,
+                    to: attrs
+                });
+                anims.push(anim);
+            }
+            me.animations = anims;
+            me.target = anim.target;
+            for (i = 0; i < ln - 1; i++) {
+                anim = anims[i];
+                anim.nextAnim = anims[i + 1];
+                anim.on('afteranimate', function() {
+                    this.nextAnim.paused = false;
+                });
+                anim.on('afteranimate', function() {
+                    this.fireEvent('keyframe', this, ++this.keyframeStep);
+                }, me);
+            }
+            anims[ln - 1].on('afteranimate', function() {
+                this.lastFrame();
+            }, me);
+        }
+    },
+
+    
+    start: function(startTime) {
+        var me = this,
+            delay = me.delay,
+            delayStart = me.delayStart,
+            delayDelta;
+        if (delay) {
+            if (!delayStart) {
+                me.delayStart = startTime;
+                return;
+            }
+            else {
+                delayDelta = startTime - delayStart;
+                if (delayDelta < delay) {
+                    return;
+                }
+                else {
+                    
+                    startTime = new Date(delayStart.getTime() + delay);
+                }
+            }
+        }
+        if (me.fireEvent('beforeanimate', me) !== false) {
+            me.startTime = startTime;
+            me.running = true;
+            me.animations[me.keyframeStep].paused = false;
+        }
+    },
+
+    
+    lastFrame: function() {
+        var me = this,
+            iter = me.iterations,
+            iterCount = me.currentIteration;
+
+        iterCount++;
+        if (iterCount < iter) {
+            me.startTime = new Date();
+            me.currentIteration = iterCount;
+            me.keyframeStep = 0;
+            me.applyAnimator(me.target);
+            me.animations[me.keyframeStep].paused = false;
+        }
+        else {
+            me.currentIteration = 0;
+            me.end();
+        }
+    },
+
+    
+    end: function() {
+        var me = this;
+        me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);
+    }
+});
+
+Ext.ns('Ext.fx');
+
+Ext.require('Ext.fx.CubicBezier', function() {
+    var math = Math,
+        pi = math.PI,
+        pow = math.pow,
+        sin = math.sin,
+        sqrt = math.sqrt,
+        abs = math.abs,
+        backInSeed = 1.70158;
+    Ext.fx.Easing = {
+        
+        
+        
+        
+        
+        
+        
+        
+    };
+
+    Ext.apply(Ext.fx.Easing, {
+        linear: function(n) {
+            return n;
+        },
+        ease: function(n) {
+            var q = 0.07813 - n / 2,
+                alpha = -0.25,
+                Q = sqrt(0.0066 + q * q),
+                x = Q - q,
+                X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
+                y = -Q - q,
+                Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
+                t = X + Y + 0.25;
+            return pow(1 - t, 2) * 3 * t * 0.1 + (1 - t) * 3 * t * t + t * t * t;
+        },
+        easeIn: function (n) {
+            return pow(n, 1.7);
+        },
+        easeOut: function (n) {
+            return pow(n, 0.48);
+        },
+        easeInOut: function(n) {
+            var q = 0.48 - n / 1.04,
+                Q = sqrt(0.1734 + q * q),
+                x = Q - q,
+                X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
+                y = -Q - q,
+                Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
+                t = X + Y + 0.5;
+            return (1 - t) * 3 * t * t + t * t * t;
+        },
+        backIn: function (n) {
+            return n * n * ((backInSeed + 1) * n - backInSeed);
+        },
+        backOut: function (n) {
+            n = n - 1;
+            return n * n * ((backInSeed + 1) * n + backInSeed) + 1;
+        },
+        elasticIn: function (n) {
+            if (n === 0 || n === 1) {
+                return n;
+            }
+            var p = 0.3,
+                s = p / 4;
+            return pow(2, -10 * n) * sin((n - s) * (2 * pi) / p) + 1;
+        },
+        elasticOut: function (n) {
+            return 1 - Ext.fx.Easing.elasticIn(1 - n);
+        },
+        bounceIn: function (n) {
+            return 1 - Ext.fx.Easing.bounceOut(1 - n);
+        },
+        bounceOut: function (n) {
+            var s = 7.5625,
+                p = 2.75,
+                l;
+            if (n < (1 / p)) {
+                l = s * n * n;
+            } else {
+                if (n < (2 / p)) {
+                    n -= (1.5 / p);
+                    l = s * n * n + 0.75;
+                } else {
+                    if (n < (2.5 / p)) {
+                        n -= (2.25 / p);
+                        l = s * n * n + 0.9375;
+                    } else {
+                        n -= (2.625 / p);
+                        l = s * n * n + 0.984375;
+                    }
+                }
+            }
+            return l;
+        }
+    });
+    Ext.apply(Ext.fx.Easing, {
+        'back-in': Ext.fx.Easing.backIn,
+        'back-out': Ext.fx.Easing.backOut,
+        'ease-in': Ext.fx.Easing.easeIn,
+        'ease-out': Ext.fx.Easing.easeOut,
+        'elastic-in': Ext.fx.Easing.elasticIn,
+        'elastic-out': Ext.fx.Easing.elasticIn,
+        'bounce-in': Ext.fx.Easing.bounceIn,
+        'bounce-out': Ext.fx.Easing.bounceOut,
+        'ease-in-out': Ext.fx.Easing.easeInOut
+    });
+});
+
+Ext.define('Ext.draw.Draw', {
+    
+
+    singleton: true,
+
+    requires: ['Ext.draw.Color'],
+
+    
+
+    pathToStringRE: /,?([achlmqrstvxz]),?/gi,
+    pathCommandRE: /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
+    pathValuesRE: /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
+    stopsRE: /^(\d+%?)$/,
+    radian: Math.PI / 180,
+
+    availableAnimAttrs: {
+        along: "along",
+        blur: null,
+        "clip-rect": "csv",
+        cx: null,
+        cy: null,
+        fill: "color",
+        "fill-opacity": null,
+        "font-size": null,
+        height: null,
+        opacity: null,
+        path: "path",
+        r: null,
+        rotation: "csv",
+        rx: null,
+        ry: null,
+        scale: "csv",
+        stroke: "color",
+        "stroke-opacity": null,
+        "stroke-width": null,
+        translation: "csv",
+        width: null,
+        x: null,
+        y: null
+    },
+
+    is: function(o, type) {
+        type = String(type).toLowerCase();
+        return (type == "object" && o === Object(o)) ||
+            (type == "undefined" && typeof o == type) ||
+            (type == "null" && o === null) ||
+            (type == "array" && Array.isArray && Array.isArray(o)) ||
+            (Object.prototype.toString.call(o).toLowerCase().slice(8, -1)) == type;
+    },
+
+    ellipsePath: function(sprite) {
+        var attr = sprite.attr;
+        return Ext.String.format("M{0},{1}A{2},{3},0,1,1,{0},{4}A{2},{3},0,1,1,{0},{1}z", attr.x, attr.y - attr.ry, attr.rx, attr.ry, attr.y + attr.ry);
+    },
+
+    rectPath: function(sprite) {
+        var attr = sprite.attr;
+        if (attr.radius) {
+            return Ext.String.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", attr.x + attr.radius, attr.y, attr.width - attr.radius * 2, attr.radius, -attr.radius, attr.height - attr.radius * 2, attr.radius * 2 - attr.width, attr.radius * 2 - attr.height);
+        }
+        else {
+            return Ext.String.format("M{0},{1}l{2},0,0,{3},{4},0z", attr.x, attr.y, attr.width, attr.height, -attr.width);
+        }
+    },
+
+    
+    path2string: function () {
+        return this.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
+    },
+
+    
+    pathToString: function(arrayPath) {
+        return arrayPath.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
+    },
+
+    parsePathString: function (pathString) {
+        if (!pathString) {
+            return null;
+        }
+        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},
+            data = [],
+            me = this;
+        if (me.is(pathString, "array") && me.is(pathString[0], "array")) { 
+            data = me.pathClone(pathString);
+        }
+        if (!data.length) {
+            String(pathString).replace(me.pathCommandRE, function (a, b, c) {
+                var params = [],
+                    name = b.toLowerCase();
+                c.replace(me.pathValuesRE, function (a, b) {
+                    b && params.push(+b);
+                });
+                if (name == "m" && params.length > 2) {
+                    data.push([b].concat(Ext.Array.splice(params, 0, 2)));
+                    name = "l";
+                    b = (b == "m") ? "l" : "L";
+                }
+                while (params.length >= paramCounts[name]) {
+                    data.push([b].concat(Ext.Array.splice(params, 0, paramCounts[name])));
+                    if (!paramCounts[name]) {
+                        break;
+                    }
+                }
+            });
+        }
+        data.toString = me.path2string;
+        return data;
+    },
+
+    mapPath: function (path, matrix) {
+        if (!matrix) {
+            return path;
+        }
+        var x, y, i, ii, j, jj, pathi;
+        path = this.path2curve(path);
+        for (i = 0, ii = path.length; i < ii; i++) {
+            pathi = path[i];
+            for (j = 1, jj = pathi.length; j < jj-1; j += 2) {
+                x = matrix.x(pathi[j], pathi[j + 1]);
+                y = matrix.y(pathi[j], pathi[j + 1]);
+                pathi[j] = x;
+                pathi[j + 1] = y;
+            }
+        }
+        return path;
+    },
+
+    pathClone: function(pathArray) {
+        var res = [],
+            j, jj, i, ii;
+        if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
+            pathArray = this.parsePathString(pathArray);
+        }
+        for (i = 0, ii = pathArray.length; i < ii; i++) {
+            res[i] = [];
+            for (j = 0, jj = pathArray[i].length; j < jj; j++) {
+                res[i][j] = pathArray[i][j];
+            }
+        }
+        res.toString = this.path2string;
+        return res;
+    },
+
+    pathToAbsolute: function (pathArray) {
+        if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
+            pathArray = this.parsePathString(pathArray);
+        }
+        var res = [],
+            x = 0,
+            y = 0,
+            mx = 0,
+            my = 0,
+            i = 0,
+            ln = pathArray.length,
+            r, pathSegment, j, ln2;
+        
+        if (ln && pathArray[0][0] == "M") {
+            x = +pathArray[0][1];
+            y = +pathArray[0][2];
+            mx = x;
+            my = y;
+            i++;
+            res[0] = ["M", x, y];
+        }
+        for (; i < ln; i++) {
+            r = res[i] = [];
+            pathSegment = pathArray[i];
+            if (pathSegment[0] != pathSegment[0].toUpperCase()) {
+                r[0] = pathSegment[0].toUpperCase();
+                switch (r[0]) {
+                    
+                    case "A":
+                        r[1] = pathSegment[1];
+                        r[2] = pathSegment[2];
+                        r[3] = pathSegment[3];
+                        r[4] = pathSegment[4];
+                        r[5] = pathSegment[5];
+                        r[6] = +(pathSegment[6] + x);
+                        r[7] = +(pathSegment[7] + y);
+                        break;
+                    
+                    case "V":
+                        r[1] = +pathSegment[1] + y;
+                        break;
+                    
+                    case "H":
+                        r[1] = +pathSegment[1] + x;
+                        break;
+                    case "M":
+                    
+                        mx = +pathSegment[1] + x;
+                        my = +pathSegment[2] + y;
+                    default:
+                        j = 1;
+                        ln2 = pathSegment.length;
+                        for (; j < ln2; j++) {
+                            r[j] = +pathSegment[j] + ((j % 2) ? x : y);
+                        }
+                }
+            }
+            else {
+                j = 0;
+                ln2 = pathSegment.length;
+                for (; j < ln2; j++) {
+                    res[i][j] = pathSegment[j];
+                }
+            }
+            switch (r[0]) {
+                
+                case "Z":
+                    x = mx;
+                    y = my;
+                    break;
+                
+                case "H":
+                    x = r[1];
+                    break;
+                
+                case "V":
+                    y = r[1];
+                    break;
+                
+                case "M":
+                    pathSegment = res[i];
+                    ln2 = pathSegment.length;
+                    mx = pathSegment[ln2 - 2];
+                    my = pathSegment[ln2 - 1];
+                default:
+                    pathSegment = res[i];
+                    ln2 = pathSegment.length;
+                    x = pathSegment[ln2 - 2];
+                    y = pathSegment[ln2 - 1];
+            }
+        }
+        res.toString = this.path2string;
+        return res;
+    },
+
+    
+    pathToRelative: function (pathArray) {
+        if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) {
+            pathArray = this.parsePathString(pathArray);
+        }
+        var res = [],
+            x = 0,
+            y = 0,
+            mx = 0,
+            my = 0,
+            start = 0;
+        if (pathArray[0][0] == "M") {
+            x = pathArray[0][1];
+            y = pathArray[0][2];
+            mx = x;
+            my = y;
+            start++;
+            res.push(["M", x, y]);
+        }
+        for (var i = start, ii = pathArray.length; i < ii; i++) {
+            var r = res[i] = [],
+                pa = pathArray[i];
+            if (pa[0] != pa[0].toLowerCase()) {
+                r[0] = pa[0].toLowerCase();
+                switch (r[0]) {
+                    case "a":
+                        r[1] = pa[1];
+                        r[2] = pa[2];
+                        r[3] = pa[3];
+                        r[4] = pa[4];
+                        r[5] = pa[5];
+                        r[6] = +(pa[6] - x).toFixed(3);
+                        r[7] = +(pa[7] - y).toFixed(3);
+                        break;
+                    case "v":
+                        r[1] = +(pa[1] - y).toFixed(3);
+                        break;
+                    case "m":
+                        mx = pa[1];
+                        my = pa[2];
+                    default:
+                        for (var j = 1, jj = pa.length; j < jj; j++) {
+                            r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
+                        }
+                }
+            } else {
+                r = res[i] = [];
+                if (pa[0] == "m") {
+                    mx = pa[1] + x;
+                    my = pa[2] + y;
+                }
+                for (var k = 0, kk = pa.length; k < kk; k++) {
+                    res[i][k] = pa[k];
+                }
+            }
+            var len = res[i].length;
+            switch (res[i][0]) {
+                case "z":
+                    x = mx;
+                    y = my;
+                    break;
+                case "h":
+                    x += +res[i][len - 1];
+                    break;
+                case "v":
+                    y += +res[i][len - 1];
+                    break;
+                default:
+                    x += +res[i][len - 2];
+                    y += +res[i][len - 1];
+            }
+        }
+        res.toString = this.path2string;
+        return res;
+    },
+
+    
+    path2curve: function (path) {
+        var me = this,
+            points = me.pathToAbsolute(path),
+            ln = points.length,
+            attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+            i, seg, segLn, point;
+            
+        for (i = 0; i < ln; i++) {
+            points[i] = me.command2curve(points[i], attrs);
+            if (points[i].length > 7) {
+                    points[i].shift();
+                    point = points[i];
+                    while (point.length) {
+                        Ext.Array.splice(points, i++, 0, ["C"].concat(Ext.Array.splice(point, 0, 6)));
+                    }
+                    Ext.Array.erase(points, i, 1);
+                    ln = points.length;
+                }
+            seg = points[i];
+            segLn = seg.length;
+            attrs.x = seg[segLn - 2];
+            attrs.y = seg[segLn - 1];
+            attrs.bx = parseFloat(seg[segLn - 4]) || attrs.x;
+            attrs.by = parseFloat(seg[segLn - 3]) || attrs.y;
+        }
+        return points;
+    },
+    
+    interpolatePaths: function (path, path2) {
+        var me = this,
+            p = me.pathToAbsolute(path),
+            p2 = me.pathToAbsolute(path2),
+            attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+            attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+            fixArc = function (pp, i) {
+                if (pp[i].length > 7) {
+                    pp[i].shift();
+                    var pi = pp[i];
+                    while (pi.length) {
+                        Ext.Array.splice(pp, i++, 0, ["C"].concat(Ext.Array.splice(pi, 0, 6)));
+                    }
+                    Ext.Array.erase(pp, i, 1);
+                    ii = Math.max(p.length, p2.length || 0);
+                }
+            },
+            fixM = function (path1, path2, a1, a2, i) {
+                if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
+                    Ext.Array.splice(path2, i, 0, ["M", a2.x, a2.y]);
+                    a1.bx = 0;
+                    a1.by = 0;
+                    a1.x = path1[i][1];
+                    a1.y = path1[i][2];
+                    ii = Math.max(p.length, p2.length || 0);
+                }
+            };
+        for (var i = 0, ii = Math.max(p.length, p2.length || 0); i < ii; i++) {
+            p[i] = me.command2curve(p[i], attrs);
+            fixArc(p, i);
+            (p2[i] = me.command2curve(p2[i], attrs2));
+            fixArc(p2, i);
+            fixM(p, p2, attrs, attrs2, i);
+            fixM(p2, p, attrs2, attrs, i);
+            var seg = p[i],
+                seg2 = p2[i],
+                seglen = seg.length,
+                seg2len = seg2.length;
+            attrs.x = seg[seglen - 2];
+            attrs.y = seg[seglen - 1];
+            attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
+            attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
+            attrs2.bx = (parseFloat(seg2[seg2len - 4]) || attrs2.x);
+            attrs2.by = (parseFloat(seg2[seg2len - 3]) || attrs2.y);
+            attrs2.x = seg2[seg2len - 2];
+            attrs2.y = seg2[seg2len - 1];
+        }
+        return [p, p2];
+    },
+    
+    
+    command2curve: function (pathCommand, d) {
+        var me = this;
+        if (!pathCommand) {
+            return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
+        }
+        if (pathCommand[0] != "T" && pathCommand[0] != "Q") {
+            d.qx = d.qy = null;
+        }
+        switch (pathCommand[0]) {
+            case "M":
+                d.X = pathCommand[1];
+                d.Y = pathCommand[2];
+                break;
+            case "A":
+                pathCommand = ["C"].concat(me.arc2curve.apply(me, [d.x, d.y].concat(pathCommand.slice(1))));
+                break;
+            case "S":
+                pathCommand = ["C", d.x + (d.x - (d.bx || d.x)), d.y + (d.y - (d.by || d.y))].concat(pathCommand.slice(1));
+                break;
+            case "T":
+                d.qx = d.x + (d.x - (d.qx || d.x));
+                d.qy = d.y + (d.y - (d.qy || d.y));
+                pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, d.qx, d.qy, pathCommand[1], pathCommand[2]));
+                break;
+            case "Q":
+                d.qx = pathCommand[1];
+                d.qy = pathCommand[2];
+                pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[3], pathCommand[4]));
+                break;
+            case "L":
+                pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[1], pathCommand[2]);
+                break;
+            case "H":
+                pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], d.y, pathCommand[1], d.y);
+                break;
+            case "V":
+                pathCommand = ["C"].concat(d.x, d.y, d.x, pathCommand[1], d.x, pathCommand[1]);
+                break;
+            case "Z":
+                pathCommand = ["C"].concat(d.x, d.y, d.X, d.Y, d.X, d.Y);
+                break;
+        }
+        return pathCommand;
+    },
+
+    quadratic2curve: function (x1, y1, ax, ay, x2, y2) {
+        var _13 = 1 / 3,
+            _23 = 2 / 3;
+        return [
+                _13 * x1 + _23 * ax,
+                _13 * y1 + _23 * ay,
+                _13 * x2 + _23 * ax,
+                _13 * y2 + _23 * ay,
+                x2,
+                y2
+            ];
+    },
+    
+    rotate: function (x, y, rad) {
+        var cos = Math.cos(rad),
+            sin = Math.sin(rad),
+            X = x * cos - y * sin,
+            Y = x * sin + y * cos;
+        return {x: X, y: Y};
+    },
+
+    arc2curve: function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
+        
+        
+        var me = this,
+            PI = Math.PI,
+            radian = me.radian,
+            _120 = PI * 120 / 180,
+            rad = radian * (+angle || 0),
+            res = [],
+            math = Math,
+            mcos = math.cos,
+            msin = math.sin,
+            msqrt = math.sqrt,
+            mabs = math.abs,
+            masin = math.asin,
+            xy, cos, sin, x, y, h, rx2, ry2, k, cx, cy, f1, f2, df, c1, s1, c2, s2,
+            t, hx, hy, m1, m2, m3, m4, newres, i, ln, f2old, x2old, y2old;
+        if (!recursive) {
+            xy = me.rotate(x1, y1, -rad);
+            x1 = xy.x;
+            y1 = xy.y;
+            xy = me.rotate(x2, y2, -rad);
+            x2 = xy.x;
+            y2 = xy.y;
+            cos = mcos(radian * angle);
+            sin = msin(radian * angle);
+            x = (x1 - x2) / 2;
+            y = (y1 - y2) / 2;
+            h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
+            if (h > 1) {
+                h = msqrt(h);
+                rx = h * rx;
+                ry = h * ry;
+            }
+            rx2 = rx * rx;
+            ry2 = ry * ry;
+            k = (large_arc_flag == sweep_flag ? -1 : 1) *
+                    msqrt(mabs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
+            cx = k * rx * y / ry + (x1 + x2) / 2;
+            cy = k * -ry * x / rx + (y1 + y2) / 2;
+            f1 = masin(((y1 - cy) / ry).toFixed(7));
+            f2 = masin(((y2 - cy) / ry).toFixed(7));
+
+            f1 = x1 < cx ? PI - f1 : f1;
+            f2 = x2 < cx ? PI - f2 : f2;
+            if (f1 < 0) {
+                f1 = PI * 2 + f1;
+            }
+            if (f2 < 0) {
+                f2 = PI * 2 + f2;
+            }
+            if (sweep_flag && f1 > f2) {
+                f1 = f1 - PI * 2;
+            }
+            if (!sweep_flag && f2 > f1) {
+                f2 = f2 - PI * 2;
+            }
+        }
+        else {
+            f1 = recursive[0];
+            f2 = recursive[1];
+            cx = recursive[2];
+            cy = recursive[3];
+        }
+        df = f2 - f1;
+        if (mabs(df) > _120) {
+            f2old = f2;
+            x2old = x2;
+            y2old = y2;
+            f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
+            x2 = cx + rx * mcos(f2);
+            y2 = cy + ry * msin(f2);
+            res = me.arc2curve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
+        }
+        df = f2 - f1;
+        c1 = mcos(f1);
+        s1 = msin(f1);
+        c2 = mcos(f2);
+        s2 = msin(f2);
+        t = math.tan(df / 4);
+        hx = 4 / 3 * rx * t;
+        hy = 4 / 3 * ry * t;
+        m1 = [x1, y1];
+        m2 = [x1 + hx * s1, y1 - hy * c1];
+        m3 = [x2 + hx * s2, y2 - hy * c2];
+        m4 = [x2, y2];
+        m2[0] = 2 * m1[0] - m2[0];
+        m2[1] = 2 * m1[1] - m2[1];
+        if (recursive) {
+            return [m2, m3, m4].concat(res);
+        }
+        else {
+            res = [m2, m3, m4].concat(res).join().split(",");
+            newres = [];
+            ln = res.length;
+            for (i = 0;  i < ln; i++) {
+                newres[i] = i % 2 ? me.rotate(res[i - 1], res[i], rad).y : me.rotate(res[i], res[i + 1], rad).x;
+            }
+            return newres;
+        }
+    },
+
+    
+    rotateAndTranslatePath: function (sprite) {
+        var alpha = sprite.rotation.degrees,
+            cx = sprite.rotation.x,
+            cy = sprite.rotation.y,
+            dx = sprite.translation.x,
+            dy = sprite.translation.y,
+            path,
+            i,
+            p,
+            xy,
+            j,
+            res = [];
+        if (!alpha && !dx && !dy) {
+            return this.pathToAbsolute(sprite.attr.path);
+        }
+        dx = dx || 0;
+        dy = dy || 0;
+        path = this.pathToAbsolute(sprite.attr.path);
+        for (i = path.length; i--;) {
+            p = res[i] = path[i].slice();
+            if (p[0] == "A") {
+                xy = this.rotatePoint(p[6], p[7], alpha, cx, cy);
+                p[6] = xy.x + dx;
+                p[7] = xy.y + dy;
+            } else {
+                j = 1;
+                while (p[j + 1] != null) {
+                    xy = this.rotatePoint(p[j], p[j + 1], alpha, cx, cy);
+                    p[j] = xy.x + dx;
+                    p[j + 1] = xy.y + dy;
+                    j += 2;
+                }
+            }
+        }
+        return res;
+    },
+
+    
+    rotatePoint: function (x, y, alpha, cx, cy) {
+        if (!alpha) {
+            return {
+                x: x,
+                y: y
+            };
+        }
+        cx = cx || 0;
+        cy = cy || 0;
+        x = x - cx;
+        y = y - cy;
+        alpha = alpha * this.radian;
+        var cos = Math.cos(alpha),
+            sin = Math.sin(alpha);
+        return {
+            x: x * cos - y * sin + cx,
+            y: x * sin + y * cos + cy
+        };
+    },
+
+    pathDimensions: function (path) {
+        if (!path || !(path + "")) {
+            return {x: 0, y: 0, width: 0, height: 0};
+        }
+        path = this.path2curve(path);
+        var x = 0, 
+            y = 0,
+            X = [],
+            Y = [],
+            i = 0,
+            ln = path.length,
+            p, xmin, ymin, dim;
+        for (; i < ln; i++) {
+            p = path[i];
+            if (p[0] == "M") {
+                x = p[1];
+                y = p[2];
+                X.push(x);
+                Y.push(y);
+            }
+            else {
+                dim = this.curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
+                X = X.concat(dim.min.x, dim.max.x);
+                Y = Y.concat(dim.min.y, dim.max.y);
+                x = p[5];
+                y = p[6];
+            }
+        }
+        xmin = Math.min.apply(0, X);
+        ymin = Math.min.apply(0, Y);
+        return {
+            x: xmin,
+            y: ymin,
+            path: path,
+            width: Math.max.apply(0, X) - xmin,
+            height: Math.max.apply(0, Y) - ymin
+        };
+    },
+
+    intersectInside: function(path, cp1, cp2) {
+        return (cp2[0] - cp1[0]) * (path[1] - cp1[1]) > (cp2[1] - cp1[1]) * (path[0] - cp1[0]);
+    },
+
+    intersectIntersection: function(s, e, cp1, cp2) {
+        var p = [],
+            dcx = cp1[0] - cp2[0],
+            dcy = cp1[1] - cp2[1],
+            dpx = s[0] - e[0],
+            dpy = s[1] - e[1],
+            n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0],
+            n2 = s[0] * e[1] - s[1] * e[0],
+            n3 = 1 / (dcx * dpy - dcy * dpx);
+
+        p[0] = (n1 * dpx - n2 * dcx) * n3;
+        p[1] = (n1 * dpy - n2 * dcy) * n3;
+        return p;
+    },
+
+    intersect: function(subjectPolygon, clipPolygon) {
+        var me = this,
+            i = 0,
+            ln = clipPolygon.length,
+            cp1 = clipPolygon[ln - 1],
+            outputList = subjectPolygon,
+            cp2, s, e, point, ln2, inputList, j;
+        for (; i < ln; ++i) {
+            cp2 = clipPolygon[i];
+            inputList = outputList;
+            outputList = [];
+            s = inputList[inputList.length - 1];
+            j = 0;
+            ln2 = inputList.length;
+            for (; j < ln2; j++) {
+                e = inputList[j];
+                if (me.intersectInside(e, cp1, cp2)) {
+                    if (!me.intersectInside(s, cp1, cp2)) {
+                        outputList.push(me.intersectIntersection(s, e, cp1, cp2));
+                    }
+                    outputList.push(e);
+                }
+                else if (me.intersectInside(s, cp1, cp2)) {
+                    outputList.push(me.intersectIntersection(s, e, cp1, cp2));
+                }
+                s = e;
+            }
+            cp1 = cp2;
+        }
+        return outputList;
+    },
+
+    curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
+        var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
+            b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
+            c = p1x - c1x,
+            t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
+            t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
+            y = [p1y, p2y],
+            x = [p1x, p2x],
+            dot;
+        if (Math.abs(t1) > 1e12) {
+            t1 = 0.5;
+        }
+        if (Math.abs(t2) > 1e12) {
+            t2 = 0.5;
+        }
+        if (t1 > 0 && t1 < 1) {
+            dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
+            x.push(dot.x);
+            y.push(dot.y);
+        }
+        if (t2 > 0 && t2 < 1) {
+            dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
+            x.push(dot.x);
+            y.push(dot.y);
+        }
+        a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
+        b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
+        c = p1y - c1y;
+        t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
+        t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
+        if (Math.abs(t1) > 1e12) {
+            t1 = 0.5;
+        }
+        if (Math.abs(t2) > 1e12) {
+            t2 = 0.5;
+        }
+        if (t1 > 0 && t1 < 1) {
+            dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
+            x.push(dot.x);
+            y.push(dot.y);
+        }
+        if (t2 > 0 && t2 < 1) {
+            dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
+            x.push(dot.x);
+            y.push(dot.y);
+        }
+        return {
+            min: {x: Math.min.apply(0, x), y: Math.min.apply(0, y)},
+            max: {x: Math.max.apply(0, x), y: Math.max.apply(0, y)}
+        };
+    },
+
+    
+    getAnchors: function (prevX, prevY, curX, curY, nextX, nextY, value) {
+        value = value || 4;
+        var M = Math,
+            PI = M.PI,
+            halfPI = PI / 2,
+            abs = M.abs,
+            sin = M.sin,
+            cos = M.cos,
+            atan = M.atan,
+            control1Length, control2Length, control1Angle, control2Angle,
+            control1X, control1Y, control2X, control2Y, alpha;
+
+        
+        
+        control1Length = (curX - prevX) / value;
+        control2Length = (nextX - curX) / value;
+
+        
+        
+        
+        
+        if ((curY >= prevY && curY >= nextY) || (curY <= prevY && curY <= nextY)) {
+            control1Angle = control2Angle = halfPI;
+        } else {
+            control1Angle = atan((curX - prevX) / abs(curY - prevY));
+            if (prevY < curY) {
+                control1Angle = PI - control1Angle;
+            }
+            control2Angle = atan((nextX - curX) / abs(curY - nextY));
+            if (nextY < curY) {
+                control2Angle = PI - control2Angle;
+            }
+        }
+
+        
+        alpha = halfPI - ((control1Angle + control2Angle) % (PI * 2)) / 2;
+        if (alpha > halfPI) {
+            alpha -= PI;
+        }
+        control1Angle += alpha;
+        control2Angle += alpha;
+
+        
+        control1X = curX - control1Length * sin(control1Angle);
+        control1Y = curY + control1Length * cos(control1Angle);
+        control2X = curX + control2Length * sin(control2Angle);
+        control2Y = curY + control2Length * cos(control2Angle);
+
+        
+        
+        
+        
+        if ((curY > prevY && control1Y < prevY) || (curY < prevY && control1Y > prevY)) {
+            control1X += abs(prevY - control1Y) * (control1X - curX) / (control1Y - curY);
+            control1Y = prevY;
+        }
+        if ((curY > nextY && control2Y < nextY) || (curY < nextY && control2Y > nextY)) {
+            control2X -= abs(nextY - control2Y) * (control2X - curX) / (control2Y - curY);
+            control2Y = nextY;
+        }
+        
+        return {
+            x1: control1X,
+            y1: control1Y,
+            x2: control2X,
+            y2: control2Y
+        };
+    },
+
+    
+    smooth: function (originalPath, value) {
+        var path = this.path2curve(originalPath),
+            newp = [path[0]],
+            x = path[0][1],
+            y = path[0][2],
+            j,
+            points,
+            i = 1,
+            ii = path.length,
+            beg = 1,
+            mx = x,
+            my = y,
+            cx = 0,
+            cy = 0;
+        for (; i < ii; i++) {
+            var pathi = path[i],
+                pathil = pathi.length,
+                pathim = path[i - 1],
+                pathiml = pathim.length,
+                pathip = path[i + 1],
+                pathipl = pathip && pathip.length;
+            if (pathi[0] == "M") {
+                mx = pathi[1];
+                my = pathi[2];
+                j = i + 1;
+                while (path[j][0] != "C") {
+                    j++;
+                }
+                cx = path[j][5];
+                cy = path[j][6];
+                newp.push(["M", mx, my]);
+                beg = newp.length;
+                x = mx;
+                y = my;
+                continue;
+            }
+            if (pathi[pathil - 2] == mx && pathi[pathil - 1] == my && (!pathip || pathip[0] == "M")) {
+                var begl = newp[beg].length;
+                points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], mx, my, newp[beg][begl - 2], newp[beg][begl - 1], value);
+                newp[beg][1] = points.x2;
+                newp[beg][2] = points.y2;
+            }
+            else if (!pathip || pathip[0] == "M") {
+                points = {
+                    x1: pathi[pathil - 2],
+                    y1: pathi[pathil - 1]
+                };
+            } else {
+                points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], pathi[pathil - 2], pathi[pathil - 1], pathip[pathipl - 2], pathip[pathipl - 1], value);
+            }
+            newp.push(["C", x, y, points.x1, points.y1, pathi[pathil - 2], pathi[pathil - 1]]);
+            x = points.x2;
+            y = points.y2;
+        }
+        return newp;
+    },
+
+    findDotAtSegment: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
+        var t1 = 1 - t;
+        return {
+            x: Math.pow(t1, 3) * p1x + Math.pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + Math.pow(t, 3) * p2x,
+            y: Math.pow(t1, 3) * p1y + Math.pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + Math.pow(t, 3) * p2y
+        };
+    },
+
+    
+    snapEnds: function (from, to, stepsMax) {
+        if (Ext.isDate(from)) {
+            return this.snapEndsByDate(from, to, stepsMax);
+        }
+        var step = (to - from) / stepsMax,
+            level = Math.floor(Math.log(step) / Math.LN10) + 1,
+            m = Math.pow(10, level),
+            cur,
+            modulo = Math.round((step % m) * Math.pow(10, 2 - level)),
+            interval = [[0, 15], [20, 4], [30, 2], [40, 4], [50, 9], [60, 4], [70, 2], [80, 4], [100, 15]],
+            stepCount = 0,
+            value,
+            weight,
+            i,
+            topValue,
+            topWeight = 1e9,
+            ln = interval.length;
+        cur = from = Math.floor(from / m) * m;
+        for (i = 0; i < ln; i++) {
+            value = interval[i][0];
+            weight = (value - modulo) < 0 ? 1e6 : (value - modulo) / interval[i][1];
+            if (weight < topWeight) {
+                topValue = value;
+                topWeight = weight;
+            }
+        }
+        step = Math.floor(step * Math.pow(10, -level)) * Math.pow(10, level) + topValue * Math.pow(10, level - 2);
+        while (cur < to) {
+            cur += step;
+            stepCount++;
+        }
+        to = +cur.toFixed(10);
+        return {
+            from: from,
+            to: to,
+            power: level,
+            step: step,
+            steps: stepCount
+        };
+    },
+
+    
+    snapEndsByDate: function (from, to, stepsMax, lockEnds) {
+        var selectedStep = false, scales = [
+                [Ext.Date.MILLI, [1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 300, 500]],
+                [Ext.Date.SECOND, [1, 2, 3, 5, 10, 15, 30]],
+                [Ext.Date.MINUTE, [1, 2, 3, 5, 10, 20, 30]],
+                [Ext.Date.HOUR, [1, 2, 3, 4, 6, 12]],
+                [Ext.Date.DAY, [1, 2, 3, 7, 14]],
+                [Ext.Date.MONTH, [1, 2, 3, 4, 6]]
+            ], j, yearDiff;
+
+        
+        Ext.each(scales, function(scale, i) {
+            for (j = 0; j < scale[1].length; j++) {
+                if (to < Ext.Date.add(from, scale[0], scale[1][j] * stepsMax)) {
+                    selectedStep = [scale[0], scale[1][j]];
+                    return false;
+                }
+            }
+        });
+        if (!selectedStep) {
+            yearDiff = this.snapEnds(from.getFullYear(), to.getFullYear() + 1, stepsMax, lockEnds);
+            selectedStep = [Date.YEAR, Math.round(yearDiff.step)];
+        }
+        return this.snapEndsByDateAndStep(from, to, selectedStep, lockEnds);
+    },
+
+
+    
+    snapEndsByDateAndStep: function(from, to, step, lockEnds) {
+        var fromStat = [from.getFullYear(), from.getMonth(), from.getDate(),
+                from.getHours(), from.getMinutes(), from.getSeconds(), from.getMilliseconds()],
+            steps = 0, testFrom, testTo;
+        if (lockEnds) {
+            testFrom = from;
+        } else {
+            switch (step[0]) {
+                case Ext.Date.MILLI:
+                    testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
+                            fromStat[4], fromStat[5], Math.floor(fromStat[6] / step[1]) * step[1]);
+                    break;
+                case Ext.Date.SECOND:
+                    testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
+                            fromStat[4], Math.floor(fromStat[5] / step[1]) * step[1], 0);
+                    break;
+                case Ext.Date.MINUTE:
+                    testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
+                            Math.floor(fromStat[4] / step[1]) * step[1], 0, 0);
+                    break;
+                case Ext.Date.HOUR:
+                    testFrom = new Date(fromStat[0], fromStat[1], fromStat[2],
+                            Math.floor(fromStat[3] / step[1]) * step[1], 0, 0, 0);
+                    break;
+                case Ext.Date.DAY:
+                    testFrom = new Date(fromStat[0], fromStat[1],
+                            Math.floor(fromStat[2] - 1 / step[1]) * step[1] + 1, 0, 0, 0, 0);
+                    break;
+                case Ext.Date.MONTH:
+                    testFrom = new Date(fromStat[0], Math.floor(fromStat[1] / step[1]) * step[1], 1, 0, 0, 0, 0);
+                    break;
+                default: 
+                    testFrom = new Date(Math.floor(fromStat[0] / step[1]) * step[1], 0, 1, 0, 0, 0, 0);
+                    break;
+            }
+        }
+
+        testTo = testFrom;
+        
+        while (testTo < to) {
+            testTo = Ext.Date.add(testTo, step[0], step[1]);
+            steps++;
+        }
+
+        if (lockEnds) {
+            testTo = to;
+        }
+        return {
+            from : +testFrom,
+            to : +testTo,
+            step : (testTo - testFrom) / steps,
+            steps : steps
+        };
+    },
+
+    sorter: function (a, b) {
+        return a.offset - b.offset;
+    },
+
+    rad: function(degrees) {
+        return degrees % 360 * Math.PI / 180;
+    },
+
+    degrees: function(radian) {
+        return radian * 180 / Math.PI % 360;
+    },
+
+    withinBox: function(x, y, bbox) {
+        bbox = bbox || {};
+        return (x >= bbox.x && x <= (bbox.x + bbox.width) && y >= bbox.y && y <= (bbox.y + bbox.height));
+    },
+
+    parseGradient: function(gradient) {
+        var me = this,
+            type = gradient.type || 'linear',
+            angle = gradient.angle || 0,
+            radian = me.radian,
+            stops = gradient.stops,
+            stopsArr = [],
+            stop,
+            vector,
+            max,
+            stopObj;
+
+        if (type == 'linear') {
+            vector = [0, 0, Math.cos(angle * radian), Math.sin(angle * radian)];
+            max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1);
+            vector[2] *= max;
+            vector[3] *= max;
+            if (vector[2] < 0) {
+                vector[0] = -vector[2];
+                vector[2] = 0;
+            }
+            if (vector[3] < 0) {
+                vector[1] = -vector[3];
+                vector[3] = 0;
+            }
+        }
+
+        for (stop in stops) {
+            if (stops.hasOwnProperty(stop) && me.stopsRE.test(stop)) {
+                stopObj = {
+                    offset: parseInt(stop, 10),
+                    color: Ext.draw.Color.toHex(stops[stop].color) || '#ffffff',
+                    opacity: stops[stop].opacity || 1
+                };
+                stopsArr.push(stopObj);
+            }
+        }
+        
+        Ext.Array.sort(stopsArr, me.sorter);
+        if (type == 'linear') {
+            return {
+                id: gradient.id,
+                type: type,
+                vector: vector,
+                stops: stopsArr
+            };
+        }
+        else {
+            return {
+                id: gradient.id,
+                type: type,
+                centerX: gradient.centerX,
+                centerY: gradient.centerY,
+                focalX: gradient.focalX,
+                focalY: gradient.focalY,
+                radius: gradient.radius,
+                vector: vector,
+                stops: stopsArr
+            };
+        }
+    }
+});
+
+
+
+Ext.define('Ext.fx.PropertyHandler', {
+
+    
+
+    requires: ['Ext.draw.Draw'],
+
+    statics: {
+        defaultHandler: {
+            pixelDefaultsRE: /width|height|top$|bottom$|left$|right$/i,
+            unitRE: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/,
+            scrollRE: /^scroll/i,
+
+            computeDelta: function(from, end, damper, initial, attr) {
+                damper = (typeof damper == 'number') ? damper : 1;
+                var unitRE = this.unitRE,
+                    match = unitRE.exec(from),
+                    start, units;
+                if (match) {
+                    from = match[1];
+                    units = match[2];
+                    if (!this.scrollRE.test(attr) && !units && this.pixelDefaultsRE.test(attr)) {
+                        units = 'px';
+                    }
+                }
+                from = +from || 0;
+
+                match = unitRE.exec(end);
+                if (match) {
+                    end = match[1];
+                    units = match[2] || units;
+                }
+                end = +end || 0;
+                start = (initial != null) ? initial : from;
+                return {
+                    from: from,
+                    delta: (end - start) * damper,
+                    units: units
+                };
+            },
+
+            get: function(from, end, damper, initialFrom, attr) {
+                var ln = from.length,
+                    out = [],
+                    i, initial, res, j, len;
+                for (i = 0; i < ln; i++) {
+                    if (initialFrom) {
+                        initial = initialFrom[i][1].from;
+                    }
+                    if (Ext.isArray(from[i][1]) && Ext.isArray(end)) {
+                        res = [];
+                        j = 0;
+                        len = from[i][1].length;
+                        for (; j < len; j++) {
+                            res.push(this.computeDelta(from[i][1][j], end[j], damper, initial, attr));
+                        }
+                        out.push([from[i][0], res]);
+                    }
+                    else {
+                        out.push([from[i][0], this.computeDelta(from[i][1], end, damper, initial, attr)]);
+                    }
+                }
+                return out;
+            },
+
+            set: function(values, easing) {
+                var ln = values.length,
+                    out = [],
+                    i, val, res, len, j;
+                for (i = 0; i < ln; i++) {
+                    val  = values[i][1];
+                    if (Ext.isArray(val)) {
+                        res = [];
+                        j = 0;
+                        len = val.length;
+                        for (; j < len; j++) {
+                            res.push(val[j].from + (val[j].delta * easing) + (val[j].units || 0));
+                        }
+                        out.push([values[i][0], res]);
+                    } else {
+                        out.push([values[i][0], val.from + (val.delta * easing) + (val.units || 0)]);
+                    }
+                }
+                return out;
+            }
+        },
+        color: {
+            rgbRE: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
+            hexRE: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
+            hex3RE: /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,
+
+            parseColor : function(color, damper) {
+                damper = (typeof damper == 'number') ? damper : 1;
+                var base,
+                    out = false,
+                    match;
+
+                Ext.each([this.hexRE, this.rgbRE, this.hex3RE], function(re, idx) {
+                    base = (idx % 2 == 0) ? 16 : 10;
+                    match = re.exec(color);
+                    if (match && match.length == 4) {
+                        if (idx == 2) {
+                            match[1] += match[1];
+                            match[2] += match[2];
+                            match[3] += match[3];
+                        }
+                        out = {
+                            red: parseInt(match[1], base),
+                            green: parseInt(match[2], base),
+                            blue: parseInt(match[3], base)
+                        };
+                        return false;
+                    }
+                });
+                return out || color;
+            },
+
+            computeDelta: function(from, end, damper, initial) {
+                from = this.parseColor(from);
+                end = this.parseColor(end, damper);
+                var start = initial ? initial : from,
+                    tfrom = typeof start,
+                    tend = typeof end;
+                
+                if (tfrom == 'string' ||  tfrom == 'undefined' 
+                  || tend == 'string' || tend == 'undefined') {
+                    return end || start;
+                }
+                return {
+                    from:  from,
+                    delta: {
+                        red: Math.round((end.red - start.red) * damper),
+                        green: Math.round((end.green - start.green) * damper),
+                        blue: Math.round((end.blue - start.blue) * damper)
+                    }
+                };
+            },
+
+            get: function(start, end, damper, initialFrom) {
+                var ln = start.length,
+                    out = [],
+                    i, initial;
+                for (i = 0; i < ln; i++) {
+                    if (initialFrom) {
+                        initial = initialFrom[i][1].from;
+                    }
+                    out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
+                }
+                return out;
+            },
+
+            set: function(values, easing) {
+                var ln = values.length,
+                    out = [],
+                    i, val, parsedString, from, delta;
+                for (i = 0; i < ln; i++) {
+                    val = values[i][1];
+                    if (val) {
+                        from = val.from;
+                        delta = val.delta;
+                        
+                        val = (typeof val == 'object' && 'red' in val)? 
+                                'rgb(' + val.red + ', ' + val.green + ', ' + val.blue + ')' : val;
+                        val = (typeof val == 'object' && val.length)? val[0] : val;
+                        if (typeof val == 'undefined') {
+                            return [];
+                        }
+                        parsedString = typeof val == 'string'? val :
+                            'rgb(' + [
+                                  (from.red + Math.round(delta.red * easing)) % 256,
+                                  (from.green + Math.round(delta.green * easing)) % 256,
+                                  (from.blue + Math.round(delta.blue * easing)) % 256
+                              ].join(',') + ')';
+                        out.push([
+                            values[i][0],
+                            parsedString
+                        ]);
+                    }
+                }
+                return out;
+            }
+        },
+        object: {
+            interpolate: function(prop, damper) {
+                damper = (typeof damper == 'number') ? damper : 1;
+                var out = {},
+                    p;
+                for(p in prop) {
+                    out[p] = parseInt(prop[p], 10) * damper;
+                }
+                return out;
+            },
+
+            computeDelta: function(from, end, damper, initial) {
+                from = this.interpolate(from);
+                end = this.interpolate(end, damper);
+                var start = initial ? initial : from,
+                    delta = {},
+                    p;
+
+                for(p in end) {
+                    delta[p] = end[p] - start[p];
+                }
+                return {
+                    from:  from,
+                    delta: delta
+                };
+            },
+
+            get: function(start, end, damper, initialFrom) {
+                var ln = start.length,
+                    out = [],
+                    i, initial;
+                for (i = 0; i < ln; i++) {
+                    if (initialFrom) {
+                        initial = initialFrom[i][1].from;
+                    }
+                    out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
+                }
+                return out;
+            },
+
+            set: function(values, easing) {
+                var ln = values.length,
+                    out = [],
+                    outObject = {},
+                    i, from, delta, val, p;
+                for (i = 0; i < ln; i++) {
+                    val  = values[i][1];
+                    from = val.from;
+                    delta = val.delta;
+                    for (p in from) {
+                        outObject[p] = Math.round(from[p] + delta[p] * easing);
+                    }
+                    out.push([
+                        values[i][0],
+                        outObject
+                    ]);
+                }
+                return out;
+            }
+        },
+
+        path: {
+            computeDelta: function(from, end, damper, initial) {
+                damper = (typeof damper == 'number') ? damper : 1;
+                var start;
+                from = +from || 0;
+                end = +end || 0;
+                start = (initial != null) ? initial : from;
+                return {
+                    from: from,
+                    delta: (end - start) * damper
+                };
+            },
+
+            forcePath: function(path) {
+                if (!Ext.isArray(path) && !Ext.isArray(path[0])) {
+                    path = Ext.draw.Draw.parsePathString(path);
+                }
+                return path;
+            },
+
+            get: function(start, end, damper, initialFrom) {
+                var endPath = this.forcePath(end),
+                    out = [],
+                    startLn = start.length,
+                    startPathLn, pointsLn, i, deltaPath, initial, j, k, path, startPath;
+                for (i = 0; i < startLn; i++) {
+                    startPath = this.forcePath(start[i][1]);
+
+                    deltaPath = Ext.draw.Draw.interpolatePaths(startPath, endPath);
+                    startPath = deltaPath[0];
+                    endPath = deltaPath[1];
+
+                    startPathLn = startPath.length;
+                    path = [];
+                    for (j = 0; j < startPathLn; j++) {
+                        deltaPath = [startPath[j][0]];
+                        pointsLn = startPath[j].length;
+                        for (k = 1; k < pointsLn; k++) {
+                            initial = initialFrom && initialFrom[0][1][j][k].from;
+                            deltaPath.push(this.computeDelta(startPath[j][k], endPath[j][k], damper, initial));
+                        }
+                        path.push(deltaPath);
+                    }
+                    out.push([start[i][0], path]);
+                }
+                return out;
+            },
+
+            set: function(values, easing) {
+                var ln = values.length,
+                    out = [],
+                    i, j, k, newPath, calcPath, deltaPath, deltaPathLn, pointsLn;
+                for (i = 0; i < ln; i++) {
+                    deltaPath = values[i][1];
+                    newPath = [];
+                    deltaPathLn = deltaPath.length;
+                    for (j = 0; j < deltaPathLn; j++) {
+                        calcPath = [deltaPath[j][0]];
+                        pointsLn = deltaPath[j].length;
+                        for (k = 1; k < pointsLn; k++) {
+                            calcPath.push(deltaPath[j][k].from + deltaPath[j][k].delta * easing);
+                        }
+                        newPath.push(calcPath.join(','));
+                    }
+                    out.push([values[i][0], newPath.join(',')]);
+                }
+                return out;
+            }
+        }
+        
+    }
+}, function() {
+    Ext.each([
+        'outlineColor',
+        'backgroundColor',
+        'borderColor',
+        'borderTopColor',
+        'borderRightColor', 
+        'borderBottomColor', 
+        'borderLeftColor',
+        'fill',
+        'stroke'
+    ], function(prop) {
+        this[prop] = this.color;
+    }, this);
+});
+
+Ext.define('Ext.fx.Anim', {
+
+    
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
+
+    
+
+    isAnimation: true,
+
+    
+
+    
+
+    
+    duration: 250,
+
+    
+    delay: 0,
+
+    
+    delayStart: 0,
+
+    
+    dynamic: false,
+
+    
+    easing: 'ease',
+
+     
+
+    
+    damper: 1,
+
+    
+    bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
+
+    
+    reverse: false,
+
+    
+    running: false,
+
+    
+    paused: false,
+
+    
+    iterations: 1,
+
+    
+    alternate: false,
+
+    
+    currentIteration: 0,
+
+    
+    startTime: 0,
+
+    
+
+    
+
+    
+
+    
+
+    
+    constructor: function(config) {
+        var me = this,
+            curve;
+            
+        config = config || {};
+        
+        if (config.keyframes) {
+            return Ext.create('Ext.fx.Animator', config);
+        }
+        config = Ext.apply(me, config);
+        if (me.from === undefined) {
+            me.from = {};
+        }
+        me.propHandlers = {};
+        me.config = config;
+        me.target = Ext.fx.Manager.createTarget(me.target);
+        me.easingFn = Ext.fx.Easing[me.easing];
+        me.target.dynamic = me.dynamic;
+
+        
+        if (!me.easingFn) {
+            me.easingFn = String(me.easing).match(me.bezierRE);
+            if (me.easingFn && me.easingFn.length == 5) {
+                curve = me.easingFn;
+                me.easingFn = Ext.fx.CubicBezier.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
+            }
+        }
+        me.id = Ext.id(null, 'ext-anim-');
+        Ext.fx.Manager.addAnim(me);
+        me.addEvents(
+            
+            'beforeanimate',
+             
+            'afteranimate',
+             
+            'lastframe'
+        );
+        me.mixins.observable.constructor.call(me, config);
+        if (config.callback) {
+            me.on('afteranimate', config.callback, config.scope);
+        }
+        return me;
+    },
+
+    
+    setAttr: function(attr, value) {
+        return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
+    },
+
+    
+    initAttrs: function() {
+        var me = this,
+            from = me.from,
+            to = me.to,
+            initialFrom = me.initialFrom || {},
+            out = {},
+            start, end, propHandler, attr;
+
+        for (attr in to) {
+            if (to.hasOwnProperty(attr)) {
+                start = me.target.getAttr(attr, from[attr]);
+                end = to[attr];
+                
+                if (!Ext.fx.PropertyHandler[attr]) {
+                    if (Ext.isObject(end)) {
+                        propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
+                    } else {
+                        propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
+                    }
+                }
+                
+                else {
+                    propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
+                }
+                out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
+            }
+        }
+        me.currentAttrs = out;
+    },
+
+    
+    start: function(startTime) {
+        var me = this,
+            delay = me.delay,
+            delayStart = me.delayStart,
+            delayDelta;
+        if (delay) {
+            if (!delayStart) {
+                me.delayStart = startTime;
+                return;
+            }
+            else {
+                delayDelta = startTime - delayStart;
+                if (delayDelta < delay) {
+                    return;
+                }
+                else {
+                    
+                    startTime = new Date(delayStart.getTime() + delay);
+                }
+            }
+        }
+        if (me.fireEvent('beforeanimate', me) !== false) {
+            me.startTime = startTime;
+            if (!me.paused && !me.currentAttrs) {
+                me.initAttrs();
+            }
+            me.running = true;
+        }
+    },
+
+    
+    runAnim: function(elapsedTime) {
+        var me = this,
+            attrs = me.currentAttrs,
+            duration = me.duration,
+            easingFn = me.easingFn,
+            propHandlers = me.propHandlers,
+            ret = {},
+            easing, values, attr, lastFrame;
+
+        if (elapsedTime >= duration) {
+            elapsedTime = duration;
+            lastFrame = true;
+        }
+        if (me.reverse) {
+            elapsedTime = duration - elapsedTime;
+        }
+
+        for (attr in attrs) {
+            if (attrs.hasOwnProperty(attr)) {
+                values = attrs[attr];
+                easing = lastFrame ? 1 : easingFn(elapsedTime / duration);
+                ret[attr] = propHandlers[attr].set(values, easing);
+            }
+        }
+        return ret;
+    },
+
+    
+    lastFrame: function() {
+        var me = this,
+            iter = me.iterations,
+            iterCount = me.currentIteration;
+
+        iterCount++;
+        if (iterCount < iter) {
+            if (me.alternate) {
+                me.reverse = !me.reverse;
+            }
+            me.startTime = new Date();
+            me.currentIteration = iterCount;
+            
+            me.paused = false;
+        }
+        else {
+            me.currentIteration = 0;
+            me.end();
+            me.fireEvent('lastframe', me, me.startTime);
+        }
+    },
+
+    
+    end: function() {
+        var me = this;
+        me.startTime = 0;
+        me.paused = false;
+        me.running = false;
+        Ext.fx.Manager.removeAnim(me);
+        me.fireEvent('afteranimate', me, me.startTime);
+    }
+});
+
+Ext.enableFx = true;
+
+
+
+
+
+Ext.define('Ext.dd.DragDrop', {
+    requires: ['Ext.dd.DragDropManager'],
+
+    
+    constructor: function(id, sGroup, config) {
+        if(id) {
+            this.init(id, sGroup, config);
+        }
+    },
+
+    
+
+    
+    id: null,
+
+    
+    config: null,
+
+    
+    dragElId: null,
+
+    
+    handleElId: null,
+
+    
+    invalidHandleTypes: null,
+
+    
+    invalidHandleIds: null,
+
+    
+    invalidHandleClasses: null,
+
+    
+    startPageX: 0,
+
+    
+    startPageY: 0,
+
+    
+    groups: null,
+
+    
+    locked: false,
+
+    
+    lock: function() {
+        this.locked = true;
+    },
+
+    
+    moveOnly: false,
+
+    
+    unlock: function() {
+        this.locked = false;
+    },
+
+    
+    isTarget: true,
+
+    
+    padding: null,
+
+    
+    _domRef: null,
+
+    
+    __ygDragDrop: true,
+
+    
+    constrainX: false,
+
+    
+    constrainY: false,
+
+    
+    minX: 0,
+
+    
+    maxX: 0,
+
+    
+    minY: 0,
+
+    
+    maxY: 0,
+
+    
+    maintainOffset: false,
+
+    
+    xTicks: null,
+
+    
+    yTicks: null,
+
+    
+    primaryButtonOnly: true,
+
+    
+    available: false,
+
+    
+    hasOuterHandles: false,
+
+    
+    b4StartDrag: function(x, y) { },
+
+    
+    startDrag: function(x, y) {  },
+
+    
+    b4Drag: function(e) { },
+
+    
+    onDrag: function(e) {  },
+
+    
+    onDragEnter: function(e, id) {  },
+
+    
+    b4DragOver: function(e) { },
+
+    
+    onDragOver: function(e, id) {  },
+
+    
+    b4DragOut: function(e) { },
+
+    
+    onDragOut: function(e, id) {  },
+
+    
+    b4DragDrop: function(e) { },
+
+    
+    onDragDrop: function(e, id) {  },
+
+    
+    onInvalidDrop: function(e) {  },
+
+    
+    b4EndDrag: function(e) { },
+
+    
+    endDrag: function(e) {  },
+
+    
+    b4MouseDown: function(e) {  },
+
+    
+    onMouseDown: function(e) {  },
+
+    
+    onMouseUp: function(e) {  },
+
+    
+    onAvailable: function () {
+    },
+
+    
+    defaultPadding: {
+        left: 0,
+        right: 0,
+        top: 0,
+        bottom: 0
+    },
+
+    
+    constrainTo : function(constrainTo, pad, inContent){
+        if(Ext.isNumber(pad)){
+            pad = {left: pad, right:pad, top:pad, bottom:pad};
+        }
+        pad = pad || this.defaultPadding;
+        var b = Ext.get(this.getEl()).getBox(),
+            ce = Ext.get(constrainTo),
+            s = ce.getScroll(),
+            c,
+            cd = ce.dom;
+        if(cd == document.body){
+            c = { x: s.left, y: s.top, width: Ext.Element.getViewWidth(), height: Ext.Element.getViewHeight()};
+        }else{
+            var xy = ce.getXY();
+            c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
+        }
+
+
+        var topSpace = b.y - c.y,
+            leftSpace = b.x - c.x;
+
+        this.resetConstraints();
+        this.setXConstraint(leftSpace - (pad.left||0), 
+                c.width - leftSpace - b.width - (pad.right||0), 
+                               this.xTickSize
+        );
+        this.setYConstraint(topSpace - (pad.top||0), 
+                c.height - topSpace - b.height - (pad.bottom||0), 
+                               this.yTickSize
+        );
+    },
+
+    
+    getEl: function() {
+        if (!this._domRef) {
+            this._domRef = Ext.getDom(this.id);
+        }
+
+        return this._domRef;
+    },
+
+    
+    getDragEl: function() {
+        return Ext.getDom(this.dragElId);
+    },
+
+    
+    init: function(id, sGroup, config) {
+        this.initTarget(id, sGroup, config);
+        Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
+        
+    },
+
+    
+    initTarget: function(id, sGroup, config) {
+        
+        this.config = config || {};
+
+        
+        this.DDMInstance = Ext.dd.DragDropManager;
+        
+        this.groups = {};
+
+        
+        
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+
+        
+        this.id = id;
+
+        
+        this.addToGroup((sGroup) ? sGroup : "default");
+
+        
+        
+        this.handleElId = id;
+
+        
+        this.setDragElId(id);
+
+        
+        this.invalidHandleTypes = { A: "A" };
+        this.invalidHandleIds = {};
+        this.invalidHandleClasses = [];
+
+        this.applyConfig();
+
+        this.handleOnAvailable();
+    },
+
+    
+    applyConfig: function() {
+
+        
+        
+        this.padding           = this.config.padding || [0, 0, 0, 0];
+        this.isTarget          = (this.config.isTarget !== false);
+        this.maintainOffset    = (this.config.maintainOffset);
+        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
+
+    },
+
+    
+    handleOnAvailable: function() {
+        this.available = true;
+        this.resetConstraints();
+        this.onAvailable();
+    },
+
+    
+    setPadding: function(iTop, iRight, iBot, iLeft) {
+        
+        if (!iRight && 0 !== iRight) {
+            this.padding = [iTop, iTop, iTop, iTop];
+        } else if (!iBot && 0 !== iBot) {
+            this.padding = [iTop, iRight, iTop, iRight];
+        } else {
+            this.padding = [iTop, iRight, iBot, iLeft];
+        }
+    },
+
+    
+    setInitPosition: function(diffX, diffY) {
+        var el = this.getEl();
+
+        if (!this.DDMInstance.verifyEl(el)) {
+            return;
+        }
+
+        var dx = diffX || 0;
+        var dy = diffY || 0;
+
+        var p = Ext.Element.getXY( el );
+
+        this.initPageX = p[0] - dx;
+        this.initPageY = p[1] - dy;
+
+        this.lastPageX = p[0];
+        this.lastPageY = p[1];
+
+        this.setStartPosition(p);
+    },
+
+    
+    setStartPosition: function(pos) {
+        var p = pos || Ext.Element.getXY( this.getEl() );
+        this.deltaSetXY = null;
+
+        this.startPageX = p[0];
+        this.startPageY = p[1];
+    },
+
+    
+    addToGroup: function(sGroup) {
+        this.groups[sGroup] = true;
+        this.DDMInstance.regDragDrop(this, sGroup);
+    },
+
+    
+    removeFromGroup: function(sGroup) {
+        if (this.groups[sGroup]) {
+            delete this.groups[sGroup];
+        }
+
+        this.DDMInstance.removeDDFromGroup(this, sGroup);
+    },
+
+    
+    setDragElId: function(id) {
+        this.dragElId = id;
+    },
+
+    
+    setHandleElId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        this.handleElId = id;
+        this.DDMInstance.regHandle(this.id, id);
+    },
+
+    
+    setOuterHandleElId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
+        this.setHandleElId(id);
+
+        this.hasOuterHandles = true;
+    },
+
+    
+    unreg: function() {
+        Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
+        this._domRef = null;
+        this.DDMInstance._remove(this);
+    },
+
+    destroy : function(){
+        this.unreg();
+    },
+
+    
+    isLocked: function() {
+        return (this.DDMInstance.isLocked() || this.locked);
+    },
+
+    
+    handleMouseDown: function(e, oDD){
+        if (this.primaryButtonOnly && e.button != 0) {
+            return;
+        }
+
+        if (this.isLocked()) {
+            return;
+        }
+
+        this.DDMInstance.refreshCache(this.groups);
+
+        var pt = e.getPoint();
+        if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) )  {
+        } else {
+            if (this.clickValidator(e)) {
+                
+                this.setStartPosition();
+                this.b4MouseDown(e);
+                this.onMouseDown(e);
+
+                this.DDMInstance.handleMouseDown(e, this);
+
+                this.DDMInstance.stopEvent(e);
+            } else {
+
+
+            }
+        }
+    },
+
+    clickValidator: function(e) {
+        var target = e.getTarget();
+        return ( this.isValidHandleChild(target) &&
+                    (this.id == this.handleElId ||
+                        this.DDMInstance.handleWasClicked(target, this.id)) );
+    },
+
+    
+    addInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        this.invalidHandleTypes[type] = type;
+    },
+
+    
+    addInvalidHandleId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        this.invalidHandleIds[id] = id;
+    },
+
+    
+    addInvalidHandleClass: function(cssClass) {
+        this.invalidHandleClasses.push(cssClass);
+    },
+
+    
+    removeInvalidHandleType: function(tagName) {
+        var type = tagName.toUpperCase();
+        
+        delete this.invalidHandleTypes[type];
+    },
+
+    
+    removeInvalidHandleId: function(id) {
+        if (typeof id !== "string") {
+            id = Ext.id(id);
+        }
+        delete this.invalidHandleIds[id];
+    },
+
+    
+    removeInvalidHandleClass: function(cssClass) {
+        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
+            if (this.invalidHandleClasses[i] == cssClass) {
+                delete this.invalidHandleClasses[i];
+            }
+        }
+    },
+
+    
+    isValidHandleChild: function(node) {
+
+        var valid = true;
+        
+        var nodeName;
+        try {
+            nodeName = node.nodeName.toUpperCase();
+        } catch(e) {
+            nodeName = node.nodeName;
+        }
+        valid = valid && !this.invalidHandleTypes[nodeName];
+        valid = valid && !this.invalidHandleIds[node.id];
+
+        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
+            valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
+        }
+
+
+        return valid;
+
+    },
+
+    
+    setXTicks: function(iStartX, iTickSize) {
+        this.xTicks = [];
+        this.xTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.xTicks[this.xTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
+    },
+
+    
+    setYTicks: function(iStartY, iTickSize) {
+        this.yTicks = [];
+        this.yTickSize = iTickSize;
+
+        var tickMap = {};
+
+        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
+            if (!tickMap[i]) {
+                this.yTicks[this.yTicks.length] = i;
+                tickMap[i] = true;
+            }
+        }
+
+        Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
+    },
+
+    
+    setXConstraint: function(iLeft, iRight, iTickSize) {
+        this.leftConstraint = iLeft;
+        this.rightConstraint = iRight;
+
+        this.minX = this.initPageX - iLeft;
+        this.maxX = this.initPageX + iRight;
+        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+
+        this.constrainX = true;
+    },
+
+    
+    clearConstraints: function() {
+        this.constrainX = false;
+        this.constrainY = false;
+        this.clearTicks();
+    },
+
+    
+    clearTicks: function() {
+        this.xTicks = null;
+        this.yTicks = null;
+        this.xTickSize = 0;
+        this.yTickSize = 0;
+    },
+
+    
+    setYConstraint: function(iUp, iDown, iTickSize) {
+        this.topConstraint = iUp;
+        this.bottomConstraint = iDown;
+
+        this.minY = this.initPageY - iUp;
+        this.maxY = this.initPageY + iDown;
+        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
+
+        this.constrainY = true;
+
+    },
+
+    
+    resetConstraints: function() {
+        
+        if (this.initPageX || this.initPageX === 0) {
+            
+            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
+            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+
+            this.setInitPosition(dx, dy);
+
+        
+        } else {
+            this.setInitPosition();
+        }
+
+        if (this.constrainX) {
+            this.setXConstraint( this.leftConstraint,
+                                 this.rightConstraint,
+                                 this.xTickSize        );
+        }
+
+        if (this.constrainY) {
+            this.setYConstraint( this.topConstraint,
+                                 this.bottomConstraint,
+                                 this.yTickSize         );
+        }
+    },
+
+    
+    getTick: function(val, tickArray) {
+        if (!tickArray) {
+            
+            
+            return val;
+        } else if (tickArray[0] >= val) {
+            
+            
+            return tickArray[0];
+        } else {
+            for (var i=0, len=tickArray.length; i<len; ++i) {
+                var next = i + 1;
+                if (tickArray[next] && tickArray[next] >= val) {
+                    var diff1 = val - tickArray[i];
+                    var diff2 = tickArray[next] - val;
+                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
+                }
+            }
+
+            
+            
+            return tickArray[tickArray.length - 1];
+        }
+    },
+
+    
+    toString: function() {
+        return ("DragDrop " + this.id);
+    }
+
+});
+
+
+
+
+
+Ext.define('Ext.dd.DD', {
+    extend: 'Ext.dd.DragDrop',
+    requires: ['Ext.dd.DragDropManager'],
+
+    
+    constructor: function(id, sGroup, config) {
+        if (id) {
+            this.init(id, sGroup, config);
+        }
+    },
+
+    
+    scroll: true,
+
+    
+    autoOffset: function(iPageX, iPageY) {
+        var x = iPageX - this.startPageX;
+        var y = iPageY - this.startPageY;
+        this.setDelta(x, y);
+    },
+
+    
+    setDelta: function(iDeltaX, iDeltaY) {
+        this.deltaX = iDeltaX;
+        this.deltaY = iDeltaY;
+    },
+
+    
+    setDragElPos: function(iPageX, iPageY) {
+        
+        
+
+        var el = this.getDragEl();
+        this.alignElWithMouse(el, iPageX, iPageY);
+    },
+
+    
+    alignElWithMouse: function(el, iPageX, iPageY) {
+        var oCoord = this.getTargetCoord(iPageX, iPageY),
+            fly = el.dom ? el : Ext.fly(el, '_dd'),
+            elSize = fly.getSize(),
+            EL = Ext.Element,
+            vpSize;
+
+        if (!this.deltaSetXY) {
+            vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
+            var aCoord = [
+                Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
+                Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
+            ];
+            fly.setXY(aCoord);
+            var newLeft = fly.getLeft(true);
+            var newTop  = fly.getTop(true);
+            this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
+        } else {
+            vpSize = this.cachedViewportSize;
+            fly.setLeftTop(
+                Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
+                Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
+            );
+        }
+
+        this.cachePosition(oCoord.x, oCoord.y);
+        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+        return oCoord;
+    },
+
+    
+    cachePosition: function(iPageX, iPageY) {
+        if (iPageX) {
+            this.lastPageX = iPageX;
+            this.lastPageY = iPageY;
+        } else {
+            var aCoord = Ext.Element.getXY(this.getEl());
+            this.lastPageX = aCoord[0];
+            this.lastPageY = aCoord[1];
+        }
+    },
+
+    
+    autoScroll: function(x, y, h, w) {
+
+        if (this.scroll) {
+            
+            var clientH = Ext.Element.getViewHeight();
+
+            
+            var clientW = Ext.Element.getViewWidth();
+
+            
+            var st = this.DDMInstance.getScrollTop();
+
+            
+            var sl = this.DDMInstance.getScrollLeft();
+
+            
+            var bot = h + y;
+
+            
+            var right = w + x;
+
+            
+            
+            
+            var toBot = (clientH + st - y - this.deltaY);
+
+            
+            var toRight = (clientW + sl - x - this.deltaX);
+
+
+            
+            
+            var thresh = 40;
+
+            
+            
+            
+            var scrAmt = (document.all) ? 80 : 30;
+
+            
+            
+            if ( bot > clientH && toBot < thresh ) {
+                window.scrollTo(sl, st + scrAmt);
+            }
+
+            
+            
+            if ( y < st && st > 0 && y - st < thresh ) {
+                window.scrollTo(sl, st - scrAmt);
+            }
+
+            
+            
+            if ( right > clientW && toRight < thresh ) {
+                window.scrollTo(sl + scrAmt, st);
+            }
+
+            
+            
+            if ( x < sl && sl > 0 && x - sl < thresh ) {
+                window.scrollTo(sl - scrAmt, st);
+            }
+        }
+    },
+
+    
+    getTargetCoord: function(iPageX, iPageY) {
+        var x = iPageX - this.deltaX;
+        var y = iPageY - this.deltaY;
+
+        if (this.constrainX) {
+            if (x < this.minX) {
+                x = this.minX;
+            }
+            if (x > this.maxX) {
+                x = this.maxX;
+            }
+        }
+
+        if (this.constrainY) {
+            if (y < this.minY) {
+                y = this.minY;
+            }
+            if (y > this.maxY) {
+                y = this.maxY;
+            }
+        }
+
+        x = this.getTick(x, this.xTicks);
+        y = this.getTick(y, this.yTicks);
+
+
+        return {x: x, y: y};
+    },
+
+    
+    applyConfig: function() {
+        this.callParent();
+        this.scroll = (this.config.scroll !== false);
+    },
+
+    
+    b4MouseDown: function(e) {
+        
+        this.autoOffset(e.getPageX(), e.getPageY());
+    },
+
+    
+    b4Drag: function(e) {
+        this.setDragElPos(e.getPageX(), e.getPageY());
+    },
+
+    toString: function() {
+        return ("DD " + this.id);
+    }
+
+    
+    
+    
+    
+
+});
+
+
+
+
+Ext.define('Ext.dd.DDProxy', {
+    extend: 'Ext.dd.DD',
+
+    statics: {
+        
+        dragElId: "ygddfdiv"
+    },
+
+    
+    constructor: function(id, sGroup, config) {
+        if (id) {
+            this.init(id, sGroup, config);
+            this.initFrame();
+        }
+    },
+
+    
+    resizeFrame: true,
+
+    
+    centerFrame: false,
+
+    
+    createFrame: function() {
+        var self = this;
+        var body = document.body;
+
+        if (!body || !body.firstChild) {
+            setTimeout( function() { self.createFrame(); }, 50 );
+            return;
+        }
+
+        var div = this.getDragEl();
+
+        if (!div) {
+            div    = document.createElement("div");
+            div.id = this.dragElId;
+            var s  = div.style;
+
+            s.position   = "absolute";
+            s.visibility = "hidden";
+            s.cursor     = "move";
+            s.border     = "2px solid #aaa";
+            s.zIndex     = 999;
+
+            
+            
+            
+            body.insertBefore(div, body.firstChild);
+        }
+    },
+
+    
+    initFrame: function() {
+        this.createFrame();
+    },
+
+    applyConfig: function() {
+        this.callParent();
+
+        this.resizeFrame = (this.config.resizeFrame !== false);
+        this.centerFrame = (this.config.centerFrame);
+        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
+    },
+
+    
+    showFrame: function(iPageX, iPageY) {
+        var el = this.getEl();
+        var dragEl = this.getDragEl();
+        var s = dragEl.style;
+
+        this._resizeProxy();
+
+        if (this.centerFrame) {
+            this.setDelta( Math.round(parseInt(s.width,  10)/2),
+                           Math.round(parseInt(s.height, 10)/2) );
+        }
+
+        this.setDragElPos(iPageX, iPageY);
+
+        Ext.fly(dragEl).show();
+    },
+
+    
+    _resizeProxy: function() {
+        if (this.resizeFrame) {
+            var el = this.getEl();
+            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
+        }
+    },
+
+    
+    b4MouseDown: function(e) {
+        var x = e.getPageX();
+        var y = e.getPageY();
+        this.autoOffset(x, y);
+        this.setDragElPos(x, y);
+    },
+
+    
+    b4StartDrag: function(x, y) {
+        
+        this.showFrame(x, y);
+    },
+
+    
+    b4EndDrag: function(e) {
+        Ext.fly(this.getDragEl()).hide();
+    },
+
+    
+    
+    
+    endDrag: function(e) {
+
+        var lel = this.getEl();
+        var del = this.getDragEl();
+
+        
+        del.style.visibility = "";
+
+        this.beforeMove();
+        
+        
+        lel.style.visibility = "hidden";
+        Ext.dd.DDM.moveToEl(lel, del);
+        del.style.visibility = "hidden";
+        lel.style.visibility = "";
+
+        this.afterDrag();
+    },
+
+    beforeMove : function(){
+
+    },
+
+    afterDrag : function(){
+
+    },
+
+    toString: function() {
+        return ("DDProxy " + this.id);
+    }
+
+});
+
+
+Ext.define('Ext.dd.DragSource', {
+    extend: 'Ext.dd.DDProxy',
+    requires: [
+        'Ext.dd.StatusProxy',
+        'Ext.dd.DragDropManager'
+    ],
+
+    
+
+    
+    dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
+    
+    dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+    
+    animRepair: true,
+
+    
+    repairHighlightColor: 'c3daf9',
+
+    
+    constructor: function(el, config) {
+        this.el = Ext.get(el);
+        if(!this.dragData){
+            this.dragData = {};
+        }
+
+        Ext.apply(this, config);
+
+        if(!this.proxy){
+            this.proxy = Ext.create('Ext.dd.StatusProxy', {
+                animRepair: this.animRepair
+            });
+        }
+        this.callParent([this.el.dom, this.ddGroup || this.group,
+              {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true}]);
+
+        this.dragging = false;
+    },
+
+    
+    getDragData : function(e){
+        return this.dragData;
+    },
+
+    
+    onDragEnter : function(e, id){
+        var target = Ext.dd.DragDropManager.getDDById(id);
+        this.cachedTarget = target;
+        if (this.beforeDragEnter(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                var status = target.notifyEnter(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            } else {
+                this.proxy.setStatus(this.dropAllowed);
+            }
+
+            if (this.afterDragEnter) {
+                
+                this.afterDragEnter(target, e, id);
+            }
+        }
+    },
+
+    
+    beforeDragEnter: function(target, e, id) {
+        return true;
+    },
+
+    
+    alignElWithMouse: function() {
+        this.callParent(arguments);
+        this.proxy.sync();
+    },
+
+    
+    onDragOver: function(e, id) {
+        var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+        if (this.beforeDragOver(target, e, id) !== false) {
+            if(target.isNotifyTarget){
+                var status = target.notifyOver(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }
+
+            if (this.afterDragOver) {
+                
+                this.afterDragOver(target, e, id);
+            }
+        }
+    },
+
+    
+    beforeDragOver: function(target, e, id) {
+        return true;
+    },
+
+    
+    onDragOut: function(e, id) {
+        var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+        if (this.beforeDragOut(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                target.notifyOut(this, e, this.dragData);
+            }
+            this.proxy.reset();
+            if (this.afterDragOut) {
+                
+                this.afterDragOut(target, e, id);
+            }
+        }
+        this.cachedTarget = null;
+    },
+
+    
+    beforeDragOut: function(target, e, id){
+        return true;
+    },
+
+    
+    onDragDrop: function(e, id){
+        var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+        if (this.beforeDragDrop(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                if (target.notifyDrop(this, e, this.dragData) !== false) { 
+                    this.onValidDrop(target, e, id);
+                } else {
+                    this.onInvalidDrop(target, e, id);
+                }
+            } else {
+                this.onValidDrop(target, e, id);
+            }
+
+            if (this.afterDragDrop) {
+                
+                this.afterDragDrop(target, e, id);
+            }
+        }
+        delete this.cachedTarget;
+    },
+
+    
+    beforeDragDrop: function(target, e, id){
+        return true;
+    },
+
+    
+    onValidDrop: function(target, e, id){
+        this.hideProxy();
+        if(this.afterValidDrop){
+            
+            this.afterValidDrop(target, e, id);
+        }
+    },
+
+    
+    getRepairXY: function(e, data){
+        return this.el.getXY();
+    },
+
+    
+    onInvalidDrop: function(target, e, id) {
+        this.beforeInvalidDrop(target, e, id);
+        if (this.cachedTarget) {
+            if(this.cachedTarget.isNotifyTarget){
+                this.cachedTarget.notifyOut(this, e, this.dragData);
+            }
+            this.cacheTarget = null;
+        }
+        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
+
+        if (this.afterInvalidDrop) {
+            
+            this.afterInvalidDrop(e, id);
+        }
+    },
+
+    
+    afterRepair: function() {
+        var me = this;
+        if (Ext.enableFx) {
+            me.el.highlight(me.repairHighlightColor);
+        }
+        me.dragging = false;
+    },
+
+    
+    beforeInvalidDrop: function(target, e, id) {
+        return true;
+    },
+
+    
+    handleMouseDown: function(e) {
+        if (this.dragging) {
+            return;
+        }
+        var data = this.getDragData(e);
+        if (data && this.onBeforeDrag(data, e) !== false) {
+            this.dragData = data;
+            this.proxy.stop();
+            this.callParent(arguments);
+        }
+    },
+
+    
+    onBeforeDrag: function(data, e){
+        return true;
+    },
+
+    
+    onStartDrag: Ext.emptyFn,
+
+    
+    startDrag: function(x, y) {
+        this.proxy.reset();
+        this.dragging = true;
+        this.proxy.update("");
+        this.onInitDrag(x, y);
+        this.proxy.show();
+    },
+
+    
+    onInitDrag: function(x, y) {
+        var clone = this.el.dom.cloneNode(true);
+        clone.id = Ext.id(); 
+        this.proxy.update(clone);
+        this.onStartDrag(x, y);
+        return true;
+    },
+
+    
+    getProxy: function() {
+        return this.proxy;
+    },
+
+    
+    hideProxy: function() {
+        this.proxy.hide();
+        this.proxy.reset(true);
+        this.dragging = false;
+    },
+
+    
+    triggerCacheRefresh: function() {
+        Ext.dd.DDM.refreshCache(this.groups);
+    },
+
+    
+    b4EndDrag: function(e) {
+    },
+
+    
+    endDrag : function(e){
+        this.onEndDrag(this.dragData, e);
+    },
+
+    
+    onEndDrag : function(data, e){
+    },
+
+    
+    autoOffset : function(x, y) {
+        this.setDelta(-12, -20);
+    },
+
+    destroy: function(){
+        this.callParent();
+        Ext.destroy(this.proxy);
+    }
+});
+
+
+Ext.define('Ext.panel.DD', {
+    extend: 'Ext.dd.DragSource',
+    requires: ['Ext.panel.Proxy'],
+
+    constructor : function(panel, cfg){
+        this.panel = panel;
+        this.dragData = {panel: panel};
+        this.proxy = Ext.create('Ext.panel.Proxy', panel, cfg);
+
+        this.callParent([panel.el, cfg]);
+
+        Ext.defer(function() {
+            var header = panel.header,
+                el = panel.body;
+
+            if(header){
+                this.setHandleElId(header.id);
+                el = header.el;
+            }
+            el.setStyle('cursor', 'move');
+            this.scroll = false;
+        }, 200, this);
+    },
+
+    showFrame: Ext.emptyFn,
+    startDrag: Ext.emptyFn,
+    b4StartDrag: function(x, y) {
+        this.proxy.show();
+    },
+    b4MouseDown: function(e) {
+        var x = e.getPageX(),
+            y = e.getPageY();
+        this.autoOffset(x, y);
+    },
+    onInitDrag : function(x, y){
+        this.onStartDrag(x, y);
+        return true;
+    },
+    createFrame : Ext.emptyFn,
+    getDragEl : function(e){
+        return this.proxy.ghost.el.dom;
+    },
+    endDrag : function(e){
+        this.proxy.hide();
+        this.panel.saveState();
+    },
+
+    autoOffset : function(x, y) {
+        x -= this.startPageX;
+        y -= this.startPageY;
+        this.setDelta(x, y);
+    }
+});
+
+
+Ext.define('Ext.layout.component.Dock', {
+
+    
+
+    alias: ['layout.dock'],
+
+    extend: 'Ext.layout.component.AbstractDock'
+
+    
+
+});
+
+Ext.define('Ext.panel.Panel', {
+    extend: 'Ext.panel.AbstractPanel',
+    requires: [
+        'Ext.panel.Header',
+        'Ext.fx.Anim',
+        'Ext.util.KeyMap',
+        'Ext.panel.DD',
+        'Ext.XTemplate',
+        'Ext.layout.component.Dock',
+        'Ext.util.Memento'
+    ],
+    alias: 'widget.panel',
+    alternateClassName: 'Ext.Panel',
+
+    
+    collapsedCls: 'collapsed',
+
+    
+    animCollapse: Ext.enableFx,
+
+    
+    minButtonWidth: 75,
+
+    
+    collapsed: false,
+
+    
+    collapseFirst: true,
+
+    
+    hideCollapseTool: false,
+
+    
+    titleCollapse: false,
+
+    
+
+    
+
+    
+    floatable: true,
+
+    
+
+    
+    collapsible: false,
+
+    
+
+    
+    closable: false,
+
+    
+    closeAction: 'destroy',
+
+    
+
+    
+    preventHeader: false,
+
+     
+    headerPosition: 'top',
+
+     
+    frame: false,
+
+    
+    frameHeader: true,
+
+    
+
+    
+
+    
+
+    initComponent: function() {
+        var me = this,
+            cls;
+
+        me.addEvents(
+
+            
+            'beforeclose',
+
+            
+            "beforeexpand",
+
+            
+            "beforecollapse",
+
+            
+            "expand",
+
+            
+            "collapse",
+
+            
+            'titlechange',
+
+            
+            'iconchange'
+        );
+
+        
+        this.addStateEvents('expand', 'collapse');
+
+        if (me.unstyled) {
+            me.setUI('plain');
+        }
+
+        if (me.frame) {
+            me.setUI(me.ui + '-framed');
+        }
+
+        
+        me.bridgeToolbars();
+
+        me.callParent();
+        me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
+    },
+
+    setBorder: function(border) {
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+
+        this.callParent(arguments);
+    },
+
+    beforeDestroy: function() {
+        Ext.destroy(
+            this.ghostPanel,
+            this.dd
+        );
+        this.callParent();
+    },
+
+    initAria: function() {
+        this.callParent();
+        this.initHeaderAria();
+    },
+
+    initHeaderAria: function() {
+        var me = this,
+            el = me.el,
+            header = me.header;
+        if (el && header) {
+            el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
+        }
+    },
+
+    getHeader: function() {
+        return this.header;
+    },
+
+    
+    setTitle: function(newTitle) {
+        var me = this,
+        oldTitle = this.title;
+
+        me.title = newTitle;
+        if (me.header) {
+            me.header.setTitle(newTitle);
+        } else {
+            me.updateHeader();
+        }
+
+        if (me.reExpander) {
+            me.reExpander.setTitle(newTitle);
+        }
+        me.fireEvent('titlechange', me, newTitle, oldTitle);
+    },
+
+    
+    setIconCls: function(newIconCls) {
+        var me = this,
+            oldIconCls = me.iconCls;
+
+        me.iconCls = newIconCls;
+        var header = me.header;
+        if (header) {
+            header.setIconCls(newIconCls);
+        }
+        me.fireEvent('iconchange', me, newIconCls, oldIconCls);
+    },
+
+    bridgeToolbars: function() {
+        var me = this,
+            docked = [],
+            fbar,
+            fbarDefaults,
+            minButtonWidth = me.minButtonWidth;
+
+        function initToolbar (toolbar, pos, useButtonAlign) {
+            if (Ext.isArray(toolbar)) {
+                toolbar = {
+                    xtype: 'toolbar',
+                    items: toolbar
+                };
+            }
+            else if (!toolbar.xtype) {
+                toolbar.xtype = 'toolbar';
+            }
+            toolbar.dock = pos;
+            if (pos == 'left' || pos == 'right') {
+                toolbar.vertical = true;
+            }
+
+            
+            if (useButtonAlign) {
+                toolbar.layout = Ext.applyIf(toolbar.layout || {}, {
+                    
+                    pack: { left:'start', center:'center' }[me.buttonAlign] || 'end'
+                });
+            }
+            return toolbar;
+        }
+
+        
+
+        
+
+        
+        if (me.tbar) {
+            docked.push(initToolbar(me.tbar, 'top'));
+            me.tbar = null;
+        }
+
+        
+        if (me.bbar) {
+            docked.push(initToolbar(me.bbar, 'bottom'));
+            me.bbar = null;
+        }
+
+        
+        if (me.buttons) {
+            me.fbar = me.buttons;
+            me.buttons = null;
+        }
+
+        
+        if (me.fbar) {
+            fbar = initToolbar(me.fbar, 'bottom', true); 
+            fbar.ui = 'footer';
+
+            
+            if (minButtonWidth) {
+                fbarDefaults = fbar.defaults;
+                fbar.defaults = function(config) {
+                    var defaults = fbarDefaults || {};
+                    if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) &&
+                            !('minWidth' in defaults)) {
+                        defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
+                    }
+                    return defaults;
+                };
+            }
+
+            docked.push(fbar);
+            me.fbar = null;
+        }
+
+        
+        if (me.lbar) {
+            docked.push(initToolbar(me.lbar, 'left'));
+            me.lbar = null;
+        }
+
+        
+        if (me.rbar) {
+            docked.push(initToolbar(me.rbar, 'right'));
+            me.rbar = null;
+        }
+
+        if (me.dockedItems) {
+            if (!Ext.isArray(me.dockedItems)) {
+                me.dockedItems = [me.dockedItems];
+            }
+            me.dockedItems = me.dockedItems.concat(docked);
+        } else {
+            me.dockedItems = docked;
+        }
+    },
+
+    
+    initTools: function() {
+        var me = this;
+
+        me.tools = me.tools ? Ext.Array.clone(me.tools) : [];
+
+        
+        
+        if (me.collapsible && !(me.hideCollapseTool || me.header === false)) {
+            me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
+            me.collapseTool = me.expandTool = me.createComponent({
+                xtype: 'tool',
+                type: 'collapse-' + me.collapseDirection,
+                expandType: me.getOppositeDirection(me.collapseDirection),
+                handler: me.toggleCollapse,
+                scope: me
+            });
+
+            
+            if (me.collapseFirst) {
+                me.tools.unshift(me.collapseTool);
+            }
+        }
+
+        
+        me.addTools();
+
+        
+        if (me.closable) {
+            me.addClsWithUI('closable');
+            me.addTool({
+                type: 'close',
+                handler: Ext.Function.bind(me.close, this, [])
+            });
+        }
+
+        
+        if (me.collapseTool && !me.collapseFirst) {
+            me.tools.push(me.collapseTool);
+        }
+    },
+
+    
+    addTools: Ext.emptyFn,
+
+    
+    close: function() {
+        if (this.fireEvent('beforeclose', this) !== false) {
+            this.doClose();
+        }
+    },
+
+    
+    doClose: function() {
+        this.fireEvent('close', this);
+        this[this.closeAction]();
+    },
+
+    onRender: function(ct, position) {
+        var me = this,
+            topContainer;
+
+        
+        
+        me.initTools();
+
+        
+        me.updateHeader();
+
+        
+        me.callParent(arguments);
+    },
+
+    afterRender: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        
+        
+        
+        if (me.collapsed) {
+            me.collapsed = false;
+            me.collapse(null, false, true);
+        }
+    },
+
+    
+    updateHeader: function(force) {
+        var me = this,
+            header = me.header,
+            title = me.title,
+            tools = me.tools;
+
+        if (!me.preventHeader && (force || title || (tools && tools.length))) {
+            if (!header) {
+                header = me.header = Ext.create('Ext.panel.Header', {
+                    title       : title,
+                    orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
+                    dock        : me.headerPosition || 'top',
+                    textCls     : me.headerTextCls,
+                    iconCls     : me.iconCls,
+                    baseCls     : me.baseCls + '-header',
+                    tools       : tools,
+                    ui          : me.ui,
+                    indicateDrag: me.draggable,
+                    border      : me.border,
+                    frame       : me.frame && me.frameHeader,
+                    ignoreParentFrame : me.frame || me.overlapHeader,
+                    ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
+                    listeners   : me.collapsible && me.titleCollapse ? {
+                        click: me.toggleCollapse,
+                        scope: me
+                    } : null
+                });
+                me.addDocked(header, 0);
+
+                
+                
+                me.tools = header.tools;
+            }
+            header.show();
+            me.initHeaderAria();
+        } else if (header) {
+            header.hide();
+        }
+    },
+
+    
+    setUI: function(ui) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        if (me.header) {
+            me.header.setUI(ui);
+        }
+    },
+
+    
+    getContentTarget: function() {
+        return this.body;
+    },
+
+    getTargetEl: function() {
+        return this.body || this.frameBody || this.el;
+    },
+
+    
+
+    
+    isVisible: function(deep){
+        var me = this;
+        if (me.collapsed && me.placeholder) {
+            return me.placeholder.isVisible(deep);
+        }
+        return me.callParent(arguments);
+    },
+
+    
+    onHide: function(){
+        var me = this;
+        if (me.collapsed && me.placeholder) {
+            me.placeholder.hide();
+        } else {
+            me.callParent(arguments);
+        }
+    },
+
+    
+    onShow: function(){
+        var me = this;
+        if (me.collapsed && me.placeholder) {
+            
+            me.hidden = true;
+            me.placeholder.show();
+        } else {
+            me.callParent(arguments);
+        }
+    },
+
+    addTool: function(tool) {
+        var me = this,
+            header = me.header;
+
+        if (Ext.isArray(tool)) {
+            Ext.each(tool, me.addTool, me);
+            return;
+        }
+        me.tools.push(tool);
+        if (header) {
+            header.addTool(tool);
+        }
+        me.updateHeader();
+    },
+
+    getOppositeDirection: function(d) {
+        var c = Ext.Component;
+        switch (d) {
+            case c.DIRECTION_TOP:
+                return c.DIRECTION_BOTTOM;
+            case c.DIRECTION_RIGHT:
+                return c.DIRECTION_LEFT;
+            case c.DIRECTION_BOTTOM:
+                return c.DIRECTION_TOP;
+            case c.DIRECTION_LEFT:
+                return c.DIRECTION_RIGHT;
+        }
+    },
+
+    
+    collapse: function(direction, animate,  internal) {
+        var me = this,
+            c = Ext.Component,
+            height = me.getHeight(),
+            width = me.getWidth(),
+            frameInfo,
+            newSize = 0,
+            dockedItems = me.dockedItems.items,
+            dockedItemCount = dockedItems.length,
+            i = 0,
+            comp,
+            pos,
+            anim = {
+                from: {
+                    height: height,
+                    width: width
+                },
+                to: {
+                    height: height,
+                    width: width
+                },
+                listeners: {
+                    afteranimate: me.afterCollapse,
+                    scope: me
+                },
+                duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
+            },
+            reExpander,
+            reExpanderOrientation,
+            reExpanderDock,
+            getDimension,
+            collapseDimension;
+
+        if (!direction) {
+            direction = me.collapseDirection;
+        }
+
+        
+        if (internal) {
+            animate = false;
+        } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
+            return false;
+        }
+
+        reExpanderDock = direction;
+        me.expandDirection = me.getOppositeDirection(direction);
+
+        
+        me.hiddenDocked = [];
+
+        switch (direction) {
+            case c.DIRECTION_TOP:
+            case c.DIRECTION_BOTTOM:
+                reExpanderOrientation = 'horizontal';
+                collapseDimension = 'height';
+                getDimension = 'getHeight';
+
+                
+                
+                for (; i < dockedItemCount; i++) {
+                    comp = dockedItems[i];
+                    if (comp.isVisible()) {
+                        if (comp.isXType('header', true) && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
+                            reExpander = comp;
+                        } else {
+                            me.hiddenDocked.push(comp);
+                        }
+                    } else if (comp === me.reExpander) {
+                        reExpander = comp;
+                    }
+                }
+
+                if (direction == Ext.Component.DIRECTION_BOTTOM) {
+                    pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
+                    anim.from.top = pos;
+                }
+                break;
+
+            case c.DIRECTION_LEFT:
+            case c.DIRECTION_RIGHT:
+                reExpanderOrientation = 'vertical';
+                collapseDimension = 'width';
+                getDimension = 'getWidth';
+
+                
+                
+                for (; i < dockedItemCount; i++) {
+                    comp = dockedItems[i];
+                    if (comp.isVisible()) {
+                        if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
+                            reExpander = comp;
+                        } else {
+                            me.hiddenDocked.push(comp);
+                        }
+                    } else if (comp === me.reExpander) {
+                        reExpander = comp;
+                    }
+                }
+
+                if (direction == Ext.Component.DIRECTION_RIGHT) {
+                    pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
+                    anim.from.left = pos;
+                }
+                break;
+
+            default:
+                throw('Panel collapse must be passed a valid Component collapse direction');
+        }
+
+        
+        if (animate && me.collapseTool) {
+            me.collapseTool.disable();
+        }
+
+        
+        me.addClsWithUI(me.collapsedCls);
+        
+        
+        
+
+        
+        if (reExpander && reExpander.rendered) {
+
+            
+            reExpander.addClsWithUI(me.collapsedCls);
+            reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
+            if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+                reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
+            }
+
+            frameInfo = reExpander.getFrameInfo();
+
+            
+            newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
+
+            
+            reExpander.removeClsWithUI(me.collapsedCls);
+            reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);
+            if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+                reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
+            }
+        }
+        
+        else {
+            reExpander = {
+                hideMode: 'offsets',
+                temporary: true,
+                title: me.title,
+                orientation: reExpanderOrientation,
+                dock: reExpanderDock,
+                textCls: me.headerTextCls,
+                iconCls: me.iconCls,
+                baseCls: me.baseCls + '-header',
+                ui: me.ui,
+                frame: me.frame && me.frameHeader,
+                ignoreParentFrame: me.frame || me.overlapHeader,
+                indicateDrag: me.draggable,
+                cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
+                renderTo: me.el
+            };
+            if (!me.hideCollapseTool) {
+                reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
+                    xtype: 'tool',
+                    type: 'expand-' + me.expandDirection,
+                    handler: me.toggleCollapse,
+                    scope: me
+                }];
+            }
+
+            
+            
+            reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
+            newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
+            reExpander.hide();
+
+            
+            me.insertDocked(0, reExpander);
+        }
+
+        me.reExpander = reExpander;
+        me.reExpander.addClsWithUI(me.collapsedCls);
+        me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
+        if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+            me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
+        }
+
+        
+        if (direction == Ext.Component.DIRECTION_RIGHT) {
+            anim.to.left = pos + (width - newSize);
+        } else if (direction == Ext.Component.DIRECTION_BOTTOM) {
+            anim.to.top = pos + (height - newSize);
+        }
+
+        
+        anim.to[collapseDimension] = newSize;
+
+        
+        
+        
+        
+        
+        if (!me.collapseMemento) {
+            me.collapseMemento = new Ext.util.Memento(me);
+        }
+        me.collapseMemento.capture(['width', 'height', 'minWidth', 'minHeight', 'layoutManagedHeight', 'layoutManagedWidth']);
+
+        
+        me.savedFlex = me.flex;
+        me.minWidth = 0;
+        me.minHeight = 0;
+        delete me.flex;
+        me.suspendLayout = true;
+
+        if (animate) {
+            me.animate(anim);
+        } else {
+            me.setSize(anim.to.width, anim.to.height);
+            if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
+                me.setPosition(anim.to.left, anim.to.top);
+            }
+            me.afterCollapse(false, internal);
+        }
+        return me;
+    },
+
+    afterCollapse: function(animated, internal) {
+        var me = this,
+            i = 0,
+            l = me.hiddenDocked.length;
+
+        me.collapseMemento.restore(['minWidth', 'minHeight']);
+
+        
+        
+        
+        if (Ext.Component.VERTICAL_DIRECTION_Re.test(me.expandDirection)) {
+            me.layoutManagedHeight = 2;
+            me.collapseMemento.restore('width', false);
+        } else {
+            me.layoutManagedWidth = 2;
+            me.collapseMemento.restore('height', false);
+        }
+
+        
+        
+        me.saveScrollTop = me.body.dom.scrollTop;
+        me.body.setStyle('display', 'none');
+
+        for (; i < l; i++) {
+            me.hiddenDocked[i].hide();
+        }
+        if (me.reExpander) {
+            me.reExpander.updateFrame();
+            me.reExpander.show();
+        }
+        me.collapsed = true;
+        me.suspendLayout = false;
+
+        if (!internal) {
+            if (me.ownerCt) {
+                
+                
+                if (animated) {
+                    me.ownerCt.layout.layout();
+                }
+            } else if (me.reExpander.temporary) {
+                me.doComponentLayout();
+            }
+        }
+
+        if (me.resizer) {
+            me.resizer.disable();
+        }
+
+        
+        if (me.collapseTool) {
+            me.collapseTool.setType('expand-' + me.expandDirection);
+        }
+        if (!internal) {
+            me.fireEvent('collapse', me);
+        }
+
+        
+        if (animated && me.collapseTool) {
+            me.collapseTool.enable();
+        }
+    },
+
+    
+    expand: function(animate) {
+        var me = this;
+        if (!me.collapsed || me.fireEvent('beforeexpand', me, animate) === false) {
+            return false;
+        }
+
+        var i = 0,
+            l = me.hiddenDocked.length,
+            direction = me.expandDirection,
+            height = me.getHeight(),
+            width = me.getWidth(),
+            pos, anim;
+
+        
+        if (animate && me.collapseTool) {
+            me.collapseTool.disable();
+        }
+
+        
+        
+        for (; i < l; i++) {
+            me.hiddenDocked[i].hidden = false;
+            me.hiddenDocked[i].el.show();
+        }
+        if (me.reExpander) {
+            if (me.reExpander.temporary) {
+                me.reExpander.hide();
+            } else {
+                me.reExpander.removeClsWithUI(me.collapsedCls);
+                me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
+                if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
+                    me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
+                }
+                me.reExpander.updateFrame();
+            }
+        }
+
+        
+        if (me.collapseTool) {
+            me.collapseTool.setType('collapse-' + me.collapseDirection);
+        }
+
+        
+        me.body.setStyle('display', '');
+        me.body.dom.scrollTop = me.saveScrollTop;
+
+        
+        me.collapsed = false;
+
+        
+        me.removeClsWithUI(me.collapsedCls);
+        
+        
+        
+
+        anim = {
+            to: {
+            },
+            from: {
+                height: height,
+                width: width
+            },
+            listeners: {
+                afteranimate: me.afterExpand,
+                scope: me
+            }
+        };
+
+        if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
+
+            
+            
+            me.collapseMemento.restore('height', false);
+
+            
+            if (me.height === undefined) {
+                me.setCalculatedSize(me.width, null);
+                anim.to.height = me.getHeight();
+
+                
+                me.setCalculatedSize(me.width, anim.from.height);
+            }
+            
+            
+            else if (me.savedFlex) {
+                me.flex = me.savedFlex;
+                anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
+                delete me.flex;
+            }
+            
+            else {
+                anim.to.height = me.height;
+            }
+
+            
+            if (direction == Ext.Component.DIRECTION_TOP) {
+                pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
+                anim.from.top = pos;
+                anim.to.top = pos - (anim.to.height - height);
+            }
+        } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
+
+            
+            
+            me.collapseMemento.restore('width', false);
+
+            
+            if (me.width === undefined) {
+                me.setCalculatedSize(null, me.height);
+                anim.to.width = me.getWidth();
+
+                
+                me.setCalculatedSize(anim.from.width, me.height);
+            }
+            
+            
+            else if (me.savedFlex) {
+                me.flex = me.savedFlex;
+                anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
+                delete me.flex;
+            }
+            
+            else {
+                anim.to.width = me.width;
+            }
+
+            
+            if (direction == Ext.Component.DIRECTION_LEFT) {
+                pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
+                anim.from.left = pos;
+                anim.to.left = pos - (anim.to.width - width);
+            }
+        }
+
+        if (animate) {
+            me.animate(anim);
+        } else {
+            me.setCalculatedSize(anim.to.width, anim.to.height);
+            if (anim.to.x) {
+                me.setLeft(anim.to.x);
+            }
+            if (anim.to.y) {
+                me.setTop(anim.to.y);
+            }
+            me.afterExpand(false);
+        }
+
+        return me;
+    },
+
+    afterExpand: function(animated) {
+        var me = this;
+
+        
+        if (me.savedFlex) {
+            me.flex = me.savedFlex;
+            delete me.savedFlex;
+            delete me.width;
+            delete me.height;
+        }
+
+        
+        if (me.collapseMemento) {
+            me.collapseMemento.restoreAll();
+        }
+
+        if (animated && me.ownerCt) {
+            
+            
+            Ext.defer(me.ownerCt.doLayout, Ext.isIE6 ? 1 : 0, me);
+        }
+
+        if (me.resizer) {
+            me.resizer.enable();
+        }
+
+        me.fireEvent('expand', me);
+
+        
+        if (animated && me.collapseTool) {
+            me.collapseTool.enable();
+        }
+    },
+
+    
+    toggleCollapse: function() {
+        if (this.collapsed) {
+            this.expand(this.animCollapse);
+        } else {
+            this.collapse(this.collapseDirection, this.animCollapse);
+        }
+        return this;
+    },
+
+    
+    getKeyMap : function(){
+        if(!this.keyMap){
+            this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
+        }
+        return this.keyMap;
+    },
+
+    
+    initDraggable : function(){
+        
+        this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
+    },
+
+    
+    ghostTools : function() {
+        var tools = [],
+            headerTools = this.header.query('tool[hidden=false]');
+
+        if (headerTools.length) {
+            Ext.each(headerTools, function(tool) {
+                
+                
+                
+                
+                tools.push({
+                    type: tool.type
+                });
+            });
+        } else {
+            tools = [{
+                type: 'placeholder'
+            }];
+        }
+        return tools;
+    },
+
+    
+    ghost: function(cls) {
+        var me = this,
+            ghostPanel = me.ghostPanel,
+            box = me.getBox(),
+            header;
+
+        if (!ghostPanel) {
+            ghostPanel = Ext.create('Ext.panel.Panel', {
+                renderTo: me.floating ? me.el.dom.parentNode : document.body,
+                floating: {
+                    shadow: false
+                },
+                frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
+                overlapHeader: me.overlapHeader,
+                headerPosition: me.headerPosition,
+                baseCls: me.baseCls,
+                cls: me.baseCls + '-ghost ' + (cls ||'')
+            });
+            me.ghostPanel = ghostPanel;
+        }
+        ghostPanel.floatParent = me.floatParent;
+        if (me.floating) {
+            ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
+        } else {
+            ghostPanel.toFront();
+        }
+        header = ghostPanel.header;
+        
+        if (header) {
+            header.suspendLayout = true;
+            Ext.Array.forEach(header.query('tool'), function(tool){
+                header.remove(tool);
+            });
+            header.suspendLayout = false;
+        }
+        ghostPanel.addTool(me.ghostTools());
+        ghostPanel.setTitle(me.title);
+        ghostPanel.setIconCls(me.iconCls);
+
+        ghostPanel.el.show();
+        ghostPanel.setPosition(box.x, box.y);
+        ghostPanel.setSize(box.width, box.height);
+        me.el.hide();
+        if (me.floatingItems) {
+            me.floatingItems.hide();
+        }
+        return ghostPanel;
+    },
+
+    
+    unghost: function(show, matchPosition) {
+        var me = this;
+        if (!me.ghostPanel) {
+            return;
+        }
+        if (show !== false) {
+            me.el.show();
+            if (matchPosition !== false) {
+                me.setPosition(me.ghostPanel.getPosition());
+            }
+            if (me.floatingItems) {
+                me.floatingItems.show();
+            }
+            Ext.defer(me.focus, 10, me);
+        }
+        me.ghostPanel.el.hide();
+    },
+
+    initResizable: function(resizable) {
+        if (this.collapsed) {
+            resizable.disabled = true;
+        }
+        this.callParent([resizable]);
+    }
+}, function(){
+    this.prototype.animCollapse = Ext.enableFx;
+});
+
+
+
+Ext.define('Ext.layout.component.Tip', {
+
+    
+
+    alias: ['layout.tip'],
+
+    extend: 'Ext.layout.component.Dock',
+
+    
+
+    type: 'tip',
+    
+    onLayout: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            el = owner.el,
+            minWidth,
+            maxWidth,
+            naturalWidth,
+            constrainedWidth,
+            xy = el.getXY();
+
+        
+        el.setXY([-9999,-9999]);
+
+        
+        this.callParent(arguments);
+
+        
+        if (!Ext.isNumber(width)) {
+            minWidth = owner.minWidth;
+            maxWidth = owner.maxWidth;
+            
+            if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
+                constrainedWidth = me.doAutoWidth();
+            } else {
+                naturalWidth = el.getWidth();
+            }
+            if (naturalWidth < minWidth) {
+                constrainedWidth = minWidth;
+            }
+            else if (naturalWidth > maxWidth) {
+                constrainedWidth = maxWidth;
+            }
+            if (constrainedWidth) {
+                this.callParent([constrainedWidth, height]);
+            }
+        }
+
+        
+        el.setXY(xy);
+    },
+    
+    doAutoWidth: function(){
+        var me = this,
+            owner = me.owner,
+            body = owner.body,
+            width = body.getTextWidth();
+            
+        if (owner.header) {
+            width = Math.max(width, owner.header.getWidth());
+        }
+        if (!Ext.isDefined(me.frameWidth)) {
+            me.frameWidth = owner.el.getWidth() - body.getWidth();
+        }
+        width += me.frameWidth + body.getPadding('lr');
+        return width;
+    }
+});
+
+
+Ext.define('Ext.tip.Tip', {
+    extend: 'Ext.panel.Panel',
+    requires: [ 'Ext.layout.component.Tip' ],
+    alternateClassName: 'Ext.Tip',
+    
+    
+    
+    minWidth : 40,
+    
+    maxWidth : 300,
+    
+    shadow : "sides",
+
+    
+    defaultAlign : "tl-bl?",
+    
+    constrainPosition : true,
+
+    
+    frame: false,
+
+    
+    autoRender: true,
+    hidden: true,
+    baseCls: Ext.baseCSSPrefix + 'tip',
+    floating: {
+        shadow: true,
+        shim: true,
+        constrain: true
+    },
+    focusOnToFront: false,
+    componentLayout: 'tip',
+
+    
+    closeAction: 'hide',
+
+    ariaRole: 'tooltip',
+
+    initComponent: function() {
+        var me = this;
+
+        me.floating = Ext.apply({}, {shadow: me.shadow}, me.self.prototype.floating);
+        me.callParent(arguments);
+
+        
+        me.constrain = me.constrain || me.constrainPosition;
+    },
+
+    
+    showAt : function(xy){
+        var me = this;
+        this.callParent(arguments);
+        
+        if (me.isVisible()) {
+            me.setPagePosition(xy[0], xy[1]);
+            if (me.constrainPosition || me.constrain) {
+                me.doConstrain();
+            }
+            me.toFront(true);
+        }
+    },
+
+    
+    showBy : function(el, pos) {
+        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
+    },
+
+    
+    initDraggable : function(){
+        var me = this;
+        me.draggable = {
+            el: me.getDragEl(),
+            delegate: me.header.el,
+            constrain: me,
+            constrainTo: me.el.getScopeParent()
+        };
+        
+        Ext.Component.prototype.initDraggable.call(me);
+    },
+
+    
+    ghost: undefined,
+    unghost: undefined
+});
+
+
+Ext.define('Ext.tip.ToolTip', {
+    extend: 'Ext.tip.Tip',
+    alias: 'widget.tooltip',
+    alternateClassName: 'Ext.ToolTip',
+    
+    
+    
+    
+    showDelay: 500,
+    
+    hideDelay: 200,
+    
+    dismissDelay: 5000,
+    
+    
+    trackMouse: false,
+    
+    
+    anchorToTarget: true,
+    
+    anchorOffset: 0,
+    
+
+    
+    targetCounter: 0,
+    quickShowInterval: 250,
+
+    
+    initComponent: function() {
+        var me = this;
+        me.callParent(arguments);
+        me.lastActive = new Date();
+        me.setTarget(me.target);
+        me.origAnchor = me.anchor;
+    },
+
+    
+    onRender: function(ct, position) {
+        var me = this;
+        me.callParent(arguments);
+        me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
+        me.anchorEl = me.el.createChild({
+            cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls
+        });
+    },
+
+    
+    afterRender: function() {
+        var me = this,
+            zIndex;
+
+        me.callParent(arguments);
+        zIndex = parseInt(me.el.getZIndex(), 10) || 0;
+        me.anchorEl.setStyle('z-index', zIndex + 1).setVisibilityMode(Ext.Element.DISPLAY);
+    },
+
+    
+    setTarget: function(target) {
+        var me = this,
+            t = Ext.get(target),
+            tg;
+
+        if (me.target) {
+            tg = Ext.get(me.target);
+            me.mun(tg, 'mouseover', me.onTargetOver, me);
+            me.mun(tg, 'mouseout', me.onTargetOut, me);
+            me.mun(tg, 'mousemove', me.onMouseMove, me);
+        }
+
+        me.target = t;
+        if (t) {
+
+            me.mon(t, {
+                
+                
+                freezeEvent: true,
+
+                mouseover: me.onTargetOver,
+                mouseout: me.onTargetOut,
+                mousemove: me.onMouseMove,
+                scope: me
+            });
+        }
+        if (me.anchor) {
+            me.anchorTarget = me.target;
+        }
+    },
+
+    
+    onMouseMove: function(e) {
+        var me = this,
+            t = me.delegate ? e.getTarget(me.delegate) : me.triggerElement = true,
+            xy;
+        if (t) {
+            me.targetXY = e.getXY();
+            if (t === me.triggerElement) {
+                if (!me.hidden && me.trackMouse) {
+                    xy = me.getTargetXY();
+                    if (me.constrainPosition) {
+                        xy = me.el.adjustForConstraints(xy, me.el.getScopeParent());
+                    }
+                    me.setPagePosition(xy);
+                }
+            } else {
+                me.hide();
+                me.lastActive = new Date(0);
+                me.onTargetOver(e);
+            }
+        } else if ((!me.closable && me.isVisible()) && me.autoHide !== false) {
+            me.hide();
+        }
+    },
+
+    
+    getTargetXY: function() {
+        var me = this,
+            mouseOffset;
+        if (me.delegate) {
+            me.anchorTarget = me.triggerElement;
+        }
+        if (me.anchor) {
+            me.targetCounter++;
+                var offsets = me.getOffsets(),
+                    xy = (me.anchorToTarget && !me.trackMouse) ? me.el.getAlignToXY(me.anchorTarget, me.getAnchorAlign()) : me.targetXY,
+                    dw = Ext.Element.getViewWidth() - 5,
+                    dh = Ext.Element.getViewHeight() - 5,
+                    de = document.documentElement,
+                    bd = document.body,
+                    scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
+                    scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
+                    axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
+                    sz = me.getSize(),
+                    constrainPosition = me.constrainPosition;
+
+            me.anchorEl.removeCls(me.anchorCls);
+
+            if (me.targetCounter < 2 && constrainPosition) {
+                if (axy[0] < scrollX) {
+                    if (me.anchorToTarget) {
+                        me.defaultAlign = 'l-r';
+                        if (me.mouseOffset) {
+                            me.mouseOffset[0] *= -1;
+                        }
+                    }
+                    me.anchor = 'left';
+                    return me.getTargetXY();
+                }
+                if (axy[0] + sz.width > dw) {
+                    if (me.anchorToTarget) {
+                        me.defaultAlign = 'r-l';
+                        if (me.mouseOffset) {
+                            me.mouseOffset[0] *= -1;
+                        }
+                    }
+                    me.anchor = 'right';
+                    return me.getTargetXY();
+                }
+                if (axy[1] < scrollY) {
+                    if (me.anchorToTarget) {
+                        me.defaultAlign = 't-b';
+                        if (me.mouseOffset) {
+                            me.mouseOffset[1] *= -1;
+                        }
+                    }
+                    me.anchor = 'top';
+                    return me.getTargetXY();
+                }
+                if (axy[1] + sz.height > dh) {
+                    if (me.anchorToTarget) {
+                        me.defaultAlign = 'b-t';
+                        if (me.mouseOffset) {
+                            me.mouseOffset[1] *= -1;
+                        }
+                    }
+                    me.anchor = 'bottom';
+                    return me.getTargetXY();
+                }
+            }
+
+            me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
+            me.anchorEl.addCls(me.anchorCls);
+            me.targetCounter = 0;
+            return axy;
+        } else {
+            mouseOffset = me.getMouseOffset();
+            return (me.targetXY) ? [me.targetXY[0] + mouseOffset[0], me.targetXY[1] + mouseOffset[1]] : mouseOffset;
+        }
+    },
+
+    getMouseOffset: function() {
+        var me = this,
+        offset = me.anchor ? [0, 0] : [15, 18];
+        if (me.mouseOffset) {
+            offset[0] += me.mouseOffset[0];
+            offset[1] += me.mouseOffset[1];
+        }
+        return offset;
+    },
+
+    
+    getAnchorPosition: function() {
+        var me = this,
+            m;
+        if (me.anchor) {
+            me.tipAnchor = me.anchor.charAt(0);
+        } else {
+            m = me.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
+            me.tipAnchor = m[1].charAt(0);
+        }
+
+        switch (me.tipAnchor) {
+        case 't':
+            return 'top';
+        case 'b':
+            return 'bottom';
+        case 'r':
+            return 'right';
+        }
+        return 'left';
+    },
+
+    
+    getAnchorAlign: function() {
+        switch (this.anchor) {
+        case 'top':
+            return 'tl-bl';
+        case 'left':
+            return 'tl-tr';
+        case 'right':
+            return 'tr-tl';
+        default:
+            return 'bl-tl';
+        }
+    },
+
+    
+    getOffsets: function() {
+        var me = this,
+            mouseOffset,
+            offsets,
+            ap = me.getAnchorPosition().charAt(0);
+        if (me.anchorToTarget && !me.trackMouse) {
+            switch (ap) {
+            case 't':
+                offsets = [0, 9];
+                break;
+            case 'b':
+                offsets = [0, -13];
+                break;
+            case 'r':
+                offsets = [ - 13, 0];
+                break;
+            default:
+                offsets = [9, 0];
+                break;
+            }
+        } else {
+            switch (ap) {
+            case 't':
+                offsets = [ - 15 - me.anchorOffset, 30];
+                break;
+            case 'b':
+                offsets = [ - 19 - me.anchorOffset, -13 - me.el.dom.offsetHeight];
+                break;
+            case 'r':
+                offsets = [ - 15 - me.el.dom.offsetWidth, -13 - me.anchorOffset];
+                break;
+            default:
+                offsets = [25, -13 - me.anchorOffset];
+                break;
+            }
+        }
+        mouseOffset = me.getMouseOffset();
+        offsets[0] += mouseOffset[0];
+        offsets[1] += mouseOffset[1];
+
+        return offsets;
+    },
+
+    
+    onTargetOver: function(e) {
+        var me = this,
+            t;
+
+        if (me.disabled || e.within(me.target.dom, true)) {
+            return;
+        }
+        t = e.getTarget(me.delegate);
+        if (t) {
+            me.triggerElement = t;
+            me.clearTimer('hide');
+            me.targetXY = e.getXY();
+            me.delayShow();
+        }
+    },
+
+    
+    delayShow: function() {
+        var me = this;
+        if (me.hidden && !me.showTimer) {
+            if (Ext.Date.getElapsed(me.lastActive) < me.quickShowInterval) {
+                me.show();
+            } else {
+                me.showTimer = Ext.defer(me.show, me.showDelay, me);
+            }
+        }
+        else if (!me.hidden && me.autoHide !== false) {
+            me.show();
+        }
+    },
+
+    
+    onTargetOut: function(e) {
+        var me = this;
+        if (me.disabled || e.within(me.target.dom, true)) {
+            return;
+        }
+        me.clearTimer('show');
+        if (me.autoHide !== false) {
+            me.delayHide();
+        }
+    },
+
+    
+    delayHide: function() {
+        var me = this;
+        if (!me.hidden && !me.hideTimer) {
+            me.hideTimer = Ext.defer(me.hide, me.hideDelay, me);
+        }
+    },
+
+    
+    hide: function() {
+        var me = this;
+        me.clearTimer('dismiss');
+        me.lastActive = new Date();
+        if (me.anchorEl) {
+            me.anchorEl.hide();
+        }
+        me.callParent(arguments);
+        delete me.triggerElement;
+    },
+
+    
+    show: function() {
+        var me = this;
+
+        
+        
+        this.callParent();
+        if (this.hidden === false) {
+            me.setPagePosition(-10000, -10000);
+
+            if (me.anchor) {
+                me.anchor = me.origAnchor;
+            }
+            me.showAt(me.getTargetXY());
+
+            if (me.anchor) {
+                me.syncAnchor();
+                me.anchorEl.show();
+            } else {
+                me.anchorEl.hide();
+            }
+        }
+    },
+
+    
+    showAt: function(xy) {
+        var me = this;
+        me.lastActive = new Date();
+        me.clearTimers();
+
+        
+        if (!me.isVisible()) {
+            this.callParent(arguments);
+        }
+
+        
+        if (me.isVisible()) {
+            me.setPagePosition(xy[0], xy[1]);
+            if (me.constrainPosition || me.constrain) {
+                me.doConstrain();
+            }
+            me.toFront(true);
+        }
+
+        if (me.dismissDelay && me.autoHide !== false) {
+            me.dismissTimer = Ext.defer(me.hide, me.dismissDelay, me);
+        }
+        if (me.anchor) {
+            me.syncAnchor();
+            if (!me.anchorEl.isVisible()) {
+                me.anchorEl.show();
+            }
+        } else {
+            me.anchorEl.hide();
+        }
+    },
+
+    
+    syncAnchor: function() {
+        var me = this,
+            anchorPos,
+            targetPos,
+            offset;
+        switch (me.tipAnchor.charAt(0)) {
+        case 't':
+            anchorPos = 'b';
+            targetPos = 'tl';
+            offset = [20 + me.anchorOffset, 1];
+            break;
+        case 'r':
+            anchorPos = 'l';
+            targetPos = 'tr';
+            offset = [ - 1, 12 + me.anchorOffset];
+            break;
+        case 'b':
+            anchorPos = 't';
+            targetPos = 'bl';
+            offset = [20 + me.anchorOffset, -1];
+            break;
+        default:
+            anchorPos = 'r';
+            targetPos = 'tl';
+            offset = [1, 12 + me.anchorOffset];
+            break;
+        }
+        me.anchorEl.alignTo(me.el, anchorPos + '-' + targetPos, offset);
+    },
+
+    
+    setPagePosition: function(x, y) {
+        var me = this;
+        me.callParent(arguments);
+        if (me.anchor) {
+            me.syncAnchor();
+        }
+    },
+
+    
+    clearTimer: function(name) {
+        name = name + 'Timer';
+        clearTimeout(this[name]);
+        delete this[name];
+    },
+
+    
+    clearTimers: function() {
+        var me = this;
+        me.clearTimer('show');
+        me.clearTimer('dismiss');
+        me.clearTimer('hide');
+    },
+
+    
+    onShow: function() {
+        var me = this;
+        me.callParent();
+        me.mon(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
+    },
+
+    
+    onHide: function() {
+        var me = this;
+        me.callParent();
+        me.mun(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
+    },
+
+    
+    onDocMouseDown: function(e) {
+        var me = this;
+        if (me.autoHide !== true && !me.closable && !e.within(me.el.dom)) {
+            me.disable();
+            Ext.defer(me.doEnable, 100, me);
+        }
+    },
+
+    
+    doEnable: function() {
+        if (!this.isDestroyed) {
+            this.enable();
+        }
+    },
+
+    
+    onDisable: function() {
+        this.callParent();
+        this.clearTimers();
+        this.hide();
+    },
+
+    beforeDestroy: function() {
+        var me = this;
+        me.clearTimers();
+        Ext.destroy(me.anchorEl);
+        delete me.anchorEl;
+        delete me.target;
+        delete me.anchorTarget;
+        delete me.triggerElement;
+        me.callParent();
+    },
+
+    
+    onDestroy: function() {
+        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
+        this.callParent();
+    }
+});
+
+
+Ext.define('Ext.tip.QuickTip', {
+    extend: 'Ext.tip.ToolTip',
+    alternateClassName: 'Ext.QuickTip',
+    
+    
+    interceptTitles : false,
+
+    
+    title: '&#160;',
+
+    
+    tagConfig : {
+        namespace : "data-",
+        attribute : "qtip",
+        width : "qwidth",
+        target : "target",
+        title : "qtitle",
+        hide : "hide",
+        cls : "qclass",
+        align : "qalign",
+        anchor : "anchor"
+    },
+
+    
+    initComponent : function(){
+        var me = this;
+
+        me.target = me.target || Ext.getDoc();
+        me.targets = me.targets || {};
+        me.callParent();
+    },
+
+    
+    register : function(config){
+        var configs = Ext.isArray(config) ? config : arguments,
+            i = 0,
+            len = configs.length,
+            target, j, targetLen;
+
+        for (; i < len; i++) {
+            config = configs[i];
+            target = config.target;
+            if (target) {
+                if (Ext.isArray(target)) {
+                    for (j = 0, targetLen = target.length; j < targetLen; j++) {
+                        this.targets[Ext.id(target[j])] = config;
+                    }
+                } else{
+                    this.targets[Ext.id(target)] = config;
+                }
+            }
+        }
+    },
+
+    
+    unregister : function(el){
+        delete this.targets[Ext.id(el)];
+    },
+
+    
+    cancelShow: function(el){
+        var me = this,
+            activeTarget = me.activeTarget;
+
+        el = Ext.get(el).dom;
+        if (me.isVisible()) {
+            if (activeTarget && activeTarget.el == el) {
+                me.hide();
+            }
+        } else if (activeTarget && activeTarget.el == el) {
+            me.clearTimer('show');
+        }
+    },
+
+    
+    getTipCfg: function(e) {
+        var t = e.getTarget(),
+            titleText = t.title,
+            cfg;
+
+        if (this.interceptTitles && titleText && Ext.isString(titleText)) {
+            t.qtip = titleText;
+            t.removeAttribute("title");
+            e.preventDefault();
+            return {
+                text: titleText
+            };
+        }
+        else {
+            cfg = this.tagConfig;
+            t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']');
+            if (t) {
+                return {
+                    target: t,
+                    text: t.getAttribute(cfg.namespace + cfg.attribute)
+                };
+            }
+        }
+    },
+
+    
+    onTargetOver : function(e){
+        var me = this,
+            target = e.getTarget(),
+            elTarget,
+            cfg,
+            ns,
+            tipConfig,
+            autoHide;
+
+        if (me.disabled) {
+            return;
+        }
+
+        
+        
+        
+        me.targetXY = e.getXY();
+
+        if(!target || target.nodeType !== 1 || target == document || target == document.body){
+            return;
+        }
+
+        if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
+            me.clearTimer('hide');
+            me.show();
+            return;
+        }
+
+        if (target) {
+            Ext.Object.each(me.targets, function(key, value) {
+                var targetEl = Ext.fly(value.target);
+                if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
+                    elTarget = targetEl.dom;
+                    return false;
+                }
+            });
+            if (elTarget) {
+                me.activeTarget = me.targets[elTarget.id];
+                me.activeTarget.el = target;
+                me.anchor = me.activeTarget.anchor;
+                if (me.anchor) {
+                    me.anchorTarget = target;
+                }
+                me.delayShow();
+                return;
+            }
+        }
+
+        elTarget = Ext.get(target);
+        cfg = me.tagConfig;
+        ns = cfg.namespace;
+        tipConfig = me.getTipCfg(e);
+
+        if (tipConfig) {
+
+            
+            
+            if (tipConfig.target) {
+                target = tipConfig.target;
+                elTarget = Ext.get(target);
+            }
+            autoHide = elTarget.getAttribute(ns + cfg.hide);
+
+            me.activeTarget = {
+                el: target,
+                text: tipConfig.text,
+                width: +elTarget.getAttribute(ns + cfg.width) || null,
+                autoHide: autoHide != "user" && autoHide !== 'false',
+                title: elTarget.getAttribute(ns + cfg.title),
+                cls: elTarget.getAttribute(ns + cfg.cls),
+                align: elTarget.getAttribute(ns + cfg.align)
+
+            };
+            me.anchor = elTarget.getAttribute(ns + cfg.anchor);
+            if (me.anchor) {
+                me.anchorTarget = target;
+            }
+            me.delayShow();
+        }
+    },
+
+    
+    onTargetOut : function(e){
+        var me = this;
+
+        
+        if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
+            return;
+        }
+
+        me.clearTimer('show');
+        if (me.autoHide !== false) {
+            me.delayHide();
+        }
+    },
+
+    
+    showAt : function(xy){
+        var me = this,
+            target = me.activeTarget;
+
+        if (target) {
+            if (!me.rendered) {
+                me.render(Ext.getBody());
+                me.activeTarget = target;
+            }
+            if (target.title) {
+                me.setTitle(target.title || '');
+                me.header.show();
+            } else {
+                me.header.hide();
+            }
+            me.body.update(target.text);
+            me.autoHide = target.autoHide;
+            me.dismissDelay = target.dismissDelay || me.dismissDelay;
+            if (me.lastCls) {
+                me.el.removeCls(me.lastCls);
+                delete me.lastCls;
+            }
+            if (target.cls) {
+                me.el.addCls(target.cls);
+                me.lastCls = target.cls;
+            }
+
+            me.setWidth(target.width);
+
+            if (me.anchor) {
+                me.constrainPosition = false;
+            } else if (target.align) { 
+                xy = me.el.getAlignToXY(target.el, target.align);
+                me.constrainPosition = false;
+            }else{
+                me.constrainPosition = true;
+            }
+        }
+        me.callParent([xy]);
+    },
+
+    
+    hide: function(){
+        delete this.activeTarget;
+        this.callParent();
+    }
+});
+
+
+Ext.define('Ext.tip.QuickTipManager', function() {
+    var tip,
+        disabled = false;
+
+    return {
+        requires: ['Ext.tip.QuickTip'],
+        singleton: true,
+        alternateClassName: 'Ext.QuickTips',
+
+        
+        init : function (autoRender, config) {
+            if (!tip) {
+                if (!Ext.isReady) {
+                    Ext.onReady(function(){
+                        Ext.tip.QuickTipManager.init(autoRender);
+                    });
+                    return;
+                }
+
+                var tipConfig = Ext.apply({ disabled: disabled }, config),
+                    className = tipConfig.className,
+                    xtype = tipConfig.xtype;
+
+                if (className) {
+                    delete tipConfig.className;
+                } else if (xtype) {
+                    className = 'widget.' + xtype;
+                    delete tipConfig.xtype;
+                }
+
+                if (autoRender !== false) {
+                    tipConfig.renderTo = document.body;
+
+                }
+
+                tip = Ext.create(className || 'Ext.tip.QuickTip', tipConfig);
+            }
+        },
+
+        
+        destroy: function() {
+            if (tip) {
+                var undef;
+                tip.destroy();
+                tip = undef;
+            }
+        },
+
+        
+        ddDisable : function(){
+            
+            if(tip && !disabled){
+                tip.disable();
+            }
+        },
+
+        
+        ddEnable : function(){
+            
+            if(tip && !disabled){
+                tip.enable();
+            }
+        },
+
+        
+        enable : function(){
+            if(tip){
+                tip.enable();
+            }
+            disabled = false;
+        },
+
+        
+        disable : function(){
+            if(tip){
+                tip.disable();
+            }
+            disabled = true;
+        },
+
+        
+        isEnabled : function(){
+            return tip !== undefined && !tip.disabled;
+        },
+
+        
+        getQuickTip : function(){
+            return tip;
+        },
+
+        
+        register : function(){
+            tip.register.apply(tip, arguments);
+        },
+
+        
+        unregister : function(){
+            tip.unregister.apply(tip, arguments);
+        },
+
+        
+        tips : function(){
+            tip.register.apply(tip, arguments);
+        }
+    };
 }());
 
-Ext.EventManager.on = Ext.EventManager.addListener;
+Ext.define('Ext.app.Application', {
+    extend: 'Ext.app.Controller',
+
+    requires: [
+        'Ext.ModelManager',
+        'Ext.data.Model',
+        'Ext.data.StoreManager',
+        'Ext.tip.QuickTipManager',
+        'Ext.ComponentManager',
+        'Ext.app.EventBus'
+    ],
+
+    
+
+    
+    scope: undefined,
+
+    
+    enableQuickTips: true,
+
+    
+
+    
+    appFolder: 'app',
+
+    
+    autoCreateViewport: false,
+
+    
+    constructor: function(config) {
+        config = config || {};
+        Ext.apply(this, config);
+
+        var requires = config.requires || [];
+
+        Ext.Loader.setPath(this.name, this.appFolder);
+
+        if (this.paths) {
+            Ext.Object.each(this.paths, function(key, value) {
+                Ext.Loader.setPath(key, value);
+            });
+        }
+
+        this.callParent(arguments);
+
+        this.eventbus = Ext.create('Ext.app.EventBus');
+
+        var controllers = Ext.Array.from(this.controllers),
+            ln = controllers && controllers.length,
+            i, controller;
+
+        this.controllers = Ext.create('Ext.util.MixedCollection');
+
+        if (this.autoCreateViewport) {
+            requires.push(this.getModuleClassName('Viewport', 'view'));
+        }
+
+        for (i = 0; i < ln; i++) {
+            requires.push(this.getModuleClassName(controllers[i], 'controller'));
+        }
+
+        Ext.require(requires);
+
+        Ext.onReady(function() {
+            for (i = 0; i < ln; i++) {
+                controller = this.getController(controllers[i]);
+                controller.init(this);
+            }
+
+            this.onBeforeLaunch.call(this);
+        }, this);
+    },
+
+    control: function(selectors, listeners, controller) {
+        this.eventbus.control(selectors, listeners, controller);
+    },
+
+    
+    launch: Ext.emptyFn,
+
+    
+    onBeforeLaunch: function() {
+        if (this.enableQuickTips) {
+            Ext.tip.QuickTipManager.init();
+        }
+
+        if (this.autoCreateViewport) {
+            this.getView('Viewport').create();
+        }
+
+        this.launch.call(this.scope || this);
+        this.launched = true;
+        this.fireEvent('launch', this);
+
+        this.controllers.each(function(controller) {
+            controller.onLaunch(this);
+        }, this);
+    },
+
+    getModuleClassName: function(name, type) {
+        var namespace = Ext.Loader.getPrefix(name);
+
+        if (namespace.length > 0 && namespace !== name) {
+            return name;
+        }
+
+        return this.name + '.' + type + '.' + name;
+    },
+
+    getController: function(name) {
+        var controller = this.controllers.get(name);
+
+        if (!controller) {
+            controller = Ext.create(this.getModuleClassName(name, 'controller'), {
+                application: this,
+                id: name
+            });
+
+            this.controllers.add(controller);
+        }
+
+        return controller;
+    },
+
+    getStore: function(name) {
+        var store = Ext.StoreManager.get(name);
+
+        if (!store) {
+            store = Ext.create(this.getModuleClassName(name, 'store'), {
+                storeId: name
+            });
+        }
+
+        return store;
+    },
+
+    getModel: function(model) {
+        model = this.getModuleClassName(model, 'model');
+
+        return Ext.ModelManager.getModel(model);
+    },
+
+    getView: function(view) {
+        view = this.getModuleClassName(view, 'view');
+
+        return Ext.ClassManager.get(view);
+    }
+});
+
+
+Ext.define('Ext.chart.Callout', {
+
+    
+
+    
+
+    constructor: function(config) {
+        if (config.callouts) {
+            config.callouts.styles = Ext.applyIf(config.callouts.styles || {}, {
+                color: "#000",
+                font: "11px Helvetica, sans-serif"
+            });
+            this.callouts = Ext.apply(this.callouts || {}, config.callouts);
+            this.calloutsArray = [];
+        }
+    },
+
+    renderCallouts: function() {
+        if (!this.callouts) {
+            return;
+        }
+
+        var me = this,
+            items = me.items,
+            animate = me.chart.animate,
+            config = me.callouts,
+            styles = config.styles,
+            group = me.calloutsArray,
+            store = me.chart.store,
+            len = store.getCount(),
+            ratio = items.length / len,
+            previouslyPlacedCallouts = [],
+            i,
+            count,
+            j,
+            p;
+            
+        for (i = 0, count = 0; i < len; i++) {
+            for (j = 0; j < ratio; j++) {
+                var item = items[count],
+                    label = group[count],
+                    storeItem = store.getAt(i),
+                    display;
+                
+                display = config.filter(storeItem);
+                
+                if (!display && !label) {
+                    count++;
+                    continue;               
+                }
+                
+                if (!label) {
+                    group[count] = label = me.onCreateCallout(storeItem, item, i, display, j, count);
+                }
+                for (p in label) {
+                    if (label[p] && label[p].setAttributes) {
+                        label[p].setAttributes(styles, true);
+                    }
+                }
+                if (!display) {
+                    for (p in label) {
+                        if (label[p]) {
+                            if (label[p].setAttributes) {
+                                label[p].setAttributes({
+                                    hidden: true
+                                }, true);
+                            } else if(label[p].setVisible) {
+                                label[p].setVisible(false);
+                            }
+                        }
+                    }
+                }
+                config.renderer(label, storeItem);
+                me.onPlaceCallout(label, storeItem, item, i, display, animate,
+                                  j, count, previouslyPlacedCallouts);
+                previouslyPlacedCallouts.push(label);
+                count++;
+            }
+        }
+        this.hideCallouts(count);
+    },
+
+    onCreateCallout: function(storeItem, item, i, display) {
+        var me = this,
+            group = me.calloutsGroup,
+            config = me.callouts,
+            styles = config.styles,
+            width = styles.width,
+            height = styles.height,
+            chart = me.chart,
+            surface = chart.surface,
+            calloutObj = {
+                
+                
+                lines: false
+            };
+
+        calloutObj.lines = surface.add(Ext.apply({},
+        {
+            type: 'path',
+            path: 'M0,0',
+            stroke: me.getLegendColor() || '#555'
+        },
+        styles));
+
+        if (config.items) {
+            calloutObj.panel = Ext.create('widget.panel', {
+                style: "position: absolute;",    
+                width: width,
+                height: height,
+                items: config.items,
+                renderTo: chart.el
+            });
+        }
+
+        return calloutObj;
+    },
+
+    hideCallouts: function(index) {
+        var calloutsArray = this.calloutsArray,
+            len = calloutsArray.length,
+            co,
+            p;
+        while (len-->index) {
+            co = calloutsArray[len];
+            for (p in co) {
+                if (co[p]) {
+                    co[p].hide(true);
+                }
+            }
+        }
+    }
+});
+
+
+Ext.define('Ext.draw.CompositeSprite', {
+
+    
+
+    extend: 'Ext.util.MixedCollection',
+    mixins: {
+        animate: 'Ext.util.Animate'
+    },
+
+    
+    isCompositeSprite: true,
+    constructor: function(config) {
+        var me = this;
+        
+        config = config || {};
+        Ext.apply(me, config);
+
+        me.addEvents(
+            'mousedown',
+            'mouseup',
+            'mouseover',
+            'mouseout',
+            'click'
+        );
+        me.id = Ext.id(null, 'ext-sprite-group-');
+        me.callParent();
+    },
+
+    
+    onClick: function(e) {
+        this.fireEvent('click', e);
+    },
+
+    
+    onMouseUp: function(e) {
+        this.fireEvent('mouseup', e);
+    },
+
+    
+    onMouseDown: function(e) {
+        this.fireEvent('mousedown', e);
+    },
+
+    
+    onMouseOver: function(e) {
+        this.fireEvent('mouseover', e);
+    },
+
+    
+    onMouseOut: function(e) {
+        this.fireEvent('mouseout', e);
+    },
+
+    attachEvents: function(o) {
+        var me = this;
+        
+        o.on({
+            scope: me,
+            mousedown: me.onMouseDown,
+            mouseup: me.onMouseUp,
+            mouseover: me.onMouseOver,
+            mouseout: me.onMouseOut,
+            click: me.onClick
+        });
+    },
+
+    
+    add: function(key, o) {
+        var result = this.callParent(arguments);
+        this.attachEvents(result);
+        return result;
+    },
+
+    insert: function(index, key, o) {
+        return this.callParent(arguments);
+    },
+
+    
+    remove: function(o) {
+        var me = this;
+        
+        o.un({
+            scope: me,
+            mousedown: me.onMouseDown,
+            mouseup: me.onMouseUp,
+            mouseover: me.onMouseOver,
+            mouseout: me.onMouseOut,
+            click: me.onClick
+        });
+        return me.callParent(arguments);
+    },
+    
+    
+    getBBox: function() {
+        var i = 0,
+            sprite,
+            bb,
+            items = this.items,
+            len = this.length,
+            infinity = Infinity,
+            minX = infinity,
+            maxHeight = -infinity,
+            minY = infinity,
+            maxWidth = -infinity,
+            maxWidthBBox, maxHeightBBox;
+        
+        for (; i < len; i++) {
+            sprite = items[i];
+            if (sprite.el) {
+                bb = sprite.getBBox();
+                minX = Math.min(minX, bb.x);
+                minY = Math.min(minY, bb.y);
+                maxHeight = Math.max(maxHeight, bb.height + bb.y);
+                maxWidth = Math.max(maxWidth, bb.width + bb.x);
+            }
+        }
+        
+        return {
+            x: minX,
+            y: minY,
+            height: maxHeight - minY,
+            width: maxWidth - minX
+        };
+    },
+
+    
+    setAttributes: function(attrs, redraw) {
+        var i = 0,
+            items = this.items,
+            len = this.length;
+            
+        for (; i < len; i++) {
+            items[i].setAttributes(attrs, redraw);
+        }
+        return this;
+    },
+
+    
+    hide: function(redraw) {
+        var i = 0,
+            items = this.items,
+            len = this.length;
+            
+        for (; i < len; i++) {
+            items[i].hide(redraw);
+        }
+        return this;
+    },
+
+    
+    show: function(redraw) {
+        var i = 0,
+            items = this.items,
+            len = this.length;
+            
+        for (; i < len; i++) {
+            items[i].show(redraw);
+        }
+        return this;
+    },
+
+    redraw: function() {
+        var me = this,
+            i = 0,
+            items = me.items,
+            surface = me.getSurface(),
+            len = me.length;
+        
+        if (surface) {
+            for (; i < len; i++) {
+                surface.renderItem(items[i]);
+            }
+        }
+        return me;
+    },
+
+    setStyle: function(obj) {
+        var i = 0,
+            items = this.items,
+            len = this.length,
+            item, el;
+            
+        for (; i < len; i++) {
+            item = items[i];
+            el = item.el;
+            if (el) {
+                el.setStyle(obj);
+            }
+        }
+    },
+
+    addCls: function(obj) {
+        var i = 0,
+            items = this.items,
+            surface = this.getSurface(),
+            len = this.length;
+        
+        if (surface) {
+            for (; i < len; i++) {
+                surface.addCls(items[i], obj);
+            }
+        }
+    },
+
+    removeCls: function(obj) {
+        var i = 0,
+            items = this.items,
+            surface = this.getSurface(),
+            len = this.length;
+        
+        if (surface) {
+            for (; i < len; i++) {
+                surface.removeCls(items[i], obj);
+            }
+        }
+    },
+    
+    
+    getSurface: function(){
+        var first = this.first();
+        if (first) {
+            return first.surface;
+        }
+        return null;
+    },
+    
+    
+    destroy: function(){
+        var me = this,
+            surface = me.getSurface(),
+            item;
+            
+        if (surface) {
+            while (me.getCount() > 0) {
+                item = me.first();
+                me.remove(item);
+                surface.remove(item);
+            }
+        }
+        me.clearListeners();
+    }
+});
+
+
+
+Ext.define('Ext.layout.component.Auto', {
+
+    
+
+    alias: 'layout.autocomponent',
+
+    extend: 'Ext.layout.component.Component',
+
+    
+
+    type: 'autocomponent',
+
+    onLayout : function(width, height) {
+        this.setTargetSize(width, height);
+    }
+});
+
+Ext.define('Ext.chart.theme.Theme', {
+
+    
+
+    requires: ['Ext.draw.Color'],
+
+    
+
+    theme: 'Base',
+    themeAttrs: false,
+    
+    initTheme: function(theme) {
+        var me = this,
+            themes = Ext.chart.theme,
+            key, gradients;
+        if (theme) {
+            theme = theme.split(':');
+            for (key in themes) {
+                if (key == theme[0]) {
+                    gradients = theme[1] == 'gradients';
+                    me.themeAttrs = new themes[key]({
+                        useGradients: gradients
+                    });
+                    if (gradients) {
+                        me.gradients = me.themeAttrs.gradients;
+                    }
+                    if (me.themeAttrs.background) {
+                        me.background = me.themeAttrs.background;
+                    }
+                    return;
+                }
+            }
+        }
+    }
+}, 
+
+function() {
+   
+
+(function() {
+    Ext.chart.theme = function(config, base) {
+        config = config || {};
+        var i = 0, l, colors, color,
+            seriesThemes, markerThemes,
+            seriesTheme, markerTheme, 
+            key, gradients = [],
+            midColor, midL;
+        
+        if (config.baseColor) {
+            midColor = Ext.draw.Color.fromString(config.baseColor);
+            midL = midColor.getHSL()[2];
+            if (midL < 0.15) {
+                midColor = midColor.getLighter(0.3);
+            } else if (midL < 0.3) {
+                midColor = midColor.getLighter(0.15);
+            } else if (midL > 0.85) {
+                midColor = midColor.getDarker(0.3);
+            } else if (midL > 0.7) {
+                midColor = midColor.getDarker(0.15);
+            }
+            config.colors = [ midColor.getDarker(0.3).toString(),
+                              midColor.getDarker(0.15).toString(),
+                              midColor.toString(),
+                              midColor.getLighter(0.15).toString(),
+                              midColor.getLighter(0.3).toString()];
+
+            delete config.baseColor;
+        }
+        if (config.colors) {
+            colors = config.colors.slice();
+            markerThemes = base.markerThemes;
+            seriesThemes = base.seriesThemes;
+            l = colors.length;
+            base.colors = colors;
+            for (; i < l; i++) {
+                color = colors[i];
+                markerTheme = markerThemes[i] || {};
+                seriesTheme = seriesThemes[i] || {};
+                markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color;
+                markerThemes[i] = markerTheme;
+                seriesThemes[i] = seriesTheme;
+            }
+            base.markerThemes = markerThemes.slice(0, l);
+            base.seriesThemes = seriesThemes.slice(0, l);
+        
+        }
+        for (key in base) {
+            if (key in config) {
+                if (Ext.isObject(config[key]) && Ext.isObject(base[key])) {
+                    Ext.apply(base[key], config[key]);
+                } else {
+                    base[key] = config[key];
+                }
+            }
+        }
+        if (config.useGradients) {
+            colors = base.colors || (function () {
+                var ans = [];
+                for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) {
+                    ans.push(seriesThemes[i].fill || seriesThemes[i].stroke);
+                }
+                return ans;
+            })();
+            for (i = 0, l = colors.length; i < l; i++) {
+                midColor = Ext.draw.Color.fromString(colors[i]);
+                if (midColor) {
+                    color = midColor.getDarker(0.1).toString();
+                    midColor = midColor.toString();
+                    key = 'theme-' + midColor.substr(1) + '-' + color.substr(1);
+                    gradients.push({
+                        id: key,
+                        angle: 45,
+                        stops: {
+                            0: {
+                                color: midColor.toString()
+                            },
+                            100: {
+                                color: color.toString()
+                            }
+                        }
+                    });
+                    colors[i] = 'url(#' + key + ')'; 
+                }
+            }
+            base.gradients = gradients;
+            base.colors = colors;
+        }
+        
+        Ext.apply(this, base);
+    };
+})();
+});
+
+
+Ext.define('Ext.chart.Mask', {
+    require: ['Ext.chart.MaskLayer'],
+    
+    constructor: function(config) {
+        var me = this;
+
+        me.addEvents('select');
+
+        if (config) {
+            Ext.apply(me, config);
+        }
+        if (me.mask) {
+            me.on('afterrender', function() {
+                
+                var comp = Ext.create('Ext.chart.MaskLayer', {
+                    renderTo: me.el
+                });
+                comp.el.on({
+                    'mousemove': function(e) {
+                        me.onMouseMove(e);
+                    },
+                    'mouseup': function(e) {
+                        me.resized(e);
+                    }
+                });
+                
+                var resizeHandler = Ext.create('Ext.resizer.Resizer', {
+                    el: comp.el,
+                    handles: 'all',
+                    pinned: true
+                });
+                resizeHandler.on({
+                    'resize': function(e) {
+                        me.resized(e);    
+                    }    
+                });
+                comp.initDraggable();
+                me.maskType = me.mask;
+                me.mask = comp;
+                me.maskSprite = me.surface.add({
+                    type: 'path',
+                    path: ['M', 0, 0],
+                    zIndex: 1001,
+                    opacity: 0.7,
+                    hidden: true,
+                    stroke: '#444'
+                });
+            }, me, { single: true });
+        }
+    },
+    
+    resized: function(e) {
+        var me = this,
+            bbox = me.bbox || me.chartBBox,
+            x = bbox.x,
+            y = bbox.y,
+            width = bbox.width,
+            height = bbox.height,
+            box = me.mask.getBox(true),
+            max = Math.max,
+            min = Math.min,
+            staticX = box.x - x,
+            staticY = box.y - y;
+        
+        staticX = max(staticX, x);
+        staticY = max(staticY, y);
+        staticX = min(staticX, width);
+        staticY = min(staticY, height);
+        box.x = staticX;
+        box.y = staticY;
+        me.fireEvent('select', me, box);
+    },
+
+    onMouseUp: function(e) {
+        var me = this,
+            bbox = me.bbox || me.chartBBox,
+            sel = me.maskSelection;
+        me.maskMouseDown = false;
+        me.mouseDown = false;
+        if (me.mouseMoved) {
+            me.onMouseMove(e);
+            me.mouseMoved = false;
+            me.fireEvent('select', me, {
+                x: sel.x - bbox.x,
+                y: sel.y - bbox.y,
+                width: sel.width,
+                height: sel.height
+            });
+        }
+    },
+
+    onMouseDown: function(e) {
+        var me = this;
+        me.mouseDown = true;
+        me.mouseMoved = false;
+        me.maskMouseDown = {
+            x: e.getPageX() - me.el.getX(),
+            y: e.getPageY() - me.el.getY()
+        };
+    },
+
+    onMouseMove: function(e) {
+        var me = this,
+            mask = me.maskType,
+            bbox = me.bbox || me.chartBBox,
+            x = bbox.x,
+            y = bbox.y,
+            math = Math,
+            floor = math.floor,
+            abs = math.abs,
+            min = math.min,
+            max = math.max,
+            height = floor(y + bbox.height),
+            width = floor(x + bbox.width),
+            posX = e.getPageX(),
+            posY = e.getPageY(),
+            staticX = posX - me.el.getX(),
+            staticY = posY - me.el.getY(),
+            maskMouseDown = me.maskMouseDown,
+            path;
+        
+        me.mouseMoved = me.mouseDown;
+        staticX = max(staticX, x);
+        staticY = max(staticY, y);
+        staticX = min(staticX, width);
+        staticY = min(staticY, height);
+        if (maskMouseDown && me.mouseDown) {
+            if (mask == 'horizontal') {
+                staticY = y;
+                maskMouseDown.y = height;
+                posY = me.el.getY() + bbox.height + me.insetPadding;
+            }
+            else if (mask == 'vertical') {
+                staticX = x;
+                maskMouseDown.x = width;
+            }
+            width = maskMouseDown.x - staticX;
+            height = maskMouseDown.y - staticY;
+            path = ['M', staticX, staticY, 'l', width, 0, 0, height, -width, 0, 'z'];
+            me.maskSelection = {
+                x: width > 0 ? staticX : staticX + width,
+                y: height > 0 ? staticY : staticY + height,
+                width: abs(width),
+                height: abs(height)
+            };
+            me.mask.updateBox(me.maskSelection);
+            me.mask.show();
+            me.maskSprite.setAttributes({
+                hidden: true    
+            }, true);
+        }
+        else {
+            if (mask == 'horizontal') {
+                path = ['M', staticX, y, 'L', staticX, height];
+            }
+            else if (mask == 'vertical') {
+                path = ['M', x, staticY, 'L', width, staticY];
+            }
+            else {
+                path = ['M', staticX, y, 'L', staticX, height, 'M', x, staticY, 'L', width, staticY];
+            }
+            me.maskSprite.setAttributes({
+                path: path,
+                fill: me.maskMouseDown ? me.maskSprite.stroke : false,
+                'stroke-width': mask === true ? 1 : 3,
+                hidden: false
+            }, true);
+        }
+    },
+
+    onMouseLeave: function(e) {
+        var me = this;
+        me.mouseMoved = false;
+        me.mouseDown = false;
+        me.maskMouseDown = false;
+        me.mask.hide();
+        me.maskSprite.hide(true);
+    }
+});
+    
+
+Ext.define('Ext.chart.Navigation', {
+
+    constructor: function() {
+        this.originalStore = this.store;
+    },
+
+    
+    setZoom: function(zoomConfig) {
+        var me = this,
+            axes = me.axes,
+            bbox = me.chartBBox,
+            xScale = 1 / bbox.width,
+            yScale = 1 / bbox.height,
+            zoomer = {
+                x : zoomConfig.x * xScale,
+                y : zoomConfig.y * yScale,
+                width : zoomConfig.width * xScale,
+                height : zoomConfig.height * yScale
+            };
+        axes.each(function(axis) {
+            var ends = axis.calcEnds();
+            if (axis.position == 'bottom' || axis.position == 'top') {
+                var from = (ends.to - ends.from) * zoomer.x + ends.from,
+                    to = (ends.to - ends.from) * zoomer.width + from;
+                axis.minimum = from;
+                axis.maximum = to;
+            } else {
+                var to = (ends.to - ends.from) * (1 - zoomer.y) + ends.from,
+                    from = to - (ends.to - ends.from) * zoomer.height;
+                axis.minimum = from;
+                axis.maximum = to;
+            }
+        });
+        me.redraw(false);
+    },
+
+    
+    restoreZoom: function() {
+        this.store = this.substore = this.originalStore;
+        this.redraw(true);
+    }
+
+});
+
+
+Ext.define('Ext.chart.Shape', {
+
+    
+
+    singleton: true,
+
+    
+
+    circle: function (surface, opts) {
+        return surface.add(Ext.apply({
+            type: 'circle',
+            x: opts.x,
+            y: opts.y,
+            stroke: null,
+            radius: opts.radius
+        }, opts));
+    },
+    line: function (surface, opts) {
+        return surface.add(Ext.apply({
+            type: 'rect',
+            x: opts.x - opts.radius,
+            y: opts.y - opts.radius,
+            height: 2 * opts.radius,
+            width: 2 * opts.radius / 5
+        }, opts));
+    },
+    square: function (surface, opts) {
+        return surface.add(Ext.applyIf({
+            type: 'rect',
+            x: opts.x - opts.radius,
+            y: opts.y - opts.radius,
+            height: 2 * opts.radius,
+            width: 2 * opts.radius,
+            radius: null
+        }, opts));
+    },
+    triangle: function (surface, opts) {
+        opts.radius *= 1.75;
+        return surface.add(Ext.apply({
+            type: 'path',
+            stroke: null,
+            path: "M".concat(opts.x, ",", opts.y, "m0-", opts.radius * 0.58, "l", opts.radius * 0.5, ",", opts.radius * 0.87, "-", opts.radius, ",0z")
+        }, opts));
+    },
+    diamond: function (surface, opts) {
+        var r = opts.radius;
+        r *= 1.5;
+        return surface.add(Ext.apply({
+            type: 'path',
+            stroke: null,
+            path: ["M", opts.x, opts.y - r, "l", r, r, -r, r, -r, -r, r, -r, "z"]
+        }, opts));
+    },
+    cross: function (surface, opts) {
+        var r = opts.radius;
+        r = r / 1.7;
+        return surface.add(Ext.apply({
+            type: 'path',
+            stroke: null,
+            path: "M".concat(opts.x - r, ",", opts.y, "l", [-r, -r, r, -r, r, r, r, -r, r, r, -r, r, r, r, -r, r, -r, -r, -r, r, -r, -r, "z"])
+        }, opts));
+    },
+    plus: function (surface, opts) {
+        var r = opts.radius / 1.3;
+        return surface.add(Ext.apply({
+            type: 'path',
+            stroke: null,
+            path: "M".concat(opts.x - r / 2, ",", opts.y - r / 2, "l", [0, -r, r, 0, 0, r, r, 0, 0, r, -r, 0, 0, r, -r, 0, 0, -r, -r, 0, 0, -r, "z"])
+        }, opts));
+    },
+    arrow: function (surface, opts) {
+        var r = opts.radius;
+        return surface.add(Ext.apply({
+            type: 'path',
+            path: "M".concat(opts.x - r * 0.7, ",", opts.y - r * 0.4, "l", [r * 0.6, 0, 0, -r * 0.4, r, r * 0.8, -r, r * 0.8, 0, -r * 0.4, -r * 0.6, 0], "z")
+        }, opts));
+    },
+    drop: function (surface, x, y, text, size, angle) {
+        size = size || 30;
+        angle = angle || 0;
+        surface.add({
+            type: 'path',
+            path: ['M', x, y, 'l', size, 0, 'A', size * 0.4, size * 0.4, 0, 1, 0, x + size * 0.7, y - size * 0.7, 'z'],
+            fill: '#000',
+            stroke: 'none',
+            rotate: {
+                degrees: 22.5 - angle,
+                x: x,
+                y: y
+            }
+        });
+        angle = (angle + 90) * Math.PI / 180;
+        surface.add({
+            type: 'text',
+            x: x + size * Math.sin(angle) - 10, 
+            y: y + size * Math.cos(angle) + 5,
+            text:  text,
+            'font-size': size * 12 / 40,
+            stroke: 'none',
+            fill: '#fff'
+        });
+    }
+});
+
+Ext.define('Ext.draw.Surface', {
+
+    
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: ['Ext.draw.CompositeSprite'],
+    uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
+
+    separatorRe: /[, ]+/,
+
+    statics: {
+        
+        create: function(config, enginePriority) {
+            enginePriority = enginePriority || ['Svg', 'Vml'];
+
+            var i = 0,
+                len = enginePriority.length,
+                surfaceClass;
+
+            for (; i < len; i++) {
+                if (Ext.supports[enginePriority[i]]) {
+                    return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
+                }
+            }
+            return false;
+        }
+    },
+
+    
+
+    
+    availableAttrs: {
+        blur: 0,
+        "clip-rect": "0 0 1e9 1e9",
+        cursor: "default",
+        cx: 0,
+        cy: 0,
+        'dominant-baseline': 'auto',
+        fill: "none",
+        "fill-opacity": 1,
+        font: '10px "Arial"',
+        "font-family": '"Arial"',
+        "font-size": "10",
+        "font-style": "normal",
+        "font-weight": 400,
+        gradient: "",
+        height: 0,
+        hidden: false,
+        href: "http://sencha.com/",
+        opacity: 1,
+        path: "M0,0",
+        radius: 0,
+        rx: 0,
+        ry: 0,
+        scale: "1 1",
+        src: "",
+        stroke: "#000",
+        "stroke-dasharray": "",
+        "stroke-linecap": "butt",
+        "stroke-linejoin": "butt",
+        "stroke-miterlimit": 0,
+        "stroke-opacity": 1,
+        "stroke-width": 1,
+        target: "_blank",
+        text: "",
+        "text-anchor": "middle",
+        title: "Ext Draw",
+        width: 0,
+        x: 0,
+        y: 0,
+        zIndex: 0
+    },
+
+    
+    
+
+    container: undefined,
+    height: 352,
+    width: 512,
+    x: 0,
+    y: 0,
+
+    
+    orderSpritesByZIndex: true,
+
+
+    
+    constructor: function(config) {
+        var me = this;
+        config = config || {};
+        Ext.apply(me, config);
+
+        me.domRef = Ext.getDoc().dom;
+
+        me.customAttributes = {};
+
+        me.addEvents(
+            'mousedown',
+            'mouseup',
+            'mouseover',
+            'mouseout',
+            'mousemove',
+            'mouseenter',
+            'mouseleave',
+            'click'
+        );
+
+        me.mixins.observable.constructor.call(me);
+
+        me.getId();
+        me.initGradients();
+        me.initItems();
+        if (me.renderTo) {
+            me.render(me.renderTo);
+            delete me.renderTo;
+        }
+        me.initBackground(config.background);
+    },
+
+    
+    
+    initSurface: Ext.emptyFn,
+
+    
+    
+    renderItem: Ext.emptyFn,
+
+    
+    renderItems: Ext.emptyFn,
+
+    
+    setViewBox: function (x, y, width, height) {
+        if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
+            this.viewBox = {x: x, y: y, width: width, height: height};
+            this.applyViewBox();
+        }
+    },
+
+    
+    addCls: Ext.emptyFn,
+
+    
+    removeCls: Ext.emptyFn,
+
+    
+    setStyle: Ext.emptyFn,
+
+    
+    initGradients: function() {
+        var gradients = this.gradients;
+        if (gradients) {
+            Ext.each(gradients, this.addGradient, this);
+        }
+    },
+
+    
+    initItems: function() {
+        var items = this.items;
+        this.items = Ext.create('Ext.draw.CompositeSprite');
+        this.groups = Ext.create('Ext.draw.CompositeSprite');
+        if (items) {
+            this.add(items);
+        }
+    },
+
+    
+    initBackground: function(config) {
+        var me = this,
+            width = me.width,
+            height = me.height,
+            gradientId, gradient, backgroundSprite;
+        if (config) {
+            if (config.gradient) {
+                gradient = config.gradient;
+                gradientId = gradient.id;
+                me.addGradient(gradient);
+                me.background = me.add({
+                    type: 'rect',
+                    x: 0,
+                    y: 0,
+                    width: width,
+                    height: height,
+                    fill: 'url(#' + gradientId + ')'
+                });
+            } else if (config.fill) {
+                me.background = me.add({
+                    type: 'rect',
+                    x: 0,
+                    y: 0,
+                    width: width,
+                    height: height,
+                    fill: config.fill
+                });
+            } else if (config.image) {
+                me.background = me.add({
+                    type: 'image',
+                    x: 0,
+                    y: 0,
+                    width: width,
+                    height: height,
+                    src: config.image
+                });
+            }
+        }
+    },
+
+    
+    setSize: function(w, h) {
+        if (this.background) {
+            this.background.setAttributes({
+                width: w,
+                height: h,
+                hidden: false
+            }, true);
+        }
+        this.applyViewBox();
+    },
+
+    
+    scrubAttrs: function(sprite) {
+        var i,
+            attrs = {},
+            exclude = {},
+            sattr = sprite.attr;
+        for (i in sattr) {
+            
+            if (this.translateAttrs.hasOwnProperty(i)) {
+                
+                attrs[this.translateAttrs[i]] = sattr[i];
+                exclude[this.translateAttrs[i]] = true;
+            }
+            else if (this.availableAttrs.hasOwnProperty(i) && !exclude[i]) {
+                
+                attrs[i] = sattr[i];
+            }
+        }
+        return attrs;
+    },
+
+    
+    onClick: function(e) {
+        this.processEvent('click', e);
+    },
+
+    
+    onMouseUp: function(e) {
+        this.processEvent('mouseup', e);
+    },
+
+    
+    onMouseDown: function(e) {
+        this.processEvent('mousedown', e);
+    },
+
+    
+    onMouseOver: function(e) {
+        this.processEvent('mouseover', e);
+    },
+
+    
+    onMouseOut: function(e) {
+        this.processEvent('mouseout', e);
+    },
+
+    
+    onMouseMove: function(e) {
+        this.fireEvent('mousemove', e);
+    },
+
+    
+    onMouseEnter: Ext.emptyFn,
+
+    
+    onMouseLeave: Ext.emptyFn,
+
+    
+    addGradient: Ext.emptyFn,
+
+    
+    add: function() {
+        var args = Array.prototype.slice.call(arguments),
+            sprite,
+            index;
+
+        var hasMultipleArgs = args.length > 1;
+        if (hasMultipleArgs || Ext.isArray(args[0])) {
+            var items = hasMultipleArgs ? args : args[0],
+                results = [],
+                i, ln, item;
+
+            for (i = 0, ln = items.length; i < ln; i++) {
+                item = items[i];
+                item = this.add(item);
+                results.push(item);
+            }
+
+            return results;
+        }
+        sprite = this.prepareItems(args[0], true)[0];
+        this.insertByZIndex(sprite);
+        this.onAdd(sprite);
+        return sprite;
+    },
+
+    
+    insertByZIndex: function(sprite) {
+        var me = this,
+            sprites = me.items.items,
+            len = sprites.length,
+            ceil = Math.ceil,
+            zIndex = sprite.attr.zIndex,
+            idx = len,
+            high = idx - 1,
+            low = 0,
+            otherZIndex;
+
+        if (me.orderSpritesByZIndex && len && zIndex < sprites[high].attr.zIndex) {
+            
+            while (low <= high) {
+                idx = ceil((low + high) / 2);
+                otherZIndex = sprites[idx].attr.zIndex;
+                if (otherZIndex > zIndex) {
+                    high = idx - 1;
+                }
+                else if (otherZIndex < zIndex) {
+                    low = idx + 1;
+                }
+                else {
+                    break;
+                }
+            }
+            
+            while (idx < len && sprites[idx].attr.zIndex <= zIndex) {
+                idx++;
+            }
+        }
+
+        me.items.insert(idx, sprite);
+        return idx;
+    },
+
+    onAdd: function(sprite) {
+        var group = sprite.group,
+            draggable = sprite.draggable,
+            groups, ln, i;
+        if (group) {
+            groups = [].concat(group);
+            ln = groups.length;
+            for (i = 0; i < ln; i++) {
+                group = groups[i];
+                this.getGroup(group).add(sprite);
+            }
+            delete sprite.group;
+        }
+        if (draggable) {
+            sprite.initDraggable();
+        }
+    },
+
+    
+    remove: function(sprite, destroySprite) {
+        if (sprite) {
+            this.items.remove(sprite);
+            this.groups.each(function(item) {
+                item.remove(sprite);
+            });
+            sprite.onRemove();
+            if (destroySprite === true) {
+                sprite.destroy();
+            }
+        }
+    },
+
+    
+    removeAll: function(destroySprites) {
+        var items = this.items.items,
+            ln = items.length,
+            i;
+        for (i = ln - 1; i > -1; i--) {
+            this.remove(items[i], destroySprites);
+        }
+    },
+
+    onRemove: Ext.emptyFn,
+
+    onDestroy: Ext.emptyFn,
+
+    
+    applyViewBox: function() {
+        var me = this,
+            viewBox = me.viewBox,
+            width = me.width,
+            height = me.height,
+            viewBoxX, viewBoxY, viewBoxWidth, viewBoxHeight,
+            relativeHeight, relativeWidth, size;
+
+        if (viewBox && (width || height)) {
+            viewBoxX = viewBox.x;
+            viewBoxY = viewBox.y;
+            viewBoxWidth = viewBox.width;
+            viewBoxHeight = viewBox.height;
+            relativeHeight = height / viewBoxHeight;
+            relativeWidth = width / viewBoxWidth;
+
+            if (viewBoxWidth * relativeHeight < width) {
+                viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
+            }
+            if (viewBoxHeight * relativeWidth < height) {
+                viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
+            }
+
+            size = 1 / Math.min(viewBoxWidth, relativeHeight);
+
+            me.viewBoxShift = {
+                dx: -viewBoxX,
+                dy: -viewBoxY,
+                scale: size
+            };
+        }
+    },
+
+    transformToViewBox: function (x, y) {
+        if (this.viewBoxShift) {
+            var me = this, shift = me.viewBoxShift;
+            return [x * shift.scale - shift.dx, y * shift.scale - shift.dy];
+        } else {
+            return [x, y];
+        }
+    },
+
+    
+    applyTransformations: function(sprite) {
+            sprite.bbox.transform = 0;
+            this.transform(sprite);
+
+        var me = this,
+            dirty = false,
+            attr = sprite.attr;
+
+        if (attr.translation.x != null || attr.translation.y != null) {
+            me.translate(sprite);
+            dirty = true;
+        }
+        if (attr.scaling.x != null || attr.scaling.y != null) {
+            me.scale(sprite);
+            dirty = true;
+        }
+        if (attr.rotation.degrees != null) {
+            me.rotate(sprite);
+            dirty = true;
+        }
+        if (dirty) {
+            sprite.bbox.transform = 0;
+            this.transform(sprite);
+            sprite.transformations = [];
+        }
+    },
+
+    
+    rotate: function (sprite) {
+        var bbox,
+            deg = sprite.attr.rotation.degrees,
+            centerX = sprite.attr.rotation.x,
+            centerY = sprite.attr.rotation.y;
+        if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
+            bbox = this.getBBox(sprite);
+            centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
+            centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
+        }
+        sprite.transformations.push({
+            type: "rotate",
+            degrees: deg,
+            x: centerX,
+            y: centerY
+        });
+    },
+
+    
+    translate: function(sprite) {
+        var x = sprite.attr.translation.x || 0,
+            y = sprite.attr.translation.y || 0;
+        sprite.transformations.push({
+            type: "translate",
+            x: x,
+            y: y
+        });
+    },
+
+    
+    scale: function(sprite) {
+        var bbox,
+            x = sprite.attr.scaling.x || 1,
+            y = sprite.attr.scaling.y || 1,
+            centerX = sprite.attr.scaling.centerX,
+            centerY = sprite.attr.scaling.centerY;
+
+        if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
+            bbox = this.getBBox(sprite);
+            centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
+            centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
+        }
+        sprite.transformations.push({
+            type: "scale",
+            x: x,
+            y: y,
+            centerX: centerX,
+            centerY: centerY
+        });
+    },
+
+    
+    rectPath: function (x, y, w, h, r) {
+        if (r) {
+            return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
+        }
+        return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
+    },
+
+    
+    ellipsePath: function (x, y, rx, ry) {
+        if (ry == null) {
+            ry = rx;
+        }
+        return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
+    },
+
+    
+    getPathpath: function (el) {
+        return el.attr.path;
+    },
+
+    
+    getPathcircle: function (el) {
+        var a = el.attr;
+        return this.ellipsePath(a.x, a.y, a.radius, a.radius);
+    },
+
+    
+    getPathellipse: function (el) {
+        var a = el.attr;
+        return this.ellipsePath(a.x, a.y,
+                                a.radiusX || (a.width / 2) || 0,
+                                a.radiusY || (a.height / 2) || 0);
+    },
+
+    
+    getPathrect: function (el) {
+        var a = el.attr;
+        return this.rectPath(a.x, a.y, a.width, a.height, a.r);
+    },
+
+    
+    getPathimage: function (el) {
+        var a = el.attr;
+        return this.rectPath(a.x || 0, a.y || 0, a.width, a.height);
+    },
+
+    
+    getPathtext: function (el) {
+        var bbox = this.getBBoxText(el);
+        return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
+    },
+
+    createGroup: function(id) {
+        var group = this.groups.get(id);
+        if (!group) {
+            group = Ext.create('Ext.draw.CompositeSprite', {
+                surface: this
+            });
+            group.id = id || Ext.id(null, 'ext-surface-group-');
+            this.groups.add(group);
+        }
+        return group;
+    },
+
+    
+    getGroup: function(id) {
+        if (typeof id == "string") {
+            var group = this.groups.get(id);
+            if (!group) {
+                group = this.createGroup(id);
+            }
+        } else {
+            group = id;
+        }
+        return group;
+    },
+
+    
+    prepareItems: function(items, applyDefaults) {
+        items = [].concat(items);
+        
+        var item, i, ln;
+        for (i = 0, ln = items.length; i < ln; i++) {
+            item = items[i];
+            if (!(item instanceof Ext.draw.Sprite)) {
+                
+                item.surface = this;
+                items[i] = this.createItem(item);
+            } else {
+                item.surface = this;
+            }
+        }
+        return items;
+    },
+
+    
+    setText: Ext.emptyFn,
+
+    //@private Creates an item and appends it to the surface. Called
+
+    
+    createItem: Ext.emptyFn,
+
+    
+    getId: function() {
+        return this.id || (this.id = Ext.id(null, 'ext-surface-'));
+    },
+
+    
+    destroy: function() {
+        delete this.domRef;
+        this.removeAll();
+    }
+});
+
+
+Ext.define('Ext.layout.component.Draw', {
+
+    
+
+    alias: 'layout.draw',
+
+    extend: 'Ext.layout.component.Auto',
+
+    
+
+    type: 'draw',
+
+    onLayout : function(width, height) {
+        this.owner.surface.setSize(width, height);
+        this.callParent(arguments);
+    }
+});
+
+Ext.define('Ext.draw.Component', {
+
+    
+
+    alias: 'widget.draw',
+
+    extend: 'Ext.Component',
+
+    requires: [
+        'Ext.draw.Surface',
+        'Ext.layout.component.Draw'
+    ],
+
+    
+
+    
+    enginePriority: ['Svg', 'Vml'],
+
+    baseCls: Ext.baseCSSPrefix + 'surface',
+
+    componentLayout: 'draw',
+
+    
+    viewBox: true,
+
+    
+    autoSize: false,
+
+    
+    initComponent: function() {
+        this.callParent(arguments);
+
+        this.addEvents(
+            'mousedown',
+            'mouseup',
+            'mousemove',
+            'mouseenter',
+            'mouseleave',
+            'click'
+        );
+    },
+
+    
+    onRender: function() {
+        var me = this,
+            viewBox = me.viewBox,
+            autoSize = me.autoSize,
+            bbox, items, width, height, x, y;
+        me.callParent(arguments);
+
+        if (me.createSurface() !== false) {
+            items = me.surface.items;
+
+            if (viewBox || autoSize) {
+                bbox = items.getBBox();
+                width = bbox.width;
+                height = bbox.height;
+                x = bbox.x;
+                y = bbox.y;
+                if (me.viewBox) {
+                    me.surface.setViewBox(x, y, width, height);
+                }
+                else {
+                    
+                    me.autoSizeSurface();
+                }
+            }
+        }
+    },
+
+    //@private
+
+    autoSizeSurface: function() {
+        var me = this,
+            items = me.surface.items,
+            bbox = items.getBBox(),
+            width = bbox.width,
+            height = bbox.height;
+        items.setAttributes({
+            translate: {
+                x: -bbox.x,
+                
+                y: -bbox.y + (+Ext.isOpera)
+            }
+        }, true);
+        if (me.rendered) {
+            me.setSize(width, height);
+            me.surface.setSize(width, height);
+        }
+        else {
+            me.surface.setSize(width, height);
+        }
+        me.el.setSize(width, height);
+    },
+
+    
+    createSurface: function() {
+        var surface = Ext.draw.Surface.create(Ext.apply({}, {
+                width: this.width,
+                height: this.height,
+                renderTo: this.el
+            }, this.initialConfig));
+        if (!surface) {
+            
+            return false;
+        }
+        this.surface = surface;
+
+
+        function refire(eventName) {
+            return function(e) {
+                this.fireEvent(eventName, e);
+            };
+        }
+
+        surface.on({
+            scope: this,
+            mouseup: refire('mouseup'),
+            mousedown: refire('mousedown'),
+            mousemove: refire('mousemove'),
+            mouseenter: refire('mouseenter'),
+            mouseleave: refire('mouseleave'),
+            click: refire('click')
+        });
+    },
+
+
+    
+    onDestroy: function() {
+        var surface = this.surface;
+        if (surface) {
+            surface.destroy();
+        }
+        this.callParent(arguments);
+    }
+
+});
+
+
+Ext.define('Ext.chart.LegendItem', {
+
+    
+
+    extend: 'Ext.draw.CompositeSprite',
+
+    requires: ['Ext.chart.Shape'],
+
+    
+
+    
+    x: 0,
+    y: 0,
+    zIndex: 500,
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        this.createLegend(config);
+    },
+
+    
+    createLegend: function(config) {
+        var me = this,
+            index = config.yFieldIndex,
+            series = me.series,
+            seriesType = series.type,
+            idx = me.yFieldIndex,
+            legend = me.legend,
+            surface = me.surface,
+            refX = legend.x + me.x,
+            refY = legend.y + me.y,
+            bbox, z = me.zIndex,
+            markerConfig, label, mask,
+            radius, toggle = false,
+            seriesStyle = Ext.apply(series.seriesStyle, series.style);
+
+        function getSeriesProp(name) {
+            var val = series[name];
+            return (Ext.isArray(val) ? val[idx] : val);
+        }
+        
+        label = me.add('label', surface.add({
+            type: 'text',
+            x: 20,
+            y: 0,
+            zIndex: z || 0,
+            font: legend.labelFont,
+            text: getSeriesProp('title') || getSeriesProp('yField')
+        }));
+
+        
+        if (seriesType === 'line' || seriesType === 'scatter') {
+            if(seriesType === 'line') {
+                me.add('line', surface.add({
+                    type: 'path',
+                    path: 'M0.5,0.5L16.5,0.5',
+                    zIndex: z,
+                    "stroke-width": series.lineWidth,
+                    "stroke-linejoin": "round",
+                    "stroke-dasharray": series.dash,
+                    stroke: seriesStyle.stroke || '#000',
+                    style: {
+                        cursor: 'pointer'
+                    }
+                }));
+            }
+            if (series.showMarkers || seriesType === 'scatter') {
+                markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
+                me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
+                    fill: markerConfig.fill,
+                    x: 8.5,
+                    y: 0.5,
+                    zIndex: z,
+                    radius: markerConfig.radius || markerConfig.size,
+                    style: {
+                        cursor: 'pointer'
+                    }
+                }));
+            }
+        }
+        
+        else {
+            me.add('box', surface.add({
+                type: 'rect',
+                zIndex: z,
+                x: 0,
+                y: 0,
+                width: 12,
+                height: 12,
+                fill: series.getLegendColor(index),
+                style: {
+                    cursor: 'pointer'
+                }
+            }));
+        }
+        
+        me.setAttributes({
+            hidden: false
+        }, true);
+        
+        bbox = me.getBBox();
+        
+        mask = me.add('mask', surface.add({
+            type: 'rect',
+            x: bbox.x,
+            y: bbox.y,
+            width: bbox.width || 20,
+            height: bbox.height || 20,
+            zIndex: (z || 0) + 1000,
+            fill: '#f00',
+            opacity: 0,
+            style: {
+                'cursor': 'pointer'
+            }
+        }));
+
+        
+        me.on('mouseover', function() {
+            label.setStyle({
+                'font-weight': 'bold'
+            });
+            mask.setStyle({
+                'cursor': 'pointer'
+            });
+            series._index = index;
+            series.highlightItem();
+        }, me);
+
+        me.on('mouseout', function() {
+            label.setStyle({
+                'font-weight': 'normal'
+            });
+            series._index = index;
+            series.unHighlightItem();
+        }, me);
+        
+        if (!series.visibleInLegend(index)) {
+            toggle = true;
+            label.setAttributes({
+               opacity: 0.5
+            }, true);
+        }
+
+        me.on('mousedown', function() {
+            if (!toggle) {
+                series.hideAll();
+                label.setAttributes({
+                    opacity: 0.5
+                }, true);
+            } else {
+                series.showAll();
+                label.setAttributes({
+                    opacity: 1
+                }, true);
+            }
+            toggle = !toggle;
+        }, me);
+        me.updatePosition({x:0, y:0}); 
+    },
+
+    
+    updatePosition: function(relativeTo) {
+        var me = this,
+            items = me.items,
+            ln = items.length,
+            i = 0,
+            item;
+        if (!relativeTo) {
+            relativeTo = me.legend;
+        }
+        for (; i < ln; i++) {
+            item = items[i];
+            switch (item.type) {
+                case 'text':
+                    item.setAttributes({
+                        x: 20 + relativeTo.x + me.x,
+                        y: relativeTo.y + me.y
+                    }, true);
+                    break;
+                case 'rect':
+                    item.setAttributes({
+                        translate: {
+                            x: relativeTo.x + me.x,
+                            y: relativeTo.y + me.y - 6
+                        }
+                    }, true);
+                    break;
+                default:
+                    item.setAttributes({
+                        translate: {
+                            x: relativeTo.x + me.x,
+                            y: relativeTo.y + me.y
+                        }
+                    }, true);
+            }
+        }
+    }
+});
+
+
+Ext.define('Ext.chart.Legend', {
+
+    
+
+    requires: ['Ext.chart.LegendItem'],
+
+    
+
+    
+    visible: true,
+
+    
+    position: 'bottom',
+
+    
+    x: 0,
+
+    
+    y: 0,
+
+    
+    labelFont: '12px Helvetica, sans-serif',
+
+    
+    boxStroke: '#000',
+
+    
+    boxStrokeWidth: 1,
+
+    
+    boxFill: '#FFF',
+
+    
+    itemSpacing: 10,
+
+    
+    padding: 5,
+
+    
+    width: 0,
+    
+    height: 0,
+
+    
+    boxZIndex: 100,
+
+    
+    constructor: function(config) {
+        var me = this;
+        if (config) {
+            Ext.apply(me, config);
+        }
+        me.items = [];
+        
+        me.isVertical = ("left|right|float".indexOf(me.position) !== -1);
+
+        
+        me.origX = me.x;
+        me.origY = me.y;
+    },
+
+    
+    create: function() {
+        var me = this;
+        me.createBox();
+        me.createItems();
+        if (!me.created && me.isDisplayed()) {
+            me.created = true;
+
+            
+            me.chart.series.each(function(series) {
+                series.on('titlechange', function() {
+                    me.create();
+                    me.updatePosition();
+                });
+            });
+        }
+    },
+
+    
+    isDisplayed: function() {
+        return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
+    },
+
+    
+    createItems: function() {
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            items = me.items,
+            padding = me.padding,
+            itemSpacing = me.itemSpacing,
+            spacingOffset = 2,
+            maxWidth = 0,
+            maxHeight = 0,
+            totalWidth = 0,
+            totalHeight = 0,
+            vertical = me.isVertical,
+            math = Math,
+            mfloor = math.floor,
+            mmax = math.max,
+            index = 0,
+            i = 0,
+            len = items ? items.length : 0,
+            x, y, spacing, item, bbox, height, width;
+
+        
+        if (len) {
+            for (; i < len; i++) {
+                items[i].destroy();
+            }
+        }
+        
+        items.length = [];
+        
+        
+        chart.series.each(function(series, i) {
+            if (series.showInLegend) {
+                Ext.each([].concat(series.yField), function(field, j) {
+                    item = Ext.create('Ext.chart.LegendItem', {
+                        legend: this,
+                        series: series,
+                        surface: chart.surface,
+                        yFieldIndex: j
+                    });
+                    bbox = item.getBBox();
+
+                    
+                    width = bbox.width;
+                    height = bbox.height;
+
+                    if (i + j === 0) {
+                        spacing = vertical ? padding + height / 2 : padding;
+                    }
+                    else {
+                        spacing = itemSpacing / (vertical ? 2 : 1);
+                    }
+                    
+                    item.x = mfloor(vertical ? padding : totalWidth + spacing);
+                    item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
+
+                    
+                    totalWidth += width + spacing;
+                    totalHeight += height + spacing;
+                    maxWidth = mmax(maxWidth, width);
+                    maxHeight = mmax(maxHeight, height);
+
+                    items.push(item);
+                }, this);
+            }
+        }, me);
+
+        
+        me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
+        if (vertical && items.length === 1) {
+            spacingOffset = 1;
+        }
+        me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
+        me.itemHeight = maxHeight;
+    },
+
+    
+    getBBox: function() {
+        var me = this;
+        return {
+            x: Math.round(me.x) - me.boxStrokeWidth / 2,
+            y: Math.round(me.y) - me.boxStrokeWidth / 2,
+            width: me.width,
+            height: me.height
+        };
+    },
+
+    
+    createBox: function() {
+        var me = this,
+            box;
+
+        if (me.boxSprite) {
+            me.boxSprite.destroy();
+        }
+        
+        box = me.boxSprite = me.chart.surface.add(Ext.apply({
+            type: 'rect',
+            stroke: me.boxStroke,
+            "stroke-width": me.boxStrokeWidth,
+            fill: me.boxFill,
+            zIndex: me.boxZIndex
+        }, me.getBBox()));
+
+        box.redraw();
+    },
+
+    
+    updatePosition: function() {
+        var me = this,
+            x, y,
+            legendWidth = me.width,
+            legendHeight = me.height,
+            padding = me.padding,
+            chart = me.chart,
+            chartBBox = chart.chartBBox,
+            insets = chart.insetPadding,
+            chartWidth = chartBBox.width - (insets * 2),
+            chartHeight = chartBBox.height - (insets * 2),
+            chartX = chartBBox.x + insets,
+            chartY = chartBBox.y + insets,
+            surface = chart.surface,
+            mfloor = Math.floor;
+
+        if (me.isDisplayed()) {
+            
+            switch(me.position) {
+                case "left":
+                    x = insets;
+                    y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
+                    break;
+                case "right":
+                    x = mfloor(surface.width - legendWidth) - insets;
+                    y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
+                    break;
+                case "top":
+                    x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
+                    y = insets;
+                    break;
+                case "bottom":
+                    x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
+                    y = mfloor(surface.height - legendHeight) - insets;
+                    break;
+                default:
+                    x = mfloor(me.origX) + insets;
+                    y = mfloor(me.origY) + insets;
+            }
+            me.x = x;
+            me.y = y;
+
+            
+            Ext.each(me.items, function(item) {
+                item.updatePosition();
+            });
+            
+            me.boxSprite.setAttributes(me.getBBox(), true);
+        }
+    }
+});
+
+
+Ext.define('Ext.chart.Chart', {
+
+    
+
+    alias: 'widget.chart',
+
+    extend: 'Ext.draw.Component',
+    
+    mixins: {
+        themeManager: 'Ext.chart.theme.Theme',
+        mask: 'Ext.chart.Mask',
+        navigation: 'Ext.chart.Navigation'
+    },
+
+    requires: [
+        'Ext.util.MixedCollection',
+        'Ext.data.StoreManager',
+        'Ext.chart.Legend',
+        'Ext.util.DelayedTask'
+    ],
+
+    
+
+    
+    viewBox: false,
+
+    
+
+    
+    animate: false,
+
+    
+    legend: false,
+
+    
+    insetPadding: 10,
+
+    
+    enginePriority: ['Svg', 'Vml'],
+
+    
+    background: false,
+
+    
+
+    
+
+    
+
+    
+
+    constructor: function(config) {
+        var me = this,
+            defaultAnim;
+            
+        config = Ext.apply({}, config);
+        me.initTheme(config.theme || me.theme);
+        if (me.gradients) {
+            Ext.apply(config, { gradients: me.gradients });
+        }
+        if (me.background) {
+            Ext.apply(config, { background: me.background });
+        }
+        if (config.animate) {
+            defaultAnim = {
+                easing: 'ease',
+                duration: 500
+            };
+            if (Ext.isObject(config.animate)) {
+                config.animate = Ext.applyIf(config.animate, defaultAnim);
+            }
+            else {
+                config.animate = defaultAnim;
+            }
+        }
+        me.mixins.mask.constructor.call(me, config);
+        me.mixins.navigation.constructor.call(me, config);
+        me.callParent([config]);
+    },
+    
+    getChartStore: function(){
+        return this.substore || this.store;    
+    },
+
+    initComponent: function() {
+        var me = this,
+            axes,
+            series;
+        me.callParent();
+        me.addEvents(
+            'itemmousedown',
+            'itemmouseup',
+            'itemmouseover',
+            'itemmouseout',
+            'itemclick',
+            'itemdoubleclick',
+            'itemdragstart',
+            'itemdrag',
+            'itemdragend',
+            
+            'beforerefresh',
+            
+            'refresh'
+        );
+        Ext.applyIf(me, {
+            zoom: {
+                width: 1,
+                height: 1,
+                x: 0,
+                y: 0
+            }
+        });
+        me.maxGutter = [0, 0];
+        me.store = Ext.data.StoreManager.lookup(me.store);
+        axes = me.axes;
+        me.axes = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.position; });
+        if (axes) {
+            me.axes.addAll(axes);
+        }
+        series = me.series;
+        me.series = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); });
+        if (series) {
+            me.series.addAll(series);
+        }
+        if (me.legend !== false) {
+            me.legend = Ext.create('Ext.chart.Legend', Ext.applyIf({chart:me}, me.legend));
+        }
+
+        me.on({
+            mousemove: me.onMouseMove,
+            mouseleave: me.onMouseLeave,
+            mousedown: me.onMouseDown,
+            mouseup: me.onMouseUp,
+            scope: me
+        });
+    },
+
+    
+    afterComponentLayout: function(width, height) {
+        var me = this;
+        if (Ext.isNumber(width) && Ext.isNumber(height)) {
+            me.curWidth = width;
+            me.curHeight = height;
+            me.redraw(true);
+        }
+        this.callParent(arguments);
+    },
+
+    
+    redraw: function(resize) {
+        var me = this,
+            chartBBox = me.chartBBox = {
+                x: 0,
+                y: 0,
+                height: me.curHeight,
+                width: me.curWidth
+            },
+            legend = me.legend;
+        me.surface.setSize(chartBBox.width, chartBBox.height);
+        
+        me.series.each(me.initializeSeries, me);
+        me.axes.each(me.initializeAxis, me);
+        
+        
+        me.axes.each(function(axis) {
+            axis.processView();
+        });
+        me.axes.each(function(axis) {
+            axis.drawAxis(true);
+        });
+
+        
+        if (legend !== false) {
+            legend.create();
+        }
+
+        
+        me.alignAxes();
+
+        
+        if (me.legend !== false) {
+            legend.updatePosition();
+        }
+
+        
+        me.getMaxGutter();
+
+        
+        me.resizing = !!resize;
+
+        me.axes.each(me.drawAxis, me);
+        me.series.each(me.drawCharts, me);
+        me.resizing = false;
+    },
+
+    
+    afterRender: function() {
+        var ref,
+            me = this;
+        this.callParent();
+
+        if (me.categoryNames) {
+            me.setCategoryNames(me.categoryNames);
+        }
+
+        if (me.tipRenderer) {
+            ref = me.getFunctionRef(me.tipRenderer);
+            me.setTipRenderer(ref.fn, ref.scope);
+        }
+        me.bindStore(me.store, true);
+        me.refresh();
+    },
+
+    
+    getEventXY: function(e) {
+        var me = this,
+            box = this.surface.getRegion(),
+            pageXY = e.getXY(),
+            x = pageXY[0] - box.left,
+            y = pageXY[1] - box.top;
+        return [x, y];
+    },
+
+    
+    onClick: function(e) {
+        var me = this,
+            position = me.getEventXY(e),
+            item;
+
+        
+        
+        me.series.each(function(series) {
+            if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+                if (series.getItemForPoint) {
+                    item = series.getItemForPoint(position[0], position[1]);
+                    if (item) {
+                        series.fireEvent('itemclick', item);
+                    }
+                }
+            }
+        }, me);
+    },
+
+    
+    onMouseDown: function(e) {
+        var me = this,
+            position = me.getEventXY(e),
+            item;
+
+        if (me.mask) {
+            me.mixins.mask.onMouseDown.call(me, e);
+        }
+        
+        
+        me.series.each(function(series) {
+            if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+                if (series.getItemForPoint) {
+                    item = series.getItemForPoint(position[0], position[1]);
+                    if (item) {
+                        series.fireEvent('itemmousedown', item);
+                    }
+                }
+            }
+        }, me);
+    },
+
+    
+    onMouseUp: function(e) {
+        var me = this,
+            position = me.getEventXY(e),
+            item;
+
+        if (me.mask) {
+            me.mixins.mask.onMouseUp.call(me, e);
+        }
+        
+        
+        me.series.each(function(series) {
+            if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+                if (series.getItemForPoint) {
+                    item = series.getItemForPoint(position[0], position[1]);
+                    if (item) {
+                        series.fireEvent('itemmouseup', item);
+                    }
+                }
+            }
+        }, me);
+    },
+
+    
+    onMouseMove: function(e) {
+        var me = this,
+            position = me.getEventXY(e),
+            item, last, storeItem, storeField;
+
+        if (me.mask) {
+            me.mixins.mask.onMouseMove.call(me, e);
+        }
+        
+        
+        me.series.each(function(series) {
+            if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
+                if (series.getItemForPoint) {
+                    item = series.getItemForPoint(position[0], position[1]);
+                    last = series._lastItemForPoint;
+                    storeItem = series._lastStoreItem;
+                    storeField = series._lastStoreField;
+
+
+                    if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) {
+                        if (last) {
+                            series.fireEvent('itemmouseout', last);
+                            delete series._lastItemForPoint;
+                            delete series._lastStoreField;
+                            delete series._lastStoreItem;
+                        }
+                        if (item) {
+                            series.fireEvent('itemmouseover', item);
+                            series._lastItemForPoint = item;
+                            series._lastStoreItem = item.storeItem;
+                            series._lastStoreField = item.storeField;
+                        }
+                    }
+                }
+            } else {
+                last = series._lastItemForPoint;
+                if (last) {
+                    series.fireEvent('itemmouseout', last);
+                    delete series._lastItemForPoint;
+                    delete series._lastStoreField;
+                    delete series._lastStoreItem;
+                }
+            }
+        }, me);
+    },
+
+    
+    onMouseLeave: function(e) {
+        var me = this;
+        if (me.mask) {
+            me.mixins.mask.onMouseLeave.call(me, e);
+        }
+        me.series.each(function(series) {
+            delete series._lastItemForPoint;
+        });
+    },
+
+    
+    delayRefresh: function() {
+        var me = this;
+        if (!me.refreshTask) {
+            me.refreshTask = Ext.create('Ext.util.DelayedTask', me.refresh, me);
+        }
+        me.refreshTask.delay(me.refreshBuffer);
+    },
+
+    
+    refresh: function() {
+        var me = this;
+        if (me.rendered && me.curWidth !== undefined && me.curHeight !== undefined) {
+            if (me.fireEvent('beforerefresh', me) !== false) {
+                me.redraw();
+                me.fireEvent('refresh', me);
+            }
+        }
+    },
+
+    
+    bindStore: function(store, initial) {
+        var me = this;
+        if (!initial && me.store) {
+            if (store !== me.store && me.store.autoDestroy) {
+                me.store.destroyStore();
+            }
+            else {
+                me.store.un('datachanged', me.refresh, me);
+                me.store.un('add', me.delayRefresh, me);
+                me.store.un('remove', me.delayRefresh, me);
+                me.store.un('update', me.delayRefresh, me);
+                me.store.un('clear', me.refresh, me);
+            }
+        }
+        if (store) {
+            store = Ext.data.StoreManager.lookup(store);
+            store.on({
+                scope: me,
+                datachanged: me.refresh,
+                add: me.delayRefresh,
+                remove: me.delayRefresh,
+                update: me.delayRefresh,
+                clear: me.refresh
+            });
+        }
+        me.store = store;
+        if (store && !initial) {
+            me.refresh();
+        }
+    },
+
+    
+    initializeAxis: function(axis) {
+        var me = this,
+            chartBBox = me.chartBBox,
+            w = chartBBox.width,
+            h = chartBBox.height,
+            x = chartBBox.x,
+            y = chartBBox.y,
+            themeAttrs = me.themeAttrs,
+            config = {
+                chart: me
+            };
+        if (themeAttrs) {
+            config.axisStyle = Ext.apply({}, themeAttrs.axis);
+            config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft);
+            config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight);
+            config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop);
+            config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom);
+            config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft);
+            config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight);
+            config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop);
+            config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom);
+        }
+        switch (axis.position) {
+            case 'top':
+                Ext.apply(config, {
+                    length: w,
+                    width: h,
+                    x: x,
+                    y: y
+                });
+            break;
+            case 'bottom':
+                Ext.apply(config, {
+                    length: w,
+                    width: h,
+                    x: x,
+                    y: h
+                });
+            break;
+            case 'left':
+                Ext.apply(config, {
+                    length: h,
+                    width: w,
+                    x: x,
+                    y: h
+                });
+            break;
+            case 'right':
+                Ext.apply(config, {
+                    length: h,
+                    width: w,
+                    x: w,
+                    y: h
+                });
+            break;
+        }
+        if (!axis.chart) {
+            Ext.apply(config, axis);
+            axis = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
+        }
+        else {
+            Ext.apply(axis, config);
+        }
+    },
+
+
+    
+    alignAxes: function() {
+        var me = this,
+            axes = me.axes,
+            legend = me.legend,
+            edges = ['top', 'right', 'bottom', 'left'],
+            chartBBox,
+            insetPadding = me.insetPadding,
+            insets = {
+                top: insetPadding,
+                right: insetPadding,
+                bottom: insetPadding,
+                left: insetPadding
+            };
+
+        function getAxis(edge) {
+            var i = axes.findIndex('position', edge);
+            return (i < 0) ? null : axes.getAt(i);
+        }
+
+        
+        Ext.each(edges, function(edge) {
+            var isVertical = (edge === 'left' || edge === 'right'),
+                axis = getAxis(edge),
+                bbox;
+
+            
+            if (legend !== false) {
+                if (legend.position === edge) {
+                    bbox = legend.getBBox();
+                    insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
+                }
+            }
+
+            
+            
+            if (axis && axis.bbox) {
+                bbox = axis.bbox;
+                insets[edge] += (isVertical ? bbox.width : bbox.height);
+            }
+        });
+        
+        chartBBox = {
+            x: insets.left,
+            y: insets.top,
+            width: me.curWidth - insets.left - insets.right,
+            height: me.curHeight - insets.top - insets.bottom
+        };
+        me.chartBBox = chartBBox;
+
+        
+        
+        axes.each(function(axis) {
+            var pos = axis.position,
+                isVertical = (pos === 'left' || pos === 'right');
+
+            axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
+            axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
+            axis.width = (isVertical ? chartBBox.width : chartBBox.height);
+            axis.length = (isVertical ? chartBBox.height : chartBBox.width);
+        });
+    },
+
+    
+    initializeSeries: function(series, idx) {
+        var me = this,
+            themeAttrs = me.themeAttrs,
+            seriesObj, markerObj, seriesThemes, st,
+            markerThemes, colorArrayStyle = [],
+            i = 0, l,
+            config = {
+                chart: me,
+                seriesId: series.seriesId
+            };
+        if (themeAttrs) {
+            seriesThemes = themeAttrs.seriesThemes;
+            markerThemes = themeAttrs.markerThemes;
+            seriesObj = Ext.apply({}, themeAttrs.series);
+            markerObj = Ext.apply({}, themeAttrs.marker);
+            config.seriesStyle = Ext.apply(seriesObj, seriesThemes[idx % seriesThemes.length]);
+            config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
+            config.markerStyle = Ext.apply(markerObj, markerThemes[idx % markerThemes.length]);
+            if (themeAttrs.colors) {
+                config.colorArrayStyle = themeAttrs.colors;
+            } else {
+                colorArrayStyle = [];
+                for (l = seriesThemes.length; i < l; i++) {
+                    st = seriesThemes[i];
+                    if (st.fill || st.stroke) {
+                        colorArrayStyle.push(st.fill || st.stroke);
+                    }
+                }
+                if (colorArrayStyle.length) {
+                    config.colorArrayStyle = colorArrayStyle;
+                }
+            }
+            config.seriesIdx = idx;
+        }
+        if (series instanceof Ext.chart.series.Series) {
+            Ext.apply(series, config);
+        } else {
+            Ext.applyIf(config, series);
+            series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
+        }
+        if (series.initialize) {
+            series.initialize();
+        }
+    },
+
+    
+    getMaxGutter: function() {
+        var me = this,
+            maxGutter = [0, 0];
+        me.series.each(function(s) {
+            var gutter = s.getGutters && s.getGutters() || [0, 0];
+            maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
+            maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
+        });
+        me.maxGutter = maxGutter;
+    },
+
+    
+    drawAxis: function(axis) {
+        axis.drawAxis();
+    },
+
+    
+    drawCharts: function(series) {
+        series.triggerafterrender = false;
+        series.drawSeries();
+        if (!this.animate) {
+            series.fireEvent('afterrender');
+        }
+    },
+
+    
+    destroy: function() {
+        Ext.destroy(this.surface);
+        this.bindStore(null);
+        this.callParent(arguments);
+    }
+});
+
+
+Ext.define('Ext.chart.Highlight', {
+
+    
+
+    requires: ['Ext.fx.Anim'],
+
+    
+
+    
+    highlight: false,
+
+    highlightCfg : null,
+
+    constructor: function(config) {
+        if (config.highlight) {
+            if (config.highlight !== true) { 
+                this.highlightCfg = Ext.apply({}, config.highlight);
+            }
+            else {
+                this.highlightCfg = {
+                    fill: '#fdd',
+                    radius: 20,
+                    lineWidth: 5,
+                    stroke: '#f55'
+                };
+            }
+        }
+    },
+
+    
+    highlightItem: function(item) {
+        if (!item) {
+            return;
+        }
+        
+        var me = this,
+            sprite = item.sprite,
+            opts = me.highlightCfg,
+            surface = me.chart.surface,
+            animate = me.chart.animate,
+            p, from, to, pi;
+
+        if (!me.highlight || !sprite || sprite._highlighted) {
+            return;
+        }
+        if (sprite._anim) {
+            sprite._anim.paused = true;
+        }
+        sprite._highlighted = true;
+        if (!sprite._defaults) {
+            sprite._defaults = Ext.apply({}, sprite.attr);
+            from = {};
+            to = {};
+            for (p in opts) {
+                if (! (p in sprite._defaults)) {
+                    sprite._defaults[p] = surface.availableAttrs[p];
+                }
+                from[p] = sprite._defaults[p];
+                to[p] = opts[p];
+                if (Ext.isObject(opts[p])) {
+                    from[p] = {};
+                    to[p] = {};
+                    Ext.apply(sprite._defaults[p], sprite.attr[p]);
+                    Ext.apply(from[p], sprite._defaults[p]);
+                    for (pi in sprite._defaults[p]) {
+                        if (! (pi in opts[p])) {
+                            to[p][pi] = from[p][pi];
+                        } else {
+                            to[p][pi] = opts[p][pi];
+                        }
+                    }
+                    for (pi in opts[p]) {
+                        if (! (pi in to[p])) {
+                            to[p][pi] = opts[p][pi];
+                        }
+                    }
+                }
+            }
+            sprite._from = from;
+            sprite._to = to;
+            sprite._endStyle = to;
+        }
+        if (animate) {
+            sprite._anim = Ext.create('Ext.fx.Anim', {
+                target: sprite,
+                from: sprite._from,
+                to: sprite._to,
+                duration: 150
+            });
+        } else {
+            sprite.setAttributes(sprite._to, true);
+        }
+    },
+
+    
+    unHighlightItem: function() {
+        if (!this.highlight || !this.items) {
+            return;
+        }
+
+        var me = this,
+            items = me.items,
+            len = items.length,
+            opts = me.highlightCfg,
+            animate = me.chart.animate,
+            i = 0,
+            obj, p, sprite;
+
+        for (; i < len; i++) {
+            if (!items[i]) {
+                continue;
+            }
+            sprite = items[i].sprite;
+            if (sprite && sprite._highlighted) {
+                if (sprite._anim) {
+                    sprite._anim.paused = true;
+                }
+                obj = {};
+                for (p in opts) {
+                    if (Ext.isObject(sprite._defaults[p])) {
+                        obj[p] = {};
+                        Ext.apply(obj[p], sprite._defaults[p]);
+                    }
+                    else {
+                        obj[p] = sprite._defaults[p];
+                    }
+                }
+                if (animate) {
+                    
+                    sprite._endStyle = obj;
+                    sprite._anim = Ext.create('Ext.fx.Anim', {
+                        target: sprite,
+                        to: obj,
+                        duration: 150
+                    });
+                }
+                else {
+                    sprite.setAttributes(obj, true);
+                }
+                delete sprite._highlighted;
+                
+            }
+        }
+    },
+
+    cleanHighlights: function() {
+        if (!this.highlight) {
+            return;
+        }
+
+        var group = this.group,
+            markerGroup = this.markerGroup,
+            i = 0,
+            l;
+        for (l = group.getCount(); i < l; i++) {
+            delete group.getAt(i)._defaults;
+        }
+        if (markerGroup) {
+            for (l = markerGroup.getCount(); i < l; i++) {
+                delete markerGroup.getAt(i)._defaults;
+            }
+        }
+    }
+});
+
+Ext.define('Ext.chart.Label', {
+
+    
+
+    requires: ['Ext.draw.Color'],
+
+    
+
+    
+
+    //@private a regex to parse url type colors.
+
+    colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/,
+
+    //@private the mixin constructor. Used internally by Series.
+
+    constructor: function(config) {
+        var me = this;
+        me.label = Ext.applyIf(me.label || {},
+        {
+            display: "none",
+            color: "#000",
+            field: "name",
+            minMargin: 50,
+            font: "11px Helvetica, sans-serif",
+            orientation: "horizontal",
+            renderer: function(v) {
+                return v;
+            }
+        });
+
+        if (me.label.display !== 'none') {
+            me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels');
+        }
+    },
+
+    //@private a method to render all labels in the labelGroup
+
+    renderLabels: function() {
+        var me = this,
+            chart = me.chart,
+            gradients = chart.gradients,
+            items = me.items,
+            animate = chart.animate,
+            config = me.label,
+            display = config.display,
+            color = config.color,
+            field = [].concat(config.field),
+            group = me.labelsGroup,
+            groupLength = (group || 0) && group.length,
+            store = me.chart.store,
+            len = store.getCount(),
+            itemLength = (items || 0) && items.length,
+            ratio = itemLength / len,
+            gradientsCount = (gradients || 0) && gradients.length,
+            Color = Ext.draw.Color,
+            hides = [],
+            gradient, i, count, groupIndex, index, j, k, colorStopTotal, colorStopIndex, colorStop, item, label,
+            storeItem, sprite, spriteColor, spriteBrightness, labelColor, colorString;
+
+        if (display == 'none') {
+            return;
+        }
+        
+        if(itemLength == 0){
+            while(groupLength--)
+                hides.push(groupLength);
+        }else{
+            for (i = 0, count = 0, groupIndex = 0; i < len; i++) {
+                index = 0;
+                for (j = 0; j < ratio; j++) {
+                    item = items[count];
+                    label = group.getAt(groupIndex);
+                    storeItem = store.getAt(i);
+                    
+                    while(this.__excludes && this.__excludes[index] && ratio > 1) {
+                        if(field[j]){
+                            hides.push(groupIndex);
+                        }
+                        index++;
+
+                    }
+
+                    if (!item && label) {
+                        label.hide(true);
+                        groupIndex++;
+                    }
+
+                    if (item && field[j]) {
+                        if (!label) {
+                            label = me.onCreateLabel(storeItem, item, i, display, j, index);
+                        }
+                        me.onPlaceLabel(label, storeItem, item, i, display, animate, j, index);
+                        groupIndex++;
+
+                        
+                        if (config.contrast && item.sprite) {
+                            sprite = item.sprite;
+                            
+                            if (sprite._endStyle) {
+                                colorString = sprite._endStyle.fill;
+                            }
+                            else if (sprite._to) {
+                                colorString = sprite._to.fill;
+                            }
+                            else {
+                                colorString = sprite.attr.fill;
+                            }
+                            colorString = colorString || sprite.attr.fill;
+
+                            spriteColor = Color.fromString(colorString);
+                            
+                            if (colorString && !spriteColor) {
+                                colorString = colorString.match(me.colorStringRe)[1];
+                                for (k = 0; k < gradientsCount; k++) {
+                                    gradient = gradients[k];
+                                    if (gradient.id == colorString) {
+                                        
+                                        colorStop = 0; colorStopTotal = 0;
+                                        for (colorStopIndex in gradient.stops) {
+                                            colorStop++;
+                                            colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
+                                        }
+                                        spriteBrightness = (colorStopTotal / colorStop) / 255;
+                                        break;
+                                    }
+                                }
+                            }
+                            else {
+                                spriteBrightness = spriteColor.getGrayscale() / 255;
+                            }
+                            if (label.isOutside) {
+                                spriteBrightness = 1;
+                            }
+                            labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
+                            labelColor[2] = spriteBrightness > 0.5 ? 0.2 : 0.8;
+                            label.setAttributes({
+                                fill: String(Color.fromHSL.apply({}, labelColor))
+                            }, true);
+                        }
+
+                    }
+                    count++;
+                    index++;
+                }
+            }
+        }
+        me.hideLabels(hides);
+    },
+    hideLabels: function(hides){
+        var labelsGroup = this.labelsGroup,
+            hlen = hides.length;
+        while(hlen--)
+            labelsGroup.getAt(hides[hlen]).hide(true);
+    }
+});
+Ext.define('Ext.chart.MaskLayer', {
+    extend: 'Ext.Component',
+    
+    constructor: function(config) {
+        config = Ext.apply(config || {}, {
+            style: 'position:absolute;background-color:#888;cursor:move;opacity:0.6;border:1px solid #222;'
+        });
+        this.callParent([config]);    
+    },
+    
+    initComponent: function() {
+        var me = this;
+        me.callParent(arguments);
+        me.addEvents(
+            'mousedown',
+            'mouseup',
+            'mousemove',
+            'mouseenter',
+            'mouseleave'
+        );
+    },
+
+    initDraggable: function() {
+        this.callParent(arguments);
+        this.dd.onStart = function (e) {
+            var me = this,
+                comp = me.comp;
+    
+            
+            this.startPosition = comp.getPosition(true);
+    
+            
+            
+            if (comp.ghost && !comp.liveDrag) {
+                 me.proxy = comp.ghost();
+                 me.dragTarget = me.proxy.header.el;
+            }
+    
+            
+            if (me.constrain || me.constrainDelegate) {
+                me.constrainTo = me.calculateConstrainRegion();
+            }
+        };
+    }
+});
+
+Ext.define('Ext.chart.TipSurface', {
+
+    
+
+    extend: 'Ext.draw.Component',
+
+    
+
+    spriteArray: false,
+    renderFirst: true,
+
+    constructor: function(config) {
+        this.callParent([config]);
+        if (config.sprites) {
+            this.spriteArray = [].concat(config.sprites);
+            delete config.sprites;
+        }
+    },
+
+    onRender: function() {
+        var me = this,
+            i = 0,
+            l = 0,
+            sp,
+            sprites;
+            this.callParent(arguments);
+        sprites = me.spriteArray;
+        if (me.renderFirst && sprites) {
+            me.renderFirst = false;
+            for (l = sprites.length; i < l; i++) {
+                sp = me.surface.add(sprites[i]);
+                sp.setAttributes({
+                    hidden: false
+                },
+                true);
+            }
+        }
+    }
+});
+
+
+Ext.define('Ext.chart.Tip', {
+
+    
+
+    requires: ['Ext.tip.ToolTip', 'Ext.chart.TipSurface'],
+
+    
+
+    constructor: function(config) {
+        var me = this,
+            surface,
+            sprites,
+            tipSurface;
+        if (config.tips) {
+            me.tipTimeout = null;
+            me.tipConfig = Ext.apply({}, config.tips, {
+                renderer: Ext.emptyFn,
+                constrainPosition: false
+            });
+            me.tooltip = Ext.create('Ext.tip.ToolTip', me.tipConfig);
+            me.chart.surface.on('mousemove', me.tooltip.onMouseMove, me.tooltip);
+            me.chart.surface.on('mouseleave', function() {
+                me.hideTip();
+            });
+            if (me.tipConfig.surface) {
+                
+                surface = me.tipConfig.surface;
+                sprites = surface.sprites;
+                tipSurface = Ext.create('Ext.chart.TipSurface', {
+                    id: 'tipSurfaceComponent',
+                    sprites: sprites
+                });
+                if (surface.width && surface.height) {
+                    tipSurface.setSize(surface.width, surface.height);
+                }
+                me.tooltip.add(tipSurface);
+                me.spriteTip = tipSurface;
+            }
+        }
+    },
+
+    showTip: function(item) {
+        var me = this;
+        if (!me.tooltip) {
+            return;
+        }
+        clearTimeout(me.tipTimeout);
+        var tooltip = me.tooltip,
+            spriteTip = me.spriteTip,
+            tipConfig = me.tipConfig,
+            trackMouse = tooltip.trackMouse,
+            sprite, surface, surfaceExt, pos, x, y;
+        if (!trackMouse) {
+            tooltip.trackMouse = true;
+            sprite = item.sprite;
+            surface = sprite.surface;
+            surfaceExt = Ext.get(surface.getId());
+            if (surfaceExt) {
+                pos = surfaceExt.getXY();
+                x = pos[0] + (sprite.attr.x || 0) + (sprite.attr.translation && sprite.attr.translation.x || 0);
+                y = pos[1] + (sprite.attr.y || 0) + (sprite.attr.translation && sprite.attr.translation.y || 0);
+                tooltip.targetXY = [x, y];
+            }
+        }
+        if (spriteTip) {
+            tipConfig.renderer.call(tooltip, item.storeItem, item, spriteTip.surface);
+        } else {
+            tipConfig.renderer.call(tooltip, item.storeItem, item);
+        }
+        tooltip.show();
+        tooltip.trackMouse = trackMouse;
+    },
+
+    hideTip: function(item) {
+        var tooltip = this.tooltip;
+        if (!tooltip) {
+            return;
+        }
+        clearTimeout(this.tipTimeout);
+        this.tipTimeout = setTimeout(function() {
+            tooltip.hide();
+        }, 0);
+    }
+});
+
+Ext.define('Ext.chart.axis.Abstract', {
+
+    
+
+    requires: ['Ext.chart.Chart'],
+
+    
+
+    
+    constructor: function(config) {
+        config = config || {};
+
+        var me = this,
+            pos = config.position || 'left';
+
+        pos = pos.charAt(0).toUpperCase() + pos.substring(1);
+        
+        config.label = Ext.apply(config['axisLabel' + pos + 'Style'] || {}, config.label || {});
+        config.axisTitleStyle = Ext.apply(config['axisTitle' + pos + 'Style'] || {}, config.labelTitle || {});
+        Ext.apply(me, config);
+        me.fields = [].concat(me.fields);
+        this.callParent();
+        me.labels = [];
+        me.getId();
+        me.labelGroup = me.chart.surface.getGroup(me.axisId + "-labels");
+    },
+
+    alignment: null,
+    grid: false,
+    steps: 10,
+    x: 0,
+    y: 0,
+    minValue: 0,
+    maxValue: 0,
+
+    getId: function() {
+        return this.axisId || (this.axisId = Ext.id(null, 'ext-axis-'));
+    },
+
+    
+    processView: Ext.emptyFn,
+
+    drawAxis: Ext.emptyFn,
+    addDisplayAndLabels: Ext.emptyFn
+});
+
+
+Ext.define('Ext.chart.axis.Axis', {
+
+    
+
+    extend: 'Ext.chart.axis.Abstract',
+
+    alternateClassName: 'Ext.chart.Axis',
+
+    requires: ['Ext.draw.Draw'],
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    //@private force min/max values from store
+
+    forceMinMax: false,
+
+    
+    dashSize: 3,
+
+    
+    position: 'bottom',
+
+    
+    skipFirst: false,
+
+    
+    length: 0,
+
+    
+    width: 0,
+
+    majorTickSteps: false,
+
+    
+    applyData: Ext.emptyFn,
+
+    getRange: function () {
+        var me = this,
+            store = me.chart.getChartStore(),
+            fields = me.fields,
+            ln = fields.length,
+            math = Math,
+            mmax = math.max,
+            mmin = math.min,
+            aggregate = false,
+            min = isNaN(me.minimum) ? Infinity : me.minimum,
+            max = isNaN(me.maximum) ? -Infinity : me.maximum,
+            total = 0, i, l, value, values, rec,
+            excludes = [],
+            series = me.chart.series.items;
+
+        
+        
+        
+        
+        
+        
+        
+        
+        for (i = 0, l = series.length; !aggregate && i < l; i++) {
+            aggregate = aggregate || series[i].stacked;
+            excludes = series[i].__excludes || excludes;
+        }
+        store.each(function(record) {
+            if (aggregate) {
+                if (!isFinite(min)) {
+                    min = 0;
+                }
+                for (values = [0, 0], i = 0; i < ln; i++) {
+                    if (excludes[i]) {
+                        continue;
+                    }
+                    rec = record.get(fields[i]);
+                    values[+(rec > 0)] += math.abs(rec);
+                }
+                max = mmax(max, -values[0], +values[1]);
+                min = mmin(min, -values[0], +values[1]);
+            }
+            else {
+                for (i = 0; i < ln; i++) {
+                    if (excludes[i]) {
+                        continue;
+                    }
+                    value = record.get(fields[i]);
+                    max = mmax(max, +value);
+                    min = mmin(min, +value);
+                }
+            }
+        });
+        if (!isFinite(max)) {
+            max = me.prevMax || 0;
+        }
+        if (!isFinite(min)) {
+            min = me.prevMin || 0;
+        }
+        
+        if (min != max && (max != Math.floor(max))) {
+            max = Math.floor(max) + 1;
+        }
+
+        if (!isNaN(me.minimum)) {
+            min = me.minimum;
+        }
+        
+        if (!isNaN(me.maximum)) {
+            max = me.maximum;
+        }
+
+        return {min: min, max: max};
+    },
+
+    
+    calcEnds: function() {
+        var me = this,
+            fields = me.fields,
+            range = me.getRange(),
+            min = range.min,
+            max = range.max,
+            outfrom, outto, out;
+
+        out = Ext.draw.Draw.snapEnds(min, max, me.majorTickSteps !== false ?  (me.majorTickSteps +1) : me.steps);
+        outfrom = out.from;
+        outto = out.to;
+        if (me.forceMinMax) {
+            if (!isNaN(max)) {
+                out.to = max;
+            }
+            if (!isNaN(min)) {
+                out.from = min;
+            }
+        }
+        if (!isNaN(me.maximum)) {
+            
+            
+            out.to = me.maximum;
+        }
+        if (!isNaN(me.minimum)) {
+            
+            
+            out.from = me.minimum;
+        }
+
+        
+        out.step = (out.to - out.from) / (outto - outfrom) * out.step;
+
+        if (me.adjustMaximumByMajorUnit) {
+            out.to += out.step;
+        }
+        if (me.adjustMinimumByMajorUnit) {
+            out.from -= out.step;
+        }
+        me.prevMin = min == max? 0 : min;
+        me.prevMax = max;
+        return out;
+    },
+
+    
+    drawAxis: function (init) {
+        var me = this,
+            i, j,
+            x = me.x,
+            y = me.y,
+            gutterX = me.chart.maxGutter[0],
+            gutterY = me.chart.maxGutter[1],
+            dashSize = me.dashSize,
+            subDashesX = me.minorTickSteps || 0,
+            subDashesY = me.minorTickSteps || 0,
+            length = me.length,
+            position = me.position,
+            inflections = [],
+            calcLabels = false,
+            stepCalcs = me.applyData(),
+            step = stepCalcs.step,
+            steps = stepCalcs.steps,
+            from = stepCalcs.from,
+            to = stepCalcs.to,
+            trueLength,
+            currentX,
+            currentY,
+            path,
+            prev,
+            dashesX,
+            dashesY,
+            delta;
+
+        
+        
+        
+        if (me.hidden || isNaN(step) || (from == to)) {
+            return;
+        }
+
+        me.from = stepCalcs.from;
+        me.to = stepCalcs.to;
+        if (position == 'left' || position == 'right') {
+            currentX = Math.floor(x) + 0.5;
+            path = ["M", currentX, y, "l", 0, -length];
+            trueLength = length - (gutterY * 2);
+        }
+        else {
+            currentY = Math.floor(y) + 0.5;
+            path = ["M", x, currentY, "l", length, 0];
+            trueLength = length - (gutterX * 2);
+        }
+
+        delta = trueLength / (steps || 1);
+        dashesX = Math.max(subDashesX +1, 0);
+        dashesY = Math.max(subDashesY +1, 0);
+        if (me.type == 'Numeric' || me.type == 'Time') {
+            calcLabels = true;
+            me.labels = [stepCalcs.from];
+        }
+        if (position == 'right' || position == 'left') {
+            currentY = y - gutterY;
+            currentX = x - ((position == 'left') * dashSize * 2);
+            while (currentY >= y - gutterY - trueLength) {
+                path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
+                if (currentY != y - gutterY) {
+                    for (i = 1; i < dashesY; i++) {
+                        path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
+                    }
+                }
+                inflections.push([ Math.floor(x), Math.floor(currentY) ]);
+                currentY -= delta;
+                if (calcLabels) {
+                    me.labels.push(me.labels[me.labels.length -1] + step);
+                }
+                if (delta === 0) {
+                    break;
+                }
+            }
+            if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
+                path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
+                for (i = 1; i < dashesY; i++) {
+                    path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
+                }
+                inflections.push([ Math.floor(x), Math.floor(currentY) ]);
+                if (calcLabels) {
+                    me.labels.push(me.labels[me.labels.length -1] + step);
+                }
+            }
+        } else {
+            currentX = x + gutterX;
+            currentY = y - ((position == 'top') * dashSize * 2);
+            while (currentX <= x + gutterX + trueLength) {
+                path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
+                if (currentX != x + gutterX) {
+                    for (i = 1; i < dashesX; i++) {
+                        path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
+                    }
+                }
+                inflections.push([ Math.floor(currentX), Math.floor(y) ]);
+                currentX += delta;
+                if (calcLabels) {
+                    me.labels.push(me.labels[me.labels.length -1] + step);
+                }
+                if (delta === 0) {
+                    break;
+                }
+            }
+            if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
+                path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
+                for (i = 1; i < dashesX; i++) {
+                    path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
+                }
+                inflections.push([ Math.floor(currentX), Math.floor(y) ]);
+                if (calcLabels) {
+                    me.labels.push(me.labels[me.labels.length -1] + step);
+                }
+            }
+        }
+        if (!me.axis) {
+            me.axis = me.chart.surface.add(Ext.apply({
+                type: 'path',
+                path: path
+            }, me.axisStyle));
+        }
+        me.axis.setAttributes({
+            path: path
+        }, true);
+        me.inflections = inflections;
+        if (!init && me.grid) {
+            me.drawGrid();
+        }
+        me.axisBBox = me.axis.getBBox();
+        me.drawLabel();
+    },
+
+    
+    drawGrid: function() {
+        var me = this,
+            surface = me.chart.surface,
+            grid = me.grid,
+            odd = grid.odd,
+            even = grid.even,
+            inflections = me.inflections,
+            ln = inflections.length - ((odd || even)? 0 : 1),
+            position = me.position,
+            gutter = me.chart.maxGutter,
+            width = me.width - 2,
+            vert = false,
+            point, prevPoint,
+            i = 1,
+            path = [], styles, lineWidth, dlineWidth,
+            oddPath = [], evenPath = [];
+
+        if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
+            (gutter[0] !== 0 && (position == 'top' || position == 'bottom'))) {
+            i = 0;
+            ln++;
+        }
+        for (; i < ln; i++) {
+            point = inflections[i];
+            prevPoint = inflections[i - 1];
+            if (odd || even) {
+                path = (i % 2)? oddPath : evenPath;
+                styles = ((i % 2)? odd : even) || {};
+                lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
+                dlineWidth = 2 * lineWidth;
+                if (position == 'left') {
+                    path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth,
+                              "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
+                              "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
+                              "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
+                }
+                else if (position == 'right') {
+                    path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth,
+                              "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
+                              "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
+                              "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
+                }
+                else if (position == 'top') {
+                    path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth,
+                              "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
+                              "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
+                              "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
+                }
+                else {
+                    path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth,
+                            "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
+                            "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
+                            "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
+                }
+            } else {
+                if (position == 'left') {
+                    path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
+                }
+                else if (position == 'right') {
+                    path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
+                }
+                else if (position == 'top') {
+                    path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
+                }
+                else {
+                    path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
+                }
+            }
+        }
+        if (odd || even) {
+            if (oddPath.length) {
+                if (!me.gridOdd && oddPath.length) {
+                    me.gridOdd = surface.add({
+                        type: 'path',
+                        path: oddPath
+                    });
+                }
+                me.gridOdd.setAttributes(Ext.apply({
+                    path: oddPath,
+                    hidden: false
+                }, odd || {}), true);
+            }
+            if (evenPath.length) {
+                if (!me.gridEven) {
+                    me.gridEven = surface.add({
+                        type: 'path',
+                        path: evenPath
+                    });
+                }
+                me.gridEven.setAttributes(Ext.apply({
+                    path: evenPath,
+                    hidden: false
+                }, even || {}), true);
+            }
+        }
+        else {
+            if (path.length) {
+                if (!me.gridLines) {
+                    me.gridLines = me.chart.surface.add({
+                        type: 'path',
+                        path: path,
+                        "stroke-width": me.lineWidth || 1,
+                        stroke: me.gridColor || '#ccc'
+                    });
+                }
+                me.gridLines.setAttributes({
+                    hidden: false,
+                    path: path
+                }, true);
+            }
+            else if (me.gridLines) {
+                me.gridLines.hide(true);
+            }
+        }
+    },
+
+    //@private
+
+    getOrCreateLabel: function(i, text) {
+        var me = this,
+            labelGroup = me.labelGroup,
+            textLabel = labelGroup.getAt(i),
+            surface = me.chart.surface;
+        if (textLabel) {
+            if (text != textLabel.attr.text) {
+                textLabel.setAttributes(Ext.apply({
+                    text: text
+                }, me.label), true);
+                textLabel._bbox = textLabel.getBBox();
+            }
+        }
+        else {
+            textLabel = surface.add(Ext.apply({
+                group: labelGroup,
+                type: 'text',
+                x: 0,
+                y: 0,
+                text: text
+            }, me.label));
+            surface.renderItem(textLabel);
+            textLabel._bbox = textLabel.getBBox();
+        }
+        
+        if (me.label.rotation) {
+            textLabel.setAttributes({
+                rotation: {
+                    degrees: 0
+                }
+            }, true);
+            textLabel._ubbox = textLabel.getBBox();
+            textLabel.setAttributes(me.label, true);
+        } else {
+            textLabel._ubbox = textLabel._bbox;
+        }
+        return textLabel;
+    },
+
+    rect2pointArray: function(sprite) {
+        var surface = this.chart.surface,
+            rect = surface.getBBox(sprite, true),
+            p1 = [rect.x, rect.y],
+            p1p = p1.slice(),
+            p2 = [rect.x + rect.width, rect.y],
+            p2p = p2.slice(),
+            p3 = [rect.x + rect.width, rect.y + rect.height],
+            p3p = p3.slice(),
+            p4 = [rect.x, rect.y + rect.height],
+            p4p = p4.slice(),
+            matrix = sprite.matrix;
+        
+        p1[0] = matrix.x.apply(matrix, p1p);
+        p1[1] = matrix.y.apply(matrix, p1p);
+
+        p2[0] = matrix.x.apply(matrix, p2p);
+        p2[1] = matrix.y.apply(matrix, p2p);
+
+        p3[0] = matrix.x.apply(matrix, p3p);
+        p3[1] = matrix.y.apply(matrix, p3p);
+
+        p4[0] = matrix.x.apply(matrix, p4p);
+        p4[1] = matrix.y.apply(matrix, p4p);
+        return [p1, p2, p3, p4];
+    },
+
+    intersect: function(l1, l2) {
+        var r1 = this.rect2pointArray(l1),
+            r2 = this.rect2pointArray(l2);
+        return !!Ext.draw.Draw.intersect(r1, r2).length;
+    },
+
+    drawHorizontalLabels: function() {
+       var  me = this,
+            labelConf = me.label,
+            floor = Math.floor,
+            max = Math.max,
+            axes = me.chart.axes,
+            position = me.position,
+            inflections = me.inflections,
+            ln = inflections.length,
+            labels = me.labels,
+            labelGroup = me.labelGroup,
+            maxHeight = 0,
+            ratio,
+            gutterY = me.chart.maxGutter[1],
+            ubbox, bbox, point, prevX, prevLabel,
+            projectedWidth = 0,
+            textLabel, attr, textRight, text,
+            label, last, x, y, i, firstLabel;
+
+        last = ln - 1;
+        
+        point = inflections[0];
+        firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
+        ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));
+
+        for (i = 0; i < ln; i++) {
+            point = inflections[i];
+            text = me.label.renderer(labels[i]);
+            textLabel = me.getOrCreateLabel(i, text);
+            bbox = textLabel._bbox;
+            maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
+            x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
+            if (me.chart.maxGutter[0] == 0) {
+                if (i == 0 && axes.findIndex('position', 'left') == -1) {
+                    x = point[0];
+                }
+                else if (i == last && axes.findIndex('position', 'right') == -1) {
+                    x = point[0] - bbox.width;
+                }
+            }
+            if (position == 'top') {
+                y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
+            }
+            else {
+                y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
+            }
+
+            textLabel.setAttributes({
+                hidden: false,
+                x: x,
+                y: y
+            }, true);
+
+            
+            if (i != 0 && (me.intersect(textLabel, prevLabel)
+                || me.intersect(textLabel, firstLabel))) {
+                textLabel.hide(true);
+                continue;
+            }
+
+            prevLabel = textLabel;
+        }
+
+        return maxHeight;
+    },
+
+    drawVerticalLabels: function() {
+        var me = this,
+            inflections = me.inflections,
+            position = me.position,
+            ln = inflections.length,
+            labels = me.labels,
+            maxWidth = 0,
+            max = Math.max,
+            floor = Math.floor,
+            ceil = Math.ceil,
+            axes = me.chart.axes,
+            gutterY = me.chart.maxGutter[1],
+            ubbox, bbox, point, prevLabel,
+            projectedWidth = 0,
+            textLabel, attr, textRight, text,
+            label, last, x, y, i;
+
+        last = ln;
+        for (i = 0; i < last; i++) {
+            point = inflections[i];
+            text = me.label.renderer(labels[i]);
+            textLabel = me.getOrCreateLabel(i, text);
+            bbox = textLabel._bbox;
+
+            maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding);
+            y = point[1];
+            if (gutterY < bbox.height / 2) {
+                if (i == last - 1 && axes.findIndex('position', 'top') == -1) {
+                    y = me.y - me.length + ceil(bbox.height / 2);
+                }
+                else if (i == 0 && axes.findIndex('position', 'bottom') == -1) {
+                    y = me.y - floor(bbox.height / 2);
+                }
+            }
+            if (position == 'left') {
+                x = point[0] - bbox.width - me.dashSize - me.label.padding - 2;
+            }
+            else {
+                x = point[0] + me.dashSize + me.label.padding + 2;
+            }
+            textLabel.setAttributes(Ext.apply({
+                hidden: false,
+                x: x,
+                y: y
+            }, me.label), true);
+            
+            if (i != 0 && me.intersect(textLabel, prevLabel)) {
+                textLabel.hide(true);
+                continue;
+            }
+            prevLabel = textLabel;
+        }
+
+        return maxWidth;
+    },
+
+    
+    drawLabel: function() {
+        var me = this,
+            position = me.position,
+            labelGroup = me.labelGroup,
+            inflections = me.inflections,
+            maxWidth = 0,
+            maxHeight = 0,
+            ln, i;
+
+        if (position == 'left' || position == 'right') {
+            maxWidth = me.drawVerticalLabels();
+        } else {
+            maxHeight = me.drawHorizontalLabels();
+        }
+
+        
+        ln = labelGroup.getCount();
+        i = inflections.length;
+        for (; i < ln; i++) {
+            labelGroup.getAt(i).hide(true);
+        }
+
+        me.bbox = {};
+        Ext.apply(me.bbox, me.axisBBox);
+        me.bbox.height = maxHeight;
+        me.bbox.width = maxWidth;
+        if (Ext.isString(me.title)) {
+            me.drawTitle(maxWidth, maxHeight);
+        }
+    },
+
+    
+    elipsis: function(sprite, text, desiredWidth, minWidth, center) {
+        var bbox,
+            x;
+
+        if (desiredWidth < minWidth) {
+            sprite.hide(true);
+            return false;
+        }
+        while (text.length > 4) {
+            text = text.substr(0, text.length - 4) + "...";
+            sprite.setAttributes({
+                text: text
+            }, true);
+            bbox = sprite.getBBox();
+            if (bbox.width < desiredWidth) {
+                if (typeof center == 'number') {
+                    sprite.setAttributes({
+                        x: Math.floor(center - (bbox.width / 2))
+                    }, true);
+                }
+                break;
+            }
+        }
+        return true;
+    },
+
+    
+    setTitle: function(title) {
+        this.title = title;
+        this.drawLabel();
+    },
+
+    
+    drawTitle: function(maxWidth, maxHeight) {
+        var me = this,
+            position = me.position,
+            surface = me.chart.surface,
+            displaySprite = me.displaySprite,
+            title = me.title,
+            rotate = (position == 'left' || position == 'right'),
+            x = me.x,
+            y = me.y,
+            base, bbox, pad;
+
+        if (displaySprite) {
+            displaySprite.setAttributes({text: title}, true);
+        } else {
+            base = {
+                type: 'text',
+                x: 0,
+                y: 0,
+                text: title
+            };
+            displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle));
+            surface.renderItem(displaySprite);
+        }
+        bbox = displaySprite.getBBox();
+        pad = me.dashSize + me.label.padding;
+
+        if (rotate) {
+            y -= ((me.length / 2) - (bbox.height / 2));
+            if (position == 'left') {
+                x -= (maxWidth + pad + (bbox.width / 2));
+            }
+            else {
+                x += (maxWidth + pad + bbox.width - (bbox.width / 2));
+            }
+            me.bbox.width += bbox.width + 10;
+        }
+        else {
+            x += (me.length / 2) - (bbox.width * 0.5);
+            if (position == 'top') {
+                y -= (maxHeight + pad + (bbox.height * 0.3));
+            }
+            else {
+                y += (maxHeight + pad + (bbox.height * 0.8));
+            }
+            me.bbox.height += bbox.height + 10;
+        }
+        displaySprite.setAttributes({
+            translate: {
+                x: x,
+                y: y
+            }
+        }, true);
+    }
+});
+
+
+Ext.define('Ext.chart.axis.Category', {
+
+    
+
+    extend: 'Ext.chart.axis.Axis',
+
+    alternateClassName: 'Ext.chart.CategoryAxis',
+
+    alias: 'axis.category',
+
+    
+
+    
+    categoryNames: null,
+
+    
+    calculateCategoryCount: false,
+
+    
+    setLabels: function() {
+        var store = this.chart.store,
+            fields = this.fields,
+            ln = fields.length,
+            i;
+
+        this.labels = [];
+        store.each(function(record) {
+            for (i = 0; i < ln; i++) {
+                this.labels.push(record.get(fields[i]));
+            }
+        }, this);
+    },
+
+    
+    applyData: function() {
+        this.callParent();
+        this.setLabels();
+        var count = this.chart.store.getCount();
+        return {
+            from: 0,
+            to: count,
+            power: 1,
+            step: 1,
+            steps: count - 1
+        };
+    }
+});
+
+
+Ext.define('Ext.chart.axis.Gauge', {
+
+    
+
+    extend: 'Ext.chart.axis.Abstract',
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    position: 'gauge',
+
+    alias: 'axis.gauge',
+
+    drawAxis: function(init) {
+        var chart = this.chart,
+            surface = chart.surface,
+            bbox = chart.chartBBox,
+            centerX = bbox.x + (bbox.width / 2),
+            centerY = bbox.y + bbox.height,
+            margin = this.margin || 10,
+            rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
+            sprites = [], sprite,
+            steps = this.steps,
+            i, pi = Math.PI,
+            cos = Math.cos,
+            sin = Math.sin;
+
+        if (this.sprites && !chart.resizing) {
+            this.drawLabel();
+            return;
+        }
+
+        if (this.margin >= 0) {
+            if (!this.sprites) {
+                
+                for (i = 0; i <= steps; i++) {
+                    sprite = surface.add({
+                        type: 'path',
+                        path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+                                    centerY + (rho - margin) * sin(i / steps * pi - pi),
+                                    'L', centerX + rho * cos(i / steps * pi - pi),
+                                    centerY + rho * sin(i / steps * pi - pi), 'Z'],
+                        stroke: '#ccc'
+                    });
+                    sprite.setAttributes({
+                        hidden: false
+                    }, true);
+                    sprites.push(sprite);
+                }
+            } else {
+                sprites = this.sprites;
+                
+                for (i = 0; i <= steps; i++) {
+                    sprites[i].setAttributes({
+                        path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+                                    centerY + (rho - margin) * sin(i / steps * pi - pi),
+                               'L', centerX + rho * cos(i / steps * pi - pi),
+                                    centerY + rho * sin(i / steps * pi - pi), 'Z'],
+                        stroke: '#ccc'
+                    }, true);
+                }
+            }
+        }
+        this.sprites = sprites;
+        this.drawLabel();
+        if (this.title) {
+            this.drawTitle();
+        }
+    },
+
+    drawTitle: function() {
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            bbox = chart.chartBBox,
+            labelSprite = me.titleSprite,
+            labelBBox;
+
+        if (!labelSprite) {
+            me.titleSprite = labelSprite = surface.add({
+                type: 'text',
+                zIndex: 2
+            });
+        }
+        labelSprite.setAttributes(Ext.apply({
+            text: me.title
+        }, me.label || {}), true);
+        labelBBox = labelSprite.getBBox();
+        labelSprite.setAttributes({
+            x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
+            y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
+        }, true);
+    },
+
+    
+    setTitle: function(title) {
+        this.title = title;
+        this.drawTitle();
+    },
+
+    drawLabel: function() {
+        var chart = this.chart,
+            surface = chart.surface,
+            bbox = chart.chartBBox,
+            centerX = bbox.x + (bbox.width / 2),
+            centerY = bbox.y + bbox.height,
+            margin = this.margin || 10,
+            rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
+            round = Math.round,
+            labelArray = [], label,
+            maxValue = this.maximum || 0,
+            steps = this.steps, i = 0,
+            adjY,
+            pi = Math.PI,
+            cos = Math.cos,
+            sin = Math.sin,
+            labelConf = this.label,
+            renderer = labelConf.renderer || function(v) { return v; };
+
+        if (!this.labelArray) {
+            
+            for (i = 0; i <= steps; i++) {
+                
+                adjY = (i === 0 || i === steps) ? 7 : 0;
+                label = surface.add({
+                    type: 'text',
+                    text: renderer(round(i / steps * maxValue)),
+                    x: centerX + rho * cos(i / steps * pi - pi),
+                    y: centerY + rho * sin(i / steps * pi - pi) - adjY,
+                    'text-anchor': 'middle',
+                    'stroke-width': 0.2,
+                    zIndex: 10,
+                    stroke: '#333'
+                });
+                label.setAttributes({
+                    hidden: false
+                }, true);
+                labelArray.push(label);
+            }
+        }
+        else {
+            labelArray = this.labelArray;
+            
+            for (i = 0; i <= steps; i++) {
+                
+                adjY = (i === 0 || i === steps) ? 7 : 0;
+                labelArray[i].setAttributes({
+                    text: renderer(round(i / steps * maxValue)),
+                    x: centerX + rho * cos(i / steps * pi - pi),
+                    y: centerY + rho * sin(i / steps * pi - pi) - adjY
+                }, true);
+            }
+        }
+        this.labelArray = labelArray;
+    }
+});
+
+Ext.define('Ext.chart.axis.Numeric', {
+
+    
+
+    extend: 'Ext.chart.axis.Axis',
+
+    alternateClassName: 'Ext.chart.NumericAxis',
+
+    
+
+    type: 'numeric',
+
+    alias: 'axis.numeric',
+
+    constructor: function(config) {
+        var me = this,
+            hasLabel = !!(config.label && config.label.renderer),
+            label;
+
+        me.callParent([config]);
+        label = me.label;
+        if (me.roundToDecimal === false) {
+            return;
+        }
+        if (!hasLabel) {
+            label.renderer = function(v) {
+                return me.roundToDecimal(v, me.decimals);
+            };
+        }
+    },
+
+    roundToDecimal: function(v, dec) {
+        var val = Math.pow(10, dec || 0);
+        return Math.floor(v * val) / val;
+    },
+
+    
+    minimum: NaN,
+
+    
+    maximum: NaN,
+
+    
+    decimals: 2,
+
+    
+    scale: "linear",
+
+    
+    position: 'left',
+
+    
+    adjustMaximumByMajorUnit: false,
+
+    
+    adjustMinimumByMajorUnit: false,
+
+    
+    applyData: function() {
+        this.callParent();
+        return this.calcEnds();
+    }
+});
+
+
+Ext.define('Ext.chart.axis.Radial', {
+
+    
+
+    extend: 'Ext.chart.axis.Abstract',
+
+    
+
+    position: 'radial',
+
+    alias: 'axis.radial',
+
+    drawAxis: function(init) {
+        var chart = this.chart,
+            surface = chart.surface,
+            bbox = chart.chartBBox,
+            store = chart.store,
+            l = store.getCount(),
+            centerX = bbox.x + (bbox.width / 2),
+            centerY = bbox.y + (bbox.height / 2),
+            rho = Math.min(bbox.width, bbox.height) /2,
+            sprites = [], sprite,
+            steps = this.steps,
+            i, j, pi2 = Math.PI * 2,
+            cos = Math.cos, sin = Math.sin;
+
+        if (this.sprites && !chart.resizing) {
+            this.drawLabel();
+            return;
+        }
+
+        if (!this.sprites) {
+            
+            for (i = 1; i <= steps; i++) {
+                sprite = surface.add({
+                    type: 'circle',
+                    x: centerX,
+                    y: centerY,
+                    radius: Math.max(rho * i / steps, 0),
+                    stroke: '#ccc'
+                });
+                sprite.setAttributes({
+                    hidden: false
+                }, true);
+                sprites.push(sprite);
+            }
+            
+            store.each(function(rec, i) {
+                sprite = surface.add({
+                    type: 'path',
+                    path: ['M', centerX, centerY, 'L', centerX + rho * cos(i / l * pi2), centerY + rho * sin(i / l * pi2), 'Z'],
+                    stroke: '#ccc'
+                });
+                sprite.setAttributes({
+                    hidden: false
+                }, true);
+                sprites.push(sprite);
+            });
+        } else {
+            sprites = this.sprites;
+            
+            for (i = 0; i < steps; i++) {
+                sprites[i].setAttributes({
+                    x: centerX,
+                    y: centerY,
+                    radius: Math.max(rho * (i + 1) / steps, 0),
+                    stroke: '#ccc'
+                }, true);
+            }
+            
+            store.each(function(rec, j) {
+                sprites[i + j].setAttributes({
+                    path: ['M', centerX, centerY, 'L', centerX + rho * cos(j / l * pi2), centerY + rho * sin(j / l * pi2), 'Z'],
+                    stroke: '#ccc'
+                }, true);
+            });
+        }
+        this.sprites = sprites;
+
+        this.drawLabel();
+    },
+
+    drawLabel: function() {
+        var chart = this.chart,
+            surface = chart.surface,
+            bbox = chart.chartBBox,
+            store = chart.store,
+            centerX = bbox.x + (bbox.width / 2),
+            centerY = bbox.y + (bbox.height / 2),
+            rho = Math.min(bbox.width, bbox.height) /2,
+            max = Math.max, round = Math.round,
+            labelArray = [], label,
+            fields = [], nfields,
+            categories = [], xField,
+            aggregate = !this.maximum,
+            maxValue = this.maximum || 0,
+            steps = this.steps, i = 0, j, dx, dy,
+            pi2 = Math.PI * 2,
+            cos = Math.cos, sin = Math.sin,
+            display = this.label.display,
+            draw = display !== 'none',
+            margin = 10;
+
+        if (!draw) {
+            return;
+        }
+
+        
+        chart.series.each(function(series) {
+            fields.push(series.yField);
+            xField = series.xField;
+        });
+        
+        
+        store.each(function(record, i) {
+            if (aggregate) {
+                for (i = 0, nfields = fields.length; i < nfields; i++) {
+                    maxValue = max(+record.get(fields[i]), maxValue);
+                }
+            }
+            categories.push(record.get(xField));
+        });
+        if (!this.labelArray) {
+            if (display != 'categories') {
+                
+                for (i = 1; i <= steps; i++) {
+                    label = surface.add({
+                        type: 'text',
+                        text: round(i / steps * maxValue),
+                        x: centerX,
+                        y: centerY - rho * i / steps,
+                        'text-anchor': 'middle',
+                        'stroke-width': 0.1,
+                        stroke: '#333'
+                    });
+                    label.setAttributes({
+                        hidden: false
+                    }, true);
+                    labelArray.push(label);
+                }
+            }
+            if (display != 'scale') {
+                
+                for (j = 0, steps = categories.length; j < steps; j++) {
+                    dx = cos(j / steps * pi2) * (rho + margin);
+                    dy = sin(j / steps * pi2) * (rho + margin);
+                    label = surface.add({
+                        type: 'text',
+                        text: categories[j],
+                        x: centerX + dx,
+                        y: centerY + dy,
+                        'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
+                    });
+                    label.setAttributes({
+                        hidden: false
+                    }, true);
+                    labelArray.push(label);
+                }
+            }
+        }
+        else {
+            labelArray = this.labelArray;
+            if (display != 'categories') {
+                
+                for (i = 0; i < steps; i++) {
+                    labelArray[i].setAttributes({
+                        text: round((i + 1) / steps * maxValue),
+                        x: centerX,
+                        y: centerY - rho * (i + 1) / steps,
+                        'text-anchor': 'middle',
+                        'stroke-width': 0.1,
+                        stroke: '#333'
+                    }, true);
+                }
+            }
+            if (display != 'scale') {
+                
+                for (j = 0, steps = categories.length; j < steps; j++) {
+                    dx = cos(j / steps * pi2) * (rho + margin);
+                    dy = sin(j / steps * pi2) * (rho + margin);
+                    if (labelArray[i + j]) {
+                        labelArray[i + j].setAttributes({
+                            type: 'text',
+                            text: categories[j],
+                            x: centerX + dx,
+                            y: centerY + dy,
+                            'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
+                        }, true);
+                    }
+                }
+            }
+        }
+        this.labelArray = labelArray;
+    }
+});
+
+Ext.define('Ext.data.AbstractStore', {
+    requires: ['Ext.util.MixedCollection', 'Ext.data.Operation', 'Ext.util.Filter'],
+    
+    mixins: {
+        observable: 'Ext.util.Observable',
+        sortable: 'Ext.util.Sortable'
+    },
+    
+    statics: {
+        create: function(store){
+            if (!store.isStore) {
+                if (!store.type) {
+                    store.type = 'store';
+                }
+                store = Ext.createByAlias('store.' + store.type, store);
+            }
+            return store;
+        }    
+    },
+    
+    remoteSort  : false,
+    remoteFilter: false,
+
+    
+
+    
+    autoLoad: false,
+
+    
+    autoSync: false,
+
+    
+    batchUpdateMode: 'operation',
+
+    
+    filterOnLoad: true,
+
+    
+    sortOnLoad: true,
+
+    
+    implicitModel: false,
+
+    
+    defaultProxyType: 'memory',
+
+    
+    isDestroyed: false,
+
+    isStore: true,
+
+    
+    
+    
+
+    
+
+    sortRoot: 'data',
+    
+    
+    constructor: function(config) {
+        var me = this,
+            filters;
+        
+        me.addEvents(
+            
+            'add',
+
+            
+            'remove',
+            
+            
+            'update',
+
+            
+            'datachanged',
+
+            
+            'beforeload',
+
+            
+            'load',
+            
+            
+            'write',
+
+            
+            'beforesync',
+            
+            'clear'
+        );
+        
+        Ext.apply(me, config);
+        
+
+        
+        me.removed = [];
+
+        me.mixins.observable.constructor.apply(me, arguments);
+        me.model = Ext.ModelManager.getModel(me.model);
+
+        
+        Ext.applyIf(me, {
+            modelDefaults: {}
+        });
+
+        
+        if (!me.model && me.fields) {
+            me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
+                extend: 'Ext.data.Model',
+                fields: me.fields,
+                proxy: me.proxy || me.defaultProxyType
+            });
+
+            delete me.fields;
+
+            me.implicitModel = true;
+        }
+        
+
+        
+        me.setProxy(me.proxy || me.model.getProxy());
+
+        if (me.id && !me.storeId) {
+            me.storeId = me.id;
+            delete me.id;
+        }
+
+        if (me.storeId) {
+            Ext.data.StoreManager.register(me);
+        }
+        
+        me.mixins.sortable.initSortable.call(me);        
+        
+        
+        filters = me.decodeFilters(me.filters);
+        me.filters = Ext.create('Ext.util.MixedCollection');
+        me.filters.addAll(filters);
+    },
+
+    
+    setProxy: function(proxy) {
+        var me = this;
+        
+        if (proxy instanceof Ext.data.proxy.Proxy) {
+            proxy.setModel(me.model);
+        } else {
+            if (Ext.isString(proxy)) {
+                proxy = {
+                    type: proxy    
+                };
+            }
+            Ext.applyIf(proxy, {
+                model: me.model
+            });
+            
+            proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
+        }
+        
+        me.proxy = proxy;
+        
+        return me.proxy;
+    },
+
+    
+    getProxy: function() {
+        return this.proxy;
+    },
+
+    
+    create: function(data, options) {
+        var me = this,
+            instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName),
+            operation;
+        
+        options = options || {};
+
+        Ext.applyIf(options, {
+            action : 'create',
+            records: [instance]
+        });
+
+        operation = Ext.create('Ext.data.Operation', options);
+
+        me.proxy.create(operation, me.onProxyWrite, me);
+        
+        return instance;
+    },
+
+    read: function() {
+        return this.load.apply(this, arguments);
+    },
+
+    onProxyRead: Ext.emptyFn,
+
+    update: function(options) {
+        var me = this,
+            operation;
+        options = options || {};
+
+        Ext.applyIf(options, {
+            action : 'update',
+            records: me.getUpdatedRecords()
+        });
+
+        operation = Ext.create('Ext.data.Operation', options);
+
+        return me.proxy.update(operation, me.onProxyWrite, me);
+    },
+
+    
+    onProxyWrite: function(operation) {
+        var me = this,
+            success = operation.wasSuccessful(),
+            records = operation.getRecords();
+
+        switch (operation.action) {
+            case 'create':
+                me.onCreateRecords(records, operation, success);
+                break;
+            case 'update':
+                me.onUpdateRecords(records, operation, success);
+                break;
+            case 'destroy':
+                me.onDestroyRecords(records, operation, success);
+                break;
+        }
+
+        if (success) {
+            me.fireEvent('write', me, operation);
+            me.fireEvent('datachanged', me);
+        }
+        
+        Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
+    },
+
+
+    
+    destroy: function(options) {
+        var me = this,
+            operation;
+            
+        options = options || {};
+
+        Ext.applyIf(options, {
+            action : 'destroy',
+            records: me.getRemovedRecords()
+        });
+
+        operation = Ext.create('Ext.data.Operation', options);
+
+        return me.proxy.destroy(operation, me.onProxyWrite, me);
+    },
+
+    
+    onBatchOperationComplete: function(batch, operation) {
+        return this.onProxyWrite(operation);
+    },
+
+    
+    onBatchComplete: function(batch, operation) {
+        var me = this,
+            operations = batch.operations,
+            length = operations.length,
+            i;
+
+        me.suspendEvents();
+
+        for (i = 0; i < length; i++) {
+            me.onProxyWrite(operations[i]);
+        }
+
+        me.resumeEvents();
+
+        me.fireEvent('datachanged', me);
+    },
+
+    onBatchException: function(batch, operation) {
+        
+        
+        
+        
+        
+    },
+
+    
+    filterNew: function(item) {
+        
+        return item.phantom === true && item.isValid();
+    },
+
+    
+    getNewRecords: function() {
+        return [];
+    },
+
+    
+    getUpdatedRecords: function() {
+        return [];
+    },
+
+    
+    filterUpdated: function(item) {
+        
+        return item.dirty === true && item.phantom !== true && item.isValid();
+    },
+
+    
+    getRemovedRecords: function() {
+        return this.removed;
+    },
+
+    filter: function(filters, value) {
+
+    },
+
+    
+    decodeFilters: function(filters) {
+        if (!Ext.isArray(filters)) {
+            if (filters === undefined) {
+                filters = [];
+            } else {
+                filters = [filters];
+            }
+        }
+
+        var length = filters.length,
+            Filter = Ext.util.Filter,
+            config, i;
+
+        for (i = 0; i < length; i++) {
+            config = filters[i];
+
+            if (!(config instanceof Filter)) {
+                Ext.apply(config, {
+                    root: 'data'
+                });
+
+                
+                if (config.fn) {
+                    config.filterFn = config.fn;
+                }
+
+                
+                if (typeof config == 'function') {
+                    config = {
+                        filterFn: config
+                    };
+                }
+
+                filters[i] = new Filter(config);
+            }
+        }
+
+        return filters;
+    },
+
+    clearFilter: function(supressEvent) {
+
+    },
+
+    isFiltered: function() {
+
+    },
+
+    filterBy: function(fn, scope) {
+
+    },
+    
+    
+    sync: function() {
+        var me        = this,
+            options   = {},
+            toCreate  = me.getNewRecords(),
+            toUpdate  = me.getUpdatedRecords(),
+            toDestroy = me.getRemovedRecords(),
+            needsSync = false;
+
+        if (toCreate.length > 0) {
+            options.create = toCreate;
+            needsSync = true;
+        }
+
+        if (toUpdate.length > 0) {
+            options.update = toUpdate;
+            needsSync = true;
+        }
+
+        if (toDestroy.length > 0) {
+            options.destroy = toDestroy;
+            needsSync = true;
+        }
+
+        if (needsSync && me.fireEvent('beforesync', options) !== false) {
+            me.proxy.batch(options, me.getBatchListeners());
+        }
+    },
+
+
+    
+    getBatchListeners: function() {
+        var me = this,
+            listeners = {
+                scope: me,
+                exception: me.onBatchException
+            };
+
+        if (me.batchUpdateMode == 'operation') {
+            listeners.operationcomplete = me.onBatchOperationComplete;
+        } else {
+            listeners.complete = me.onBatchComplete;
+        }
+
+        return listeners;
+    },
+
+    
+    save: function() {
+        return this.sync.apply(this, arguments);
+    },
+
+    
+    load: function(options) {
+        var me = this,
+            operation;
+
+        options = options || {};
+
+        Ext.applyIf(options, {
+            action : 'read',
+            filters: me.filters.items,
+            sorters: me.getSorters()
+        });
+        
+        operation = Ext.create('Ext.data.Operation', options);
+
+        if (me.fireEvent('beforeload', me, operation) !== false) {
+            me.loading = true;
+            me.proxy.read(operation, me.onProxyLoad, me);
+        }
+        
+        return me;
+    },
+
+    
+    afterEdit : function(record) {
+        var me = this;
+        
+        if (me.autoSync) {
+            me.sync();
+        }
+        
+        me.fireEvent('update', me, record, Ext.data.Model.EDIT);
+    },
+
+    
+    afterReject : function(record) {
+        this.fireEvent('update', this, record, Ext.data.Model.REJECT);
+    },
+
+    
+    afterCommit : function(record) {
+        this.fireEvent('update', this, record, Ext.data.Model.COMMIT);
+    },
+
+    clearData: Ext.emptyFn,
+
+    destroyStore: function() {
+        var me = this;
+        
+        if (!me.isDestroyed) {
+            if (me.storeId) {
+                Ext.data.StoreManager.unregister(me);
+            }
+            me.clearData();
+            me.data = null;
+            me.tree = null;
+            
+            me.reader = me.writer = null;
+            me.clearListeners();
+            me.isDestroyed = true;
+
+            if (me.implicitModel) {
+                Ext.destroy(me.model);
+            }
+        }
+    },
+    
+    doSort: function(sorterFn) {
+        var me = this;
+        if (me.remoteSort) {
+            
+            me.load();
+        } else {
+            me.data.sortBy(sorterFn);
+            me.fireEvent('datachanged', me);
+        }
+    },
+
+    getCount: Ext.emptyFn,
+
+    getById: Ext.emptyFn,
+    
+    
+    removeAll: Ext.emptyFn,
+    
+    
+
+    
+    isLoading: function() {
+        return !!this.loading;
+     }
+});
+
+
+Ext.define('Ext.util.Grouper', {
+
+    
+
+    extend: 'Ext.util.Sorter',
+
+    
+
+    
+    getGroupString: function(instance) {
+        return instance.get(this.property);
+    }
+});
+
+Ext.define('Ext.data.Store', {
+    extend: 'Ext.data.AbstractStore',
+
+    alias: 'store.store',
+
+    requires: ['Ext.data.StoreManager', 'Ext.ModelManager', 'Ext.data.Model', 'Ext.util.Grouper'],
+    uses: ['Ext.data.proxy.Memory'],
+
+    
+    remoteSort: false,
+
+    
+    remoteFilter: false,
+
+    
+    remoteGroup : false,
+
+    
+
+    
+
+    
+    groupField: undefined,
+
+    
+    groupDir: "ASC",
+
+    
+    pageSize: 25,
+
+    
+    currentPage: 1,
+
+    
+    clearOnPageLoad: true,
+
+    
+    loading: false,
+
+    
+    sortOnFilter: true,
+
+    
+    buffered: false,
+
+    
+    purgePageCount: 5,
+
+    isStore: true,
+
+    onClassExtended: function(cls, data) {
+        var model = data.model;
+
+        if (typeof model == 'string') {
+            var onBeforeClassCreated = data.onBeforeClassCreated;
+
+            data.onBeforeClassCreated = function(cls, data) {
+                var me = this;
+
+                Ext.require(model, function() {
+                    onBeforeClassCreated.call(me, cls, data);
+                });
+            };
+        }
+    },
+
+    
+    constructor: function(config) {
+        
+        config = Ext.Object.merge({}, config);
+
+        var me = this,
+            groupers = config.groupers || me.groupers,
+            groupField = config.groupField || me.groupField,
+            proxy,
+            data;
+
+        if (config.buffered || me.buffered) {
+            me.prefetchData = Ext.create('Ext.util.MixedCollection', false, function(record) {
+                return record.index;
+            });
+            me.pendingRequests = [];
+            me.pagesRequested = [];
+
+            me.sortOnLoad = false;
+            me.filterOnLoad = false;
+        }
+
+        me.addEvents(
+            
+            'beforeprefetch',
+            
+            'groupchange',
+            
+            'prefetch'
+        );
+        data = config.data || me.data;
+
+        
+        me.data = Ext.create('Ext.util.MixedCollection', false, function(record) {
+            return record.internalId;
+        });
+
+        if (data) {
+            me.inlineData = data;
+            delete config.data;
+        }
+
+        if (!groupers && groupField) {
+            groupers = [{
+                property : groupField,
+                direction: config.groupDir || me.groupDir
+            }];
+        }
+        delete config.groupers;
+
+        
+        me.groupers = Ext.create('Ext.util.MixedCollection');
+        me.groupers.addAll(me.decodeGroupers(groupers));
+
+        this.callParent([config]);
+        
+
+        if (me.groupers.items.length) {
+            me.sort(me.groupers.items, 'prepend', false);
+        }
+
+        proxy = me.proxy;
+        data = me.inlineData;
+
+        if (data) {
+            if (proxy instanceof Ext.data.proxy.Memory) {
+                proxy.data = data;
+                me.read();
+            } else {
+                me.add.apply(me, data);
+            }
+
+            me.sort();
+            delete me.inlineData;
+        } else if (me.autoLoad) {
+            Ext.defer(me.load, 10, me, [typeof me.autoLoad === 'object' ? me.autoLoad: undefined]);
+            
+            
+        }
+    },
+
+    onBeforeSort: function() {
+        var groupers = this.groupers;
+        if (groupers.getCount() > 0) {
+            this.sort(groupers.items, 'prepend', false);
+        }
+    },
+
+    
+    decodeGroupers: function(groupers) {
+        if (!Ext.isArray(groupers)) {
+            if (groupers === undefined) {
+                groupers = [];
+            } else {
+                groupers = [groupers];
+            }
+        }
+
+        var length  = groupers.length,
+            Grouper = Ext.util.Grouper,
+            config, i;
+
+        for (i = 0; i < length; i++) {
+            config = groupers[i];
+
+            if (!(config instanceof Grouper)) {
+                if (Ext.isString(config)) {
+                    config = {
+                        property: config
+                    };
+                }
+
+                Ext.applyIf(config, {
+                    root     : 'data',
+                    direction: "ASC"
+                });
 
+                
+                if (config.fn) {
+                    config.sorterFn = config.fn;
+                }
 
-Ext.apply(Ext.EventObjectImpl.prototype, {
-   
-   BACKSPACE: 8,
-   
-   TAB: 9,
-   
-   NUM_CENTER: 12,
-   
-   ENTER: 13,
-   
-   RETURN: 13,
-   
-   SHIFT: 16,
-   
-   CTRL: 17,
-   CONTROL : 17, 
-   
-   ALT: 18,
-   
-   PAUSE: 19,
-   
-   CAPS_LOCK: 20,
-   
-   ESC: 27,
-   
-   SPACE: 32,
-   
-   PAGE_UP: 33,
-   PAGEUP : 33, 
-   
-   PAGE_DOWN: 34,
-   PAGEDOWN : 34, 
-   
-   END: 35,
-   
-   HOME: 36,
-   
-   LEFT: 37,
-   
-   UP: 38,
-   
-   RIGHT: 39,
-   
-   DOWN: 40,
-   
-   PRINT_SCREEN: 44,
-   
-   INSERT: 45,
-   
-   DELETE: 46,
-   
-   ZERO: 48,
-   
-   ONE: 49,
-   
-   TWO: 50,
-   
-   THREE: 51,
-   
-   FOUR: 52,
-   
-   FIVE: 53,
-   
-   SIX: 54,
-   
-   SEVEN: 55,
-   
-   EIGHT: 56,
-   
-   NINE: 57,
-   
-   A: 65,
-   
-   B: 66,
-   
-   C: 67,
-   
-   D: 68,
-   
-   E: 69,
-   
-   F: 70,
-   
-   G: 71,
-   
-   H: 72,
-   
-   I: 73,
-   
-   J: 74,
-   
-   K: 75,
-   
-   L: 76,
-   
-   M: 77,
-   
-   N: 78,
-   
-   O: 79,
-   
-   P: 80,
-   
-   Q: 81,
-   
-   R: 82,
-   
-   S: 83,
-   
-   T: 84,
-   
-   U: 85,
-   
-   V: 86,
-   
-   W: 87,
-   
-   X: 88,
-   
-   Y: 89,
-   
-   Z: 90,
-   
-   CONTEXT_MENU: 93,
-   
-   NUM_ZERO: 96,
-   
-   NUM_ONE: 97,
-   
-   NUM_TWO: 98,
-   
-   NUM_THREE: 99,
-   
-   NUM_FOUR: 100,
-   
-   NUM_FIVE: 101,
-   
-   NUM_SIX: 102,
-   
-   NUM_SEVEN: 103,
-   
-   NUM_EIGHT: 104,
-   
-   NUM_NINE: 105,
-   
-   NUM_MULTIPLY: 106,
-   
-   NUM_PLUS: 107,
-   
-   NUM_MINUS: 109,
-   
-   NUM_PERIOD: 110,
-   
-   NUM_DIVISION: 111,
-   
-   F1: 112,
-   
-   F2: 113,
-   
-   F3: 114,
-   
-   F4: 115,
-   
-   F5: 116,
-   
-   F6: 117,
-   
-   F7: 118,
-   
-   F8: 119,
-   
-   F9: 120,
-   
-   F10: 121,
-   
-   F11: 122,
-   
-   F12: 123,
+                
+                if (typeof config == 'function') {
+                    config = {
+                        sorterFn: config
+                    };
+                }
 
-   
-   isNavKeyPress : function(){
-       var me = this,
-           k = this.normalizeKey(me.keyCode);
-       return (k >= 33 && k <= 40) ||  
-       k == me.RETURN ||
-       k == me.TAB ||
-       k == me.ESC;
-   },
+                groupers[i] = new Grouper(config);
+            }
+        }
 
-   isSpecialKey : function(){
-       var k = this.normalizeKey(this.keyCode);
-       return (this.type == 'keypress' && this.ctrlKey) ||
-       this.isNavKeyPress() ||
-       (k == this.BACKSPACE) || 
-       (k >= 16 && k <= 20) || 
-       (k >= 44 && k <= 46);   
-   },
+        return groupers;
+    },
 
-   getPoint : function(){
-       return new Ext.lib.Point(this.xy[0], this.xy[1]);
-   },
+    
+    group: function(groupers, direction) {
+        var me = this,
+            hasNew = false,
+            grouper,
+            newGroupers;
+
+        if (Ext.isArray(groupers)) {
+            newGroupers = groupers;
+        } else if (Ext.isObject(groupers)) {
+            newGroupers = [groupers];
+        } else if (Ext.isString(groupers)) {
+            grouper = me.groupers.get(groupers);
+
+            if (!grouper) {
+                grouper = {
+                    property : groupers,
+                    direction: direction
+                };
+                newGroupers = [grouper];
+            } else if (direction === undefined) {
+                grouper.toggle();
+            } else {
+                grouper.setDirection(direction);
+            }
+        }
 
-   
-   hasModifier : function(){
-       return ((this.ctrlKey || this.altKey) || this.shiftKey);
-   }
-});
-(function(){
-var DOC = document;
+        if (newGroupers && newGroupers.length) {
+            hasNew = true;
+            newGroupers = me.decodeGroupers(newGroupers);
+            me.groupers.clear();
+            me.groupers.addAll(newGroupers);
+        }
 
-Ext.Element = function(element, forceNew){
-    var dom = typeof element == "string" ?
-              DOC.getElementById(element) : element,
-        id;
+        if (me.remoteGroup) {
+            me.load({
+                scope: me,
+                callback: me.fireGroupChange
+            });
+        } else {
+            
+            me.sort(null, null, null, hasNew);
+            me.fireGroupChange();
+        }
+    },
+
+    
+    clearGrouping: function(){
+        var me = this;
+        
+        me.groupers.each(function(grouper){
+            me.sorters.remove(grouper);
+        });
+        me.groupers.clear();
+        if (me.remoteGroup) {
+            me.load({
+                scope: me,
+                callback: me.fireGroupChange
+            });
+        } else {
+            me.sort();
+            me.fireEvent('groupchange', me, me.groupers);
+        }
+    },
 
-    if(!dom) return null;
+    
+    isGrouped: function() {
+        return this.groupers.getCount() > 0;
+    },
 
-    id = dom.id;
+    
+    fireGroupChange: function(){
+        this.fireEvent('groupchange', this, this.groupers);
+    },
 
-    if(!forceNew && id && Ext.elCache[id]){ 
-        return Ext.elCache[id].el;
-    }
+    
+    getGroups: function(requestGroupString) {
+        var records = this.data.items,
+            length = records.length,
+            groups = [],
+            pointers = {},
+            record,
+            groupStr,
+            group,
+            i;
+
+        for (i = 0; i < length; i++) {
+            record = records[i];
+            groupStr = this.getGroupString(record);
+            group = pointers[groupStr];
+
+            if (group === undefined) {
+                group = {
+                    name: groupStr,
+                    children: []
+                };
+
+                groups.push(group);
+                pointers[groupStr] = group;
+            }
+
+            group.children.push(record);
+        }
+
+        return requestGroupString ? pointers[requestGroupString] : groups;
+    },
 
     
-    this.dom = dom;
+    getGroupsForGrouper: function(records, grouper) {
+        var length = records.length,
+            groups = [],
+            oldValue,
+            newValue,
+            record,
+            group,
+            i;
+
+        for (i = 0; i < length; i++) {
+            record = records[i];
+            newValue = grouper.getGroupString(record);
+
+            if (newValue !== oldValue) {
+                group = {
+                    name: newValue,
+                    grouper: grouper,
+                    records: []
+                };
+                groups.push(group);
+            }
+
+            group.records.push(record);
+
+            oldValue = newValue;
+        }
+
+        return groups;
+    },
 
     
-    this.id = id || Ext.id(dom);
-};
+    getGroupsForGrouperIndex: function(records, grouperIndex) {
+        var me = this,
+            groupers = me.groupers,
+            grouper = groupers.getAt(grouperIndex),
+            groups = me.getGroupsForGrouper(records, grouper),
+            length = groups.length,
+            i;
+
+        if (grouperIndex + 1 < groupers.length) {
+            for (i = 0; i < length; i++) {
+                groups[i].children = me.getGroupsForGrouperIndex(groups[i].records, grouperIndex + 1);
+            }
+        }
+
+        for (i = 0; i < length; i++) {
+            groups[i].depth = grouperIndex;
+        }
 
-var DH = Ext.DomHelper,
-    El = Ext.Element,
-    EC = Ext.elCache;
+        return groups;
+    },
 
-El.prototype = {
     
-    set : function(o, useSet){
-        var el = this.dom,
-            attr,
-            val,
-            useSet = (useSet !== false) && !!el.setAttribute;
+    getGroupData: function(sort) {
+        var me = this;
+        if (sort !== false) {
+            me.sort();
+        }
 
-        for (attr in o) {
-            if (o.hasOwnProperty(attr)) {
-                val = o[attr];
-                if (attr == 'style') {
-                    DH.applyStyles(el, val);
-                } else if (attr == 'cls') {
-                    el.className = val;
-                } else if (useSet) {
-                    el.setAttribute(attr, val);
-                } else {
-                    el[attr] = val;
+        return me.getGroupsForGrouperIndex(me.data.items, 0);
+    },
+
+    
+    getGroupString: function(instance) {
+        var group = this.groupers.first();
+        if (group) {
+            return instance.get(group.property);
+        }
+        return '';
+    },
+    
+    insert: function(index, records) {
+        var me = this,
+            sync = false,
+            i,
+            record,
+            len;
+
+        records = [].concat(records);
+        for (i = 0, len = records.length; i < len; i++) {
+            record = me.createModel(records[i]);
+            record.set(me.modelDefaults);
+            
+            records[i] = record;
+
+            me.data.insert(index + i, record);
+            record.join(me);
+
+            sync = sync || record.phantom === true;
+        }
+
+        if (me.snapshot) {
+            me.snapshot.addAll(records);
+        }
+
+        me.fireEvent('add', me, records, index);
+        me.fireEvent('datachanged', me);
+        if (me.autoSync && sync) {
+            me.sync();
+        }
+    },
+
+    
+    add: function(records) {
+        
+        if (!Ext.isArray(records)) {
+            records = Array.prototype.slice.apply(arguments);
+        }
+
+        var me = this,
+            i = 0,
+            length = records.length,
+            record;
+
+        for (; i < length; i++) {
+            record = me.createModel(records[i]);
+            
+            records[i] = record;
+        }
+
+        me.insert(me.data.length, records);
+
+        return records;
+    },
+
+    
+    createModel: function(record) {
+        if (!record.isModel) {
+            record = Ext.ModelManager.create(record, this.model);
+        }
+
+        return record;
+    },
+
+    
+    each: function(fn, scope) {
+        this.data.each(fn, scope);
+    },
+
+    
+    remove: function(records,  isMove) {
+        if (!Ext.isArray(records)) {
+            records = [records];
+        }
+
+        
+        isMove = isMove === true;
+        var me = this,
+            sync = false,
+            i = 0,
+            length = records.length,
+            isPhantom,
+            index,
+            record;
+
+        for (; i < length; i++) {
+            record = records[i];
+            index = me.data.indexOf(record);
+
+            if (me.snapshot) {
+                me.snapshot.remove(record);
+            }
+
+            if (index > -1) {
+                isPhantom = record.phantom === true;
+                if (!isMove && !isPhantom) {
+                    
+                    me.removed.push(record);
                 }
+
+                record.unjoin(me);
+                me.data.remove(record);
+                sync = sync || !isPhantom;
+
+                me.fireEvent('remove', me, record, index);
             }
         }
-        return this;
+
+        me.fireEvent('datachanged', me);
+        if (!isMove && me.autoSync && sync) {
+            me.sync();
+        }
+    },
+
+    
+    removeAt: function(index) {
+        var record = this.getAt(index);
+
+        if (record) {
+            this.remove(record);
+        }
+    },
+
+    
+    load: function(options) {
+        var me = this;
+
+        options = options || {};
+
+        if (Ext.isFunction(options)) {
+            options = {
+                callback: options
+            };
+        }
+
+        Ext.applyIf(options, {
+            groupers: me.groupers.items,
+            page: me.currentPage,
+            start: (me.currentPage - 1) * me.pageSize,
+            limit: me.pageSize,
+            addRecords: false
+        });
+
+        return me.callParent([options]);
+    },
+
+    
+    onProxyLoad: function(operation) {
+        var me = this,
+            resultSet = operation.getResultSet(),
+            records = operation.getRecords(),
+            successful = operation.wasSuccessful();
+
+        if (resultSet) {
+            me.totalCount = resultSet.total;
+        }
+
+        if (successful) {
+            me.loadRecords(records, operation);
+        }
+
+        me.loading = false;
+        me.fireEvent('load', me, records, successful);
+
+        
+        
+        me.fireEvent('read', me, records, operation.wasSuccessful());
+
+        
+        Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
+    },
+
+    
+    onCreateRecords: function(records, operation, success) {
+        if (success) {
+            var i = 0,
+                data = this.data,
+                snapshot = this.snapshot,
+                length = records.length,
+                originalRecords = operation.records,
+                record,
+                original,
+                index;
+
+            
+            for (; i < length; ++i) {
+                record = records[i];
+                original = originalRecords[i];
+                if (original) {
+                    index = data.indexOf(original);
+                    if (index > -1) {
+                        data.removeAt(index);
+                        data.insert(index, record);
+                    }
+                    if (snapshot) {
+                        index = snapshot.indexOf(original);
+                        if (index > -1) {
+                            snapshot.removeAt(index);
+                            snapshot.insert(index, record);
+                        }
+                    }
+                    record.phantom = false;
+                    record.join(this);
+                }
+            }
+        }
+    },
+
+    
+    onUpdateRecords: function(records, operation, success){
+        if (success) {
+            var i = 0,
+                length = records.length,
+                data = this.data,
+                snapshot = this.snapshot,
+                record;
+
+            for (; i < length; ++i) {
+                record = records[i];
+                data.replace(record);
+                if (snapshot) {
+                    snapshot.replace(record);
+                }
+                record.join(this);
+            }
+        }
+    },
+
+    
+    onDestroyRecords: function(records, operation, success){
+        if (success) {
+            var me = this,
+                i = 0,
+                length = records.length,
+                data = me.data,
+                snapshot = me.snapshot,
+                record;
+
+            for (; i < length; ++i) {
+                record = records[i];
+                record.unjoin(me);
+                data.remove(record);
+                if (snapshot) {
+                    snapshot.remove(record);
+                }
+            }
+            me.removed = [];
+        }
+    },
+
+    
+    getNewRecords: function() {
+        return this.data.filterBy(this.filterNew).items;
+    },
+
+    
+    getUpdatedRecords: function() {
+        return this.data.filterBy(this.filterUpdated).items;
+    },
+
+    
+    filter: function(filters, value) {
+        if (Ext.isString(filters)) {
+            filters = {
+                property: filters,
+                value: value
+            };
+        }
+
+        var me = this,
+            decoded = me.decodeFilters(filters),
+            i = 0,
+            doLocalSort = me.sortOnFilter && !me.remoteSort,
+            length = decoded.length;
+
+        for (; i < length; i++) {
+            me.filters.replace(decoded[i]);
+        }
+
+        if (me.remoteFilter) {
+            
+            me.load();
+        } else {
+            
+            if (me.filters.getCount()) {
+                me.snapshot = me.snapshot || me.data.clone();
+                me.data = me.data.filter(me.filters.items);
+
+                if (doLocalSort) {
+                    me.sort();
+                }
+                
+                if (!doLocalSort || me.sorters.length < 1) {
+                    me.fireEvent('datachanged', me);
+                }
+            }
+        }
+    },
+
+    
+    clearFilter: function(suppressEvent) {
+        var me = this;
+
+        me.filters.clear();
+
+        if (me.remoteFilter) {
+            me.load();
+        } else if (me.isFiltered()) {
+            me.data = me.snapshot.clone();
+            delete me.snapshot;
+
+            if (suppressEvent !== true) {
+                me.fireEvent('datachanged', me);
+            }
+        }
+    },
+
+    
+    isFiltered: function() {
+        var snapshot = this.snapshot;
+        return !! snapshot && snapshot !== this.data;
+    },
+
+    
+    filterBy: function(fn, scope) {
+        var me = this;
+
+        me.snapshot = me.snapshot || me.data.clone();
+        me.data = me.queryBy(fn, scope || me);
+        me.fireEvent('datachanged', me);
     },
 
+    
+    queryBy: function(fn, scope) {
+        var me = this,
+        data = me.snapshot || me.data;
+        return data.filterBy(fn, scope || me);
+    },
+
+    
+    loadData: function(data, append) {
+        var model = this.model,
+            length = data.length,
+            newData = [],
+            i,
+            record;
+
+        
+        for (i = 0; i < length; i++) {
+            record = data[i];
+
+            if (!(record instanceof Ext.data.Model)) {
+                record = Ext.ModelManager.create(record, model);
+            }
+            newData.push(record);
+        }
+
+        this.loadRecords(newData, {addRecords: append});
+    },
+
+
+    
+    loadRawData : function(data, append) {
+         var me      = this,
+             result  = me.proxy.reader.read(data),
+             records = result.records;
+
+         if (result.success) {
+             me.loadRecords(records, { addRecords: append });
+             me.fireEvent('load', me, records, true);
+         }
+     },
+
+
+    
+    loadRecords: function(records, options) {
+        var me     = this,
+            i      = 0,
+            length = records.length;
+
+        options = options || {};
+
+
+        if (!options.addRecords) {
+            delete me.snapshot;
+            me.clearData();
+        }
+
+        me.data.addAll(records);
+
+        
+        for (; i < length; i++) {
+            if (options.start !== undefined) {
+                records[i].index = options.start + i;
+
+            }
+            records[i].join(me);
+        }
+
+        
+        me.suspendEvents();
+
+        if (me.filterOnLoad && !me.remoteFilter) {
+            me.filter();
+        }
+
+        if (me.sortOnLoad && !me.remoteSort) {
+            me.sort();
+        }
+
+        me.resumeEvents();
+        me.fireEvent('datachanged', me, records);
+    },
 
     
     
+    loadPage: function(page, options) {
+        var me = this;
+        options = Ext.apply({}, options);
+
+        me.currentPage = page;
+
+        me.read(Ext.applyIf(options, {
+            page: page,
+            start: (page - 1) * me.pageSize,
+            limit: me.pageSize,
+            addRecords: !me.clearOnPageLoad
+        }));
+    },
+
     
+    nextPage: function(options) {
+        this.loadPage(this.currentPage + 1, options);
+    },
+
     
+    previousPage: function(options) {
+        this.loadPage(this.currentPage - 1, options);
+    },
+
     
+    clearData: function() {
+        var me = this;
+        me.data.each(function(record) {
+            record.unjoin(me);
+        });
+
+        me.data.clear();
+    },
+
     
     
+    prefetch: function(options) {
+        var me = this,
+            operation,
+            requestId = me.getRequestId();
+
+        options = options || {};
+
+        Ext.applyIf(options, {
+            action : 'read',
+            filters: me.filters.items,
+            sorters: me.sorters.items,
+            requestId: requestId
+        });
+        me.pendingRequests.push(requestId);
+
+        operation = Ext.create('Ext.data.Operation', options);
+
+        
+        
+        
+        
+        if (me.fireEvent('beforeprefetch', me, operation) !== false) {
+            me.loading = true;
+            me.proxy.read(operation, me.onProxyPrefetch, me);
+        }
+
+        return me;
+    },
+
     
+    prefetchPage: function(page, options) {
+        var me = this,
+            pageSize = me.pageSize,
+            start = (page - 1) * me.pageSize,
+            end = start + pageSize;
+
+        
+        if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
+            options = options || {};
+            me.pagesRequested.push(page);
+            Ext.applyIf(options, {
+                page : page,
+                start: start,
+                limit: pageSize,
+                callback: me.onWaitForGuarantee,
+                scope: me
+            });
+
+            me.prefetch(options);
+        }
+
+    },
+
     
+    getRequestId: function() {
+        this.requestSeed = this.requestSeed || 1;
+        return this.requestSeed++;
+    },
+
     
+    onProxyPrefetch: function(operation) {
+        var me         = this,
+            resultSet  = operation.getResultSet(),
+            records    = operation.getRecords(),
+
+            successful = operation.wasSuccessful();
+
+        if (resultSet) {
+            me.totalCount = resultSet.total;
+            me.fireEvent('totalcountchange', me.totalCount);
+        }
+
+        if (successful) {
+            me.cacheRecords(records, operation);
+        }
+        Ext.Array.remove(me.pendingRequests, operation.requestId);
+        if (operation.page) {
+            Ext.Array.remove(me.pagesRequested, operation.page);
+        }
+
+        me.loading = false;
+        me.fireEvent('prefetch', me, records, successful, operation);
+
+        
+        if (operation.blocking) {
+            me.fireEvent('load', me, records, successful);
+        }
 
+        
+        Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
+    },
 
     
+    cacheRecords: function(records, operation) {
+        var me     = this,
+            i      = 0,
+            length = records.length,
+            start  = operation ? operation.start : 0;
+
+        if (!Ext.isDefined(me.totalCount)) {
+            me.totalCount = records.length;
+            me.fireEvent('totalcountchange', me.totalCount);
+        }
+
+        for (; i < length; i++) {
+            
+            records[i].index = start + i;
+        }
+
+        me.prefetchData.addAll(records);
+        if (me.purgePageCount) {
+            me.purgeRecords();
+        }
+
+    },
+
+
     
+    purgeRecords: function() {
+        var me = this,
+            prefetchCount = me.prefetchData.getCount(),
+            purgeCount = me.purgePageCount * me.pageSize,
+            numRecordsToPurge = prefetchCount - purgeCount - 1,
+            i = 0;
+
+        for (; i <= numRecordsToPurge; i++) {
+            me.prefetchData.removeAt(0);
+        }
+    },
+
     
+    rangeSatisfied: function(start, end) {
+        var me = this,
+            i = start,
+            satisfied = true;
 
+        for (; i < end; i++) {
+            if (!me.prefetchData.getByKey(i)) {
+                satisfied = false;
+                break;
+            }
+        }
+        return satisfied;
+    },
 
+    
+    getPageFromRecordIndex: function(index) {
+        return Math.floor(index / this.pageSize) + 1;
+    },
 
     
+    onGuaranteedRange: function() {
+        var me = this,
+            totalCount = me.getTotalCount(),
+            start = me.requestStart,
+            end = ((totalCount - 1) < me.requestEnd) ? totalCount - 1 : me.requestEnd,
+            range = [],
+            record,
+            i = start;
+
+        end = Math.max(0, end);
+
+
+        if (start !== me.guaranteedStart && end !== me.guaranteedEnd) {
+            me.guaranteedStart = start;
+            me.guaranteedEnd = end;
+
+            for (; i <= end; i++) {
+                record = me.prefetchData.getByKey(i);
+                if (record) {
+                    range.push(record);
+                }
+            }
+            me.fireEvent('guaranteedrange', range, start, end);
+            if (me.cb) {
+                me.cb.call(me.scope || me, range);
+            }
+        }
+
+        me.unmask();
+    },
+
     
+    mask: function() {
+        this.masked = true;
+        this.fireEvent('beforeload');
+    },
+
     
+    unmask: function() {
+        if (this.masked) {
+            this.fireEvent('load');
+        }
+    },
+
     
+    hasPendingRequests: function() {
+        return this.pendingRequests.length;
+    },
+
+
     
+    onWaitForGuarantee: function() {
+        if (!this.hasPendingRequests()) {
+            this.onGuaranteedRange();
+        }
+    },
+
     
+    guaranteeRange: function(start, end, cb, scope) {
+
+        end = (end > this.totalCount) ? this.totalCount - 1 : end;
+
+        var me = this,
+            i = start,
+            prefetchData = me.prefetchData,
+            range = [],
+            startLoaded = !!prefetchData.getByKey(start),
+            endLoaded = !!prefetchData.getByKey(end),
+            startPage = me.getPageFromRecordIndex(start),
+            endPage = me.getPageFromRecordIndex(end);
+
+        me.cb = cb;
+        me.scope = scope;
 
+        me.requestStart = start;
+        me.requestEnd = end;
+        
+        if (!startLoaded || !endLoaded) {
+            
+            if (startPage === endPage) {
+                me.mask();
+                me.prefetchPage(startPage, {
+                    
+                    callback: me.onWaitForGuarantee,
+                    scope: me
+                });
+            
+            } else {
+                me.mask();
+                me.prefetchPage(startPage, {
+                    
+                    callback: me.onWaitForGuarantee,
+                    scope: me
+                });
+                me.prefetchPage(endPage, {
+                    
+                    callback: me.onWaitForGuarantee,
+                    scope: me
+                });
+            }
+        
+        } else {
+            me.onGuaranteedRange();
+        }
+    },
 
     
     
+    sort: function() {
+        var me = this,
+            prefetchData = me.prefetchData,
+            sorters,
+            start,
+            end,
+            range;
+
+        if (me.buffered) {
+            if (me.remoteSort) {
+                prefetchData.clear();
+                me.callParent(arguments);
+            } else {
+                sorters = me.getSorters();
+                start = me.guaranteedStart;
+                end = me.guaranteedEnd;
+
+                if (sorters.length) {
+                    prefetchData.sort(sorters);
+                    range = prefetchData.getRange();
+                    prefetchData.clear();
+                    me.cacheRecords(range);
+                    delete me.guaranteedStart;
+                    delete me.guaranteedEnd;
+                    me.guaranteeRange(start, end);
+                }
+                me.callParent(arguments);
+            }
+        } else {
+            me.callParent(arguments);
+        }
+    },
+
+    
     
     
+    doSort: function(sorterFn) {
+        var me = this;
+        if (me.remoteSort) {
+            
+            me.load();
+        } else {
+            me.data.sortBy(sorterFn);
+            if (!me.buffered) {
+                var range = me.getRange(),
+                    ln = range.length,
+                    i  = 0;
+                for (; i < ln; i++) {
+                    range[i].index = i;
+                }
+            }
+            me.fireEvent('datachanged', me);
+        }
+    },
+
     
+    find: function(property, value, start, anyMatch, caseSensitive, exactMatch) {
+        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
+        return fn ? this.data.findIndexBy(fn, null, start) : -1;
+    },
+
     
+    findRecord: function() {
+        var me = this,
+            index = me.find.apply(me, arguments);
+        return index !== -1 ? me.getAt(index) : null;
+    },
 
+    
+    createFilterFn: function(property, value, anyMatch, caseSensitive, exactMatch) {
+        if (Ext.isEmpty(value)) {
+            return false;
+        }
+        value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
+        return function(r) {
+            return value.test(r.data[property]);
+        };
+    },
 
     
+    findExact: function(property, value, start) {
+        return this.data.findIndexBy(function(rec) {
+            return rec.get(property) == value;
+        },
+        this, start);
+    },
+
     
+    findBy: function(fn, scope, start) {
+        return this.data.findIndexBy(fn, scope, start);
+    },
+
     
+    collect: function(dataIndex, allowNull, bypassFilter) {
+        var me = this,
+            data = (bypassFilter === true && me.snapshot) ? me.snapshot: me.data;
 
+        return data.collect(dataIndex, 'data', allowNull);
+    },
 
     
+    getCount: function() {
+        return this.data.length || 0;
+    },
+
     
+    getTotalCount: function() {
+        return this.totalCount;
+    },
+
     
-    
-    
-    
-    
+    getAt: function(index) {
+        return this.data.getAt(index);
+    },
 
     
-    defaultUnit : "px",
+    getRange: function(start, end) {
+        return this.data.getRange(start, end);
+    },
 
     
-    is : function(simpleSelector){
-        return Ext.DomQuery.is(this.dom, simpleSelector);
+    getById: function(id) {
+        return (this.snapshot || this.data).findBy(function(record) {
+            return record.getId() === id;
+        });
     },
 
     
-    focus : function(defer,  dom) {
-        var me = this,
-            dom = dom || me.dom;
-        try{
-            if(Number(defer)){
-                me.focus.defer(defer, null, [null, dom]);
-            }else{
-                dom.focus();
-            }
-        }catch(e){}
-        return me;
+    indexOf: function(record) {
+        return this.data.indexOf(record);
     },
 
+
     
-    blur : function() {
-        try{
-            this.dom.blur();
-        }catch(e){}
-        return this;
+    indexOfTotal: function(record) {
+        var index = record.index;
+        if (index || index === 0) {
+            return index;
+        }
+        return this.indexOf(record);
     },
 
     
-    getValue : function(asNumber){
-        var val = this.dom.value;
-        return asNumber ? parseInt(val, 10) : val;
+    indexOfId: function(id) {
+        return this.indexOf(this.getById(id));
     },
 
     
-    addListener : function(eventName, fn, scope, options){
-        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
-        return this;
+    removeAll: function(silent) {
+        var me = this;
+
+        me.clearData();
+        if (me.snapshot) {
+            me.snapshot.clear();
+        }
+        if (silent !== true) {
+            me.fireEvent('clear', me);
+        }
     },
 
     
-    removeListener : function(eventName, fn, scope){
-        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
-        return this;
+
+    
+    first: function(grouped) {
+        var me = this;
+
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(function(records) {
+                return records.length ? records[0] : undefined;
+            }, me, true);
+        } else {
+            return me.data.first();
+        }
     },
 
     
-    removeAllListeners : function(){
-        Ext.EventManager.removeAll(this.dom);
-        return this;
+    last: function(grouped) {
+        var me = this;
+
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(function(records) {
+                var len = records.length;
+                return len ? records[len - 1] : undefined;
+            }, me, true);
+        } else {
+            return me.data.last();
+        }
     },
 
     
-    purgeAllListeners : function() {
-        Ext.EventManager.purgeElement(this, true);
-        return this;
+    sum: function(field, grouped) {
+        var me = this;
+
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(me.getSum, me, true, [field]);
+        } else {
+            return me.getSum(me.data.items, field);
+        }
     },
+
     
-    addUnits : function(size){
-        if(size === "" || size == "auto" || size === undefined){
-            size = size || '';
-        } else if(!isNaN(size) || !unitPattern.test(size)){
-            size = size + (this.defaultUnit || 'px');
+    getSum: function(records, field) {
+        var total = 0,
+            i = 0,
+            len = records.length;
+
+        for (; i < len; ++i) {
+            total += records[i].get(field);
         }
-        return size;
+
+        return total;
     },
 
     
-    load : function(url, params, cb){
-        Ext.Ajax.request(Ext.apply({
-            params: params,
-            url: url.url || url,
-            callback: cb,
-            el: this.dom,
-            indicatorText: url.indicatorText || ''
-        }, Ext.isObject(url) ? url : {}));
-        return this;
+    count: function(grouped) {
+        var me = this;
+
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(function(records) {
+                return records.length;
+            }, me, true);
+        } else {
+            return me.getCount();
+        }
     },
 
     
-    isBorderBox : function(){
-        return noBoxAdjust[(this.dom.tagName || "").toLowerCase()] || Ext.isBorderBox;
+    min: function(field, grouped) {
+        var me = this;
+
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(me.getMin, me, true, [field]);
+        } else {
+            return me.getMin(me.data.items, field);
+        }
     },
 
     
-    remove : function(){
-        var me = this,
-            dom = me.dom;
+    getMin: function(records, field){
+        var i = 1,
+            len = records.length,
+            value, min;
+
+        if (len > 0) {
+            min = records[0].get(field);
+        }
 
-        if (dom) {
-            delete me.dom;
-            Ext.removeNode(dom);
+        for (; i < len; ++i) {
+            value = records[i].get(field);
+            if (value < min) {
+                min = value;
+            }
         }
+        return min;
     },
 
     
-    hover : function(overFn, outFn, scope, options){
+    max: function(field, grouped) {
         var me = this;
-        me.on('mouseenter', overFn, scope || me.dom, options);
-        me.on('mouseleave', outFn, scope || me.dom, options);
-        return me;
+
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(me.getMax, me, true, [field]);
+        } else {
+            return me.getMax(me.data.items, field);
+        }
     },
 
     
-    contains : function(el){
-        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
+    getMax: function(records, field) {
+        var i = 1,
+            len = records.length,
+            value,
+            max;
+
+        if (len > 0) {
+            max = records[0].get(field);
+        }
+
+        for (; i < len; ++i) {
+            value = records[i].get(field);
+            if (value > max) {
+                max = value;
+            }
+        }
+        return max;
     },
 
     
-    getAttributeNS : function(ns, name){
-        return this.getAttribute(name, ns);
+    average: function(field, grouped) {
+        var me = this;
+        if (grouped && me.isGrouped()) {
+            return me.aggregate(me.getAverage, me, true, [field]);
+        } else {
+            return me.getAverage(me.data.items, field);
+        }
     },
 
     
-    getAttribute : Ext.isIE ? function(name, ns){
-        var d = this.dom,
-            type = typeof d[ns + ":" + name];
+    getAverage: function(records, field) {
+        var i = 0,
+            len = records.length,
+            sum = 0;
 
-        if(['undefined', 'unknown'].indexOf(type) == -1){
-            return d[ns + ":" + name];
+        if (records.length > 0) {
+            for (; i < len; ++i) {
+                sum += records[i].get(field);
+            }
+            return sum / len;
         }
-        return d[name];
-    } : function(name, ns){
-        var d = this.dom;
-        return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
+        return 0;
     },
 
     
-    update : function(html) {
-        if (this.dom) {
-            this.dom.innerHTML = html;
+    aggregate: function(fn, scope, grouped, args) {
+        args = args || [];
+        if (grouped && this.isGrouped()) {
+            var groups = this.getGroups(),
+                i = 0,
+                len = groups.length,
+                out = {},
+                group;
+
+            for (; i < len; ++i) {
+                group = groups[i];
+                out[group.name] = fn.apply(scope || this, [group.children].concat(args));
+            }
+            return out;
+        } else {
+            return fn.apply(scope || this, [this.data.items].concat(args));
         }
-        return this;
     }
-};
+}, function() {
+    
+    
+    
+    Ext.regStore('ext-empty-store', {fields: [], proxy: 'proxy'});
+});
 
-var ep = El.prototype;
 
-El.addMethods = function(o){
-   Ext.apply(ep, o);
-};
+Ext.define('Ext.data.JsonStore',  {
+    extend: 'Ext.data.Store',
+    alias: 'store.json',
+
+    
+    constructor: function(config) {
+        config = config || {};
 
+        Ext.applyIf(config, {
+            proxy: {
+                type  : 'ajax',
+                reader: 'json',
+                writer: 'json'
+            }
+        });
 
-ep.on = ep.addListener;
+        this.callParent([config]);
+    }
+});
 
 
-ep.un = ep.removeListener;
+Ext.define('Ext.chart.axis.Time', {
 
+    
 
-ep.autoBoxAdjust = true;
+    extend: 'Ext.chart.axis.Numeric',
 
+    alternateClassName: 'Ext.chart.TimeAxis',
 
-var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
-    docEl;
+    alias: 'axis.time',
 
+    requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
 
+    
 
+    
+    dateFormat: false,
 
-El.get = function(el){
-    var ex,
-        elm,
-        id;
-    if(!el){ return null; }
-    if (typeof el == "string") { 
-        if (!(elm = DOC.getElementById(el))) {
-            return null;
+    
+    fromDate: false,
+
+    
+    toDate: false,
+
+    
+    step: [Ext.Date.DAY, 1],
+    
+    
+    constrain: false,
+
+    
+    roundToDecimal: false,
+    
+    constructor: function (config) {
+        var me = this, label, f, df;
+        me.callParent([config]);
+        label = me.label || {};
+        df = this.dateFormat;
+        if (df) {
+            if (label.renderer) {
+                f = label.renderer;
+                label.renderer = function(v) {
+                    v = f(v);
+                    return Ext.Date.format(new Date(f(v)), df);
+                };
+            } else {
+                label.renderer = function(v) {
+                    return Ext.Date.format(new Date(v >> 0), df);
+                };
+            }
         }
-        if (EC[el] && EC[el].el) {
-            ex = EC[el].el;
-            ex.dom = elm;
-        } else {
-            ex = El.addToCache(new El(elm));
+    },
+
+    doConstrain: function () {
+        var me = this,
+            store = me.chart.store,
+            data = [],
+            series = me.chart.series.items,
+            math = Math,
+            mmax = math.max,
+            mmin = math.min,
+            fields = me.fields,
+            ln = fields.length,
+            range = me.getRange(),
+            min = range.min, max = range.max, i, l, excludes = [],
+            value, values, rec, data = [];
+        for (i = 0, l = series.length; i < l; i++) {
+            excludes[i] = series[i].__excludes;
+        }
+        store.each(function(record) {
+            for (i = 0; i < ln; i++) {
+                if (excludes[i]) {
+                    continue;
+                }
+                value = record.get(fields[i]);
+                if (+value < +min) return;
+                if (+value > +max) return;
+            }
+            data.push(record);
+        })
+        me.chart.substore = Ext.create('Ext.data.JsonStore', { model: store.model, data: data });
+    },
+
+    
+    processView: function () {
+        var me = this;
+        if (me.fromDate) {
+            me.minimum = +me.fromDate;
         }
-        return ex;
-    } else if (el.tagName) { 
-        if(!(id = el.id)){
-            id = Ext.id(el);
+        if (me.toDate) {
+            me.maximum = +me.toDate;
         }
-        if (EC[id] && EC[id].el) {
-            ex = EC[id].el;
-            ex.dom = el;
-        } else {
-            ex = El.addToCache(new El(el));
+        if (me.constrain) {
+            me.doConstrain();
         }
-        return ex;
-    } else if (el instanceof El) {
-        if(el != docEl){
-            
-            
+     },
 
-            
-            if (Ext.isIE && (el.id == undefined || el.id == '')) {
-                el.dom = el.dom;
-            } else {
-                el.dom = DOC.getElementById(el.id) || el.dom;
+    
+    calcEnds: function() {
+        var me = this, range, step = me.step;
+        if (step) {
+            range = me.getRange();
+            range = Ext.draw.Draw.snapEndsByDateAndStep(new Date(range.min), new Date(range.max), Ext.isNumber(step) ? [Date.MILLI, step]: step);
+            if (me.minimum) {
+                range.from = me.minimum;
             }
+            if (me.maximum) {
+                range.to = me.maximum;
+            }
+            range.step = (range.to - range.from) / range.steps;
+            return range;
+        } else {
+            return me.callParent(arguments);
         }
-        return el;
-    } else if(el.isComposite) {
-        return el;
-    } else if(Ext.isArray(el)) {
-        return El.select(el);
-    } else if(el == DOC) {
-        
-        if(!docEl){
-            var f = function(){};
-            f.prototype = El.prototype;
-            docEl = new f();
-            docEl.dom = DOC;
-        }
-        return docEl;
     }
-    return null;
-};
+ });
 
-El.addToCache = function(el, id){
-    id = id || el.id;
-    EC[id] = {
-        el:  el,
-        data: {},
-        events: {}
-    };
-    return el;
-};
 
 
-El.data = function(el, key, value){
-    el = El.get(el);
-    if (!el) {
-        return null;
-    }
-    var c = EC[el.id].data;
-    if(arguments.length == 2){
-        return c[key];
-    }else{
-        return (c[key] = value);
-    }
-};
+Ext.define('Ext.chart.series.Series', {
 
+    
 
+    mixins: {
+        observable: 'Ext.util.Observable',
+        labels: 'Ext.chart.Label',
+        highlights: 'Ext.chart.Highlight',
+        tips: 'Ext.chart.Tip',
+        callouts: 'Ext.chart.Callout'
+    },
 
+    
 
-function garbageCollect(){
-    if(!Ext.enableGarbageCollector){
-        clearInterval(El.collectorThreadId);
-    } else {
-        var eid,
-            el,
-            d,
-            o;
+    
 
-        for(eid in EC){
-            o = EC[eid];
-            if(o.skipGC){
-                continue;
-            }
-            el = o.el;
-            d = el.dom;
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            
-            if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
-                if(Ext.enableListenerCollection){
-                    Ext.EventManager.removeAll(d);
-                }
-                delete EC[eid];
-            }
-        }
-        
-        if (Ext.isIE) {
-            var t = {};
-            for (eid in EC) {
-                t[eid] = EC[eid];
-            }
-            EC = Ext.elCache = t;
-        }
-    }
-}
-El.collectorThreadId = setInterval(garbageCollect, 30000);
+    
+
+    
+    type: null,
 
-var flyFn = function(){};
-flyFn.prototype = El.prototype;
+    
+    title: null,
 
+    
+    showInLegend: true,
 
-El.Flyweight = function(dom){
-    this.dom = dom;
-};
+    
+    renderer: function(sprite, record, attributes, index, store) {
+        return attributes;
+    },
 
-El.Flyweight.prototype = new flyFn();
-El.Flyweight.prototype.isFlyweight = true;
-El._flyweights = {};
+    
+    shadowAttributes: null,
 
+    //@private triggerdrawlistener flag
 
-El.fly = function(el, named){
-    var ret = null;
-    named = named || '_global';
+    triggerAfterDraw: false,
 
-    if (el = Ext.getDom(el)) {
-        (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
-        ret = El._flyweights[named];
-    }
-    return ret;
-};
+    
 
+    constructor: function(config) {
+        var me = this;
+        if (config) {
+            Ext.apply(me, config);
+        }
 
-Ext.get = El.get;
+        me.shadowGroups = [];
 
+        me.mixins.labels.constructor.call(me, config);
+        me.mixins.highlights.constructor.call(me, config);
+        me.mixins.tips.constructor.call(me, config);
+        me.mixins.callouts.constructor.call(me, config);
 
-Ext.fly = El.fly;
+        me.addEvents({
+            scope: me,
+            itemmouseover: true,
+            itemmouseout: true,
+            itemmousedown: true,
+            itemmouseup: true,
+            mouseleave: true,
+            afterdraw: true,
 
+            
+            titlechange: true
+        });
 
-var noBoxAdjust = Ext.isStrict ? {
-    select:1
-} : {
-    input:1, select:1, textarea:1
-};
-if(Ext.isIE || Ext.isGecko){
-    noBoxAdjust['button'] = 1;
-}
+        me.mixins.observable.constructor.call(me, config);
 
-})();
+        me.on({
+            scope: me,
+            itemmouseover: me.onItemMouseOver,
+            itemmouseout: me.onItemMouseOut,
+            mouseleave: me.onMouseLeave
+        });
+    },
+    
+    
+    eachRecord: function(fn, scope) {
+        var chart = this.chart;
+        (chart.substore || chart.store).each(fn, scope);
+    },
 
-Ext.Element.addMethods({
     
-    swallowEvent : function(eventName, preventDefault){
-        var me = this;
-        function fn(e){
-            e.stopPropagation();
-            if(preventDefault){
-                e.preventDefault();
-            }
-        }
-        if(Ext.isArray(eventName)){
-            Ext.each(eventName, function(e) {
-                 me.on(e, fn);
-            });
-            return me;
-        }
-        me.on(eventName, fn);
-        return me;
+    getRecordCount: function() {
+        var chart = this.chart,
+            store = chart.substore || chart.store;
+        return store ? store.getCount() : 0;
     },
 
     
-    relayEvent : function(eventName, observable){
-        this.on(eventName, function(e){
-            observable.fireEvent(eventName, e);
-        });
+    isExcluded: function(index) {
+        var excludes = this.__excludes;
+        return !!(excludes && excludes[index]);
     },
 
     
-    clean : function(forceReclean){
+    setBBox: function(noGutter) {
         var me = this,
-            dom = me.dom,
-            n = dom.firstChild,
-            ni = -1;
+            chart = me.chart,
+            chartBBox = chart.chartBBox,
+            gutterX = noGutter ? 0 : chart.maxGutter[0],
+            gutterY = noGutter ? 0 : chart.maxGutter[1],
+            clipBox, bbox;
+
+        clipBox = {
+            x: chartBBox.x,
+            y: chartBBox.y,
+            width: chartBBox.width,
+            height: chartBBox.height
+        };
+        me.clipBox = clipBox;
 
-        if(Ext.Element.data(dom, 'isCleaned') && forceReclean !== true){
-            return me;
+        bbox = {
+            x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
+            y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
+            width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
+            height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
+        };
+        me.bbox = bbox;
+    },
+
+    
+    onAnimate: function(sprite, attr) {
+        var me = this;
+        sprite.stopAnimation();
+        if (me.triggerAfterDraw) {
+            return sprite.animate(Ext.applyIf(attr, me.chart.animate));
+        } else {
+            me.triggerAfterDraw = true;
+            return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
+                listeners: {
+                    'afteranimate': function() {
+                        me.triggerAfterDraw = false;
+                        me.fireEvent('afterrender');
+                    }
+                }
+            }));
         }
+    },
 
-        while(n){
-            var nx = n.nextSibling;
-            if(n.nodeType == 3 && !/\S/.test(n.nodeValue)){
-                dom.removeChild(n);
-            }else{
-                n.nodeIndex = ++ni;
+    
+    getGutters: function() {
+        return [0, 0];
+    },
+
+    
+    onItemMouseOver: function(item) {
+        var me = this;
+        if (item.series === me) {
+            if (me.highlight) {
+                me.highlightItem(item);
+            }
+            if (me.tooltip) {
+                me.showTip(item);
             }
-            n = nx;
         }
-        Ext.Element.data(dom, 'isCleaned', true);
-        return me;
     },
 
     
-    load : function(){
-        var um = this.getUpdater();
-        um.update.apply(um, arguments);
-        return this;
+    onItemMouseOut: function(item) {
+        var me = this;
+        if (item.series === me) {
+            me.unHighlightItem();
+            if (me.tooltip) {
+                me.hideTip(item);
+            }
+        }
     },
 
     
-    getUpdater : function(){
-        return this.updateManager || (this.updateManager = new Ext.Updater(this));
+    onMouseLeave: function() {
+        var me = this;
+        me.unHighlightItem();
+        if (me.tooltip) {
+            me.hideTip();
+        }
     },
 
     
-    update : function(html, loadScripts, callback){
-        if (!this.dom) {
-            return this;
+    getItemForPoint: function(x, y) {
+        
+        if (!this.items || !this.items.length || this.seriesIsHidden) {
+            return null;
         }
-        html = html || "";
-
-        if(loadScripts !== true){
-            this.dom.innerHTML = html;
-            if(typeof callback == 'function'){
-                callback();
+        var me = this,
+            items = me.items,
+            bbox = me.bbox,
+            item, i, ln;
+        
+        if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
+            return null;
+        }
+        for (i = 0, ln = items.length; i < ln; i++) {
+            if (items[i] && this.isItemInPoint(x, y, items[i], i)) {
+                return items[i];
             }
-            return this;
         }
 
-        var id = Ext.id(),
-            dom = this.dom;
+        return null;
+    },
 
-        html += '<span id="' + id + '"></span>';
-
-        Ext.lib.Event.onAvailable(id, function(){
-            var DOC = document,
-                hd = DOC.getElementsByTagName("head")[0],
-                re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
-                srcRe = /\ssrc=([\'\"])(.*?)\1/i,
-                typeRe = /\stype=([\'\"])(.*?)\1/i,
-                match,
-                attrs,
-                srcMatch,
-                typeMatch,
-                el,
-                s;
+    isItemInPoint: function(x, y, item, i) {
+        return false;
+    },
 
-            while((match = re.exec(html))){
-                attrs = match[1];
-                srcMatch = attrs ? attrs.match(srcRe) : false;
-                if(srcMatch && srcMatch[2]){
-                   s = DOC.createElement("script");
-                   s.src = srcMatch[2];
-                   typeMatch = attrs.match(typeRe);
-                   if(typeMatch && typeMatch[2]){
-                       s.type = typeMatch[2];
-                   }
-                   hd.appendChild(s);
-                }else if(match[2] && match[2].length > 0){
-                    if(window.execScript) {
-                       window.execScript(match[2]);
-                    } else {
-                       window.eval(match[2]);
-                    }
+    
+    hideAll: function() {
+        var me = this,
+            items = me.items,
+            item, len, i, j, l, sprite, shadows;
+
+        me.seriesIsHidden = true;
+        me._prevShowMarkers = me.showMarkers;
+
+        me.showMarkers = false;
+        
+        me.hideLabels(0);
+        
+        for (i = 0, len = items.length; i < len; i++) {
+            item = items[i];
+            sprite = item.sprite;
+            if (sprite) {
+                sprite.setAttributes({
+                    hidden: true
+                }, true);
+            }
+
+            if (sprite && sprite.shadows) {
+                shadows = sprite.shadows;
+                for (j = 0, l = shadows.length; j < l; ++j) {
+                    shadows[j].setAttributes({
+                        hidden: true
+                    }, true);
                 }
             }
-            el = DOC.getElementById(id);
-            if(el){Ext.removeNode(el);}
-            if(typeof callback == 'function'){
-                callback();
-            }
-        });
-        dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
-        return this;
+        }
     },
 
     
-    removeAllListeners : function(){
-        this.removeAnchor();
-        Ext.EventManager.removeAll(this.dom);
-        return this;
+    showAll: function() {
+        var me = this,
+            prevAnimate = me.chart.animate;
+        me.chart.animate = false;
+        me.seriesIsHidden = false;
+        me.showMarkers = me._prevShowMarkers;
+        me.drawSeries();
+        me.chart.animate = prevAnimate;
+    },
+
+    
+    getLegendColor: function(index) {
+        var me = this, fill, stroke;
+        if (me.seriesStyle) {
+            fill = me.seriesStyle.fill;
+            stroke = me.seriesStyle.stroke;
+            if (fill && fill != 'none') {
+                return fill;
+            }
+            return stroke;
+        }
+        return '#000';
     },
 
     
-    createProxy : function(config, renderTo, matchBox){
-        config = (typeof config == 'object') ? config : {tag : "div", cls: config};
+    visibleInLegend: function(index){
+        var excludes = this.__excludes;
+        if (excludes) {
+            return !excludes[index];
+        }
+        return !this.seriesIsHidden;
+    },
 
+    
+    setTitle: function(index, title) {
         var me = this,
-            proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
-                               Ext.DomHelper.insertBefore(me.dom, config, true);
+            oldTitle = me.title;
 
-        if(matchBox && me.setBox && me.getBox){ 
-           proxy.setBox(me.getBox());
+        if (Ext.isString(index)) {
+            title = index;
+            index = 0;
         }
-        return proxy;
+
+        if (Ext.isArray(oldTitle)) {
+            oldTitle[index] = title;
+        } else {
+            me.title = title;
+        }
+
+        me.fireEvent('titlechange', title, index);
     }
 });
 
-Ext.Element.prototype.getUpdateManager = Ext.Element.prototype.getUpdater;
 
-Ext.Element.addMethods({
+Ext.define('Ext.chart.series.Cartesian', {
+
     
-    getAnchorXY : function(anchor, local, s){
-        
-        
-               anchor = (anchor || "tl").toLowerCase();
-        s = s || {};
-        
-        var me = this,        
-               vp = me.dom == document.body || me.dom == document,
-               w = s.width || vp ? Ext.lib.Dom.getViewWidth() : me.getWidth(),
-               h = s.height || vp ? Ext.lib.Dom.getViewHeight() : me.getHeight(),                              
-               xy,             
-               r = Math.round,
-               o = me.getXY(),
-               scroll = me.getScroll(),
-               extraX = vp ? scroll.left : !local ? o[0] : 0,
-               extraY = vp ? scroll.top : !local ? o[1] : 0,
-               hash = {
-                       c  : [r(w * 0.5), r(h * 0.5)],
-                       t  : [r(w * 0.5), 0],
-                       l  : [0, r(h * 0.5)],
-                       r  : [w, r(h * 0.5)],
-                       b  : [r(w * 0.5), h],
-                       tl : [0, 0],    
-                       bl : [0, h],
-                       br : [w, h],
-                       tr : [w, 0]
-               };
-        
-        xy = hash[anchor];     
-        return [xy[0] + extraX, xy[1] + extraY]; 
-    },
-
-    
-    anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){        
-           var me = this,
-            dom = me.dom,
-            scroll = !Ext.isEmpty(monitorScroll),
-            action = function(){
-                Ext.fly(dom).alignTo(el, alignment, offsets, animate);
-                Ext.callback(callback, Ext.fly(dom));
-            },
-            anchor = this.getAnchor();
+
+    extend: 'Ext.chart.series.Series',
+
+    alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'],
+
+    
+
+    
+    xField: null,
+
+    
+    yField: null,
+
+    
+    axis: 'left',
+
+    getLegendLabels: function() {
+        var me = this,
+            labels = [],
+            combinations = me.combinations;
+
+        Ext.each([].concat(me.yField), function(yField, i) {
+            var title = me.title;
             
-        
-        this.removeAnchor();
-        Ext.apply(anchor, {
-            fn: action,
-            scroll: scroll
+            labels.push((Ext.isArray(title) ? title[i] : title) || yField);
         });
 
-        Ext.EventManager.onWindowResize(action, null);
         
-        if(scroll){
-            Ext.EventManager.on(window, 'scroll', action, null,
-                {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
+        if (combinations) {
+            Ext.each(combinations, function(combo) {
+                var label0 = labels[combo[0]],
+                    label1 = labels[combo[1]];
+                labels[combo[1]] = label0 + ' & ' + label1;
+                labels.splice(combo[0], 1);
+            });
         }
-        action.call(me); 
-        return me;
+
+        return labels;
     },
+
     
+    eachYValue: function(record, fn, scope) {
+        Ext.each(this.getYValueAccessors(), function(accessor, i) {
+            fn.call(scope, accessor(record), i);
+        });
+    },
+
     
-    removeAnchor : function(){
+    getYValueCount: function() {
+        return this.getYValueAccessors().length;
+    },
+
+    combine: function(index1, index2) {
         var me = this,
-            anchor = this.getAnchor();
-            
-        if(anchor && anchor.fn){
-            Ext.EventManager.removeResizeListener(anchor.fn);
-            if(anchor.scroll){
-                Ext.EventManager.un(window, 'scroll', anchor.fn);
-            }
-            delete anchor.fn;
+            accessors = me.getYValueAccessors(),
+            accessor1 = accessors[index1],
+            accessor2 = accessors[index2];
+
+        
+        accessors[index2] = function(record) {
+            return accessor1(record) + accessor2(record);
+        };
+        accessors.splice(index1, 1);
+
+        me.callParent([index1, index2]);
+    },
+
+    clearCombinations: function() {
+        
+        delete this.yValueAccessors;
+        this.callParent();
+    },
+
+    
+    getYValueAccessors: function() {
+        var me = this,
+            accessors = me.yValueAccessors;
+        if (!accessors) {
+            accessors = me.yValueAccessors = [];
+            Ext.each([].concat(me.yField), function(yField) {
+                accessors.push(function(record) {
+                    return record.get(yField);
+                });
+            });
         }
-        return me;
+        return accessors;
     },
+
     
+    getMinMaxXValues: function() {
+        var me = this,
+            min, max,
+            xField = me.xField;
+
+        if (me.getRecordCount() > 0) {
+            min = Infinity;
+            max = -min;
+            me.eachRecord(function(record) {
+                var xValue = record.get(xField);
+                if (xValue > max) {
+                    max = xValue;
+                }
+                if (xValue < min) {
+                    min = xValue;
+                }
+            });
+        } else {
+            min = max = 0;
+        }
+        return [min, max];
+    },
+
     
-    getAnchor : function(){
-        var data = Ext.Element.data,
-            dom = this.dom;
-            if (!dom) {
-                return;
+    getMinMaxYValues: function() {
+        var me = this,
+            stacked = me.stacked,
+            min, max,
+            positiveTotal, negativeTotal;
+
+        function eachYValueStacked(yValue, i) {
+            if (!me.isExcluded(i)) {
+                if (yValue < 0) {
+                    negativeTotal += yValue;
+                } else {
+                    positiveTotal += yValue;
+                }
             }
-            var anchor = data(dom, '_anchor');
-            
-        if(!anchor){
-            anchor = data(dom, '_anchor', {});
         }
-        return anchor;
+
+        function eachYValue(yValue, i) {
+            if (!me.isExcluded(i)) {
+                if (yValue > max) {
+                    max = yValue;
+                }
+                if (yValue < min) {
+                    min = yValue;
+                }
+            }
+        }
+
+        if (me.getRecordCount() > 0) {
+            min = Infinity;
+            max = -min;
+            me.eachRecord(function(record) {
+                if (stacked) {
+                    positiveTotal = 0;
+                    negativeTotal = 0;
+                    me.eachYValue(record, eachYValueStacked);
+                    if (positiveTotal > max) {
+                        max = positiveTotal;
+                    }
+                    if (negativeTotal < min) {
+                        min = negativeTotal;
+                    }
+                } else {
+                    me.eachYValue(record, eachYValue);
+                }
+            });
+        } else {
+            min = max = 0;
+        }
+        return [min, max];
     },
 
-    
-    getAlignToXY : function(el, p, o){     
-        el = Ext.get(el);
-        
-        if(!el || !el.dom){
-            throw "Element.alignToXY with an element that doesn't exist";
+    getAxesForXAndYFields: function() {
+        var me = this,
+            axes = me.chart.axes,
+            axis = [].concat(me.axis),
+            xAxis, yAxis;
+
+        if (Ext.Array.indexOf(axis, 'top') > -1) {
+            xAxis = 'top';
+        } else if (Ext.Array.indexOf(axis, 'bottom') > -1) {
+            xAxis = 'bottom';
+        } else {
+            if (axes.get('top')) {
+                xAxis = 'top';
+            } else if (axes.get('bottom')) {
+                xAxis = 'bottom';
+            }
         }
-        
-        o = o || [0,0];
-        p = (!p || p == "?" ? "tl-bl?" : (!/-/.test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();       
-                
-        var me = this,
-               d = me.dom,
-               a1,
-               a2,
-               x,
-               y,
-               
-               w,
-               h,
-               r,
-               dw = Ext.lib.Dom.getViewWidth() -10, 
-               dh = Ext.lib.Dom.getViewHeight()-10, 
-               p1y,
-               p1x,            
-               p2y,
-               p2x,
-               swapY,
-               swapX,
-               doc = document,
-               docElement = doc.documentElement,
-               docBody = doc.body,
-               scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
-               scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
-               c = false, 
-               p1 = "", 
-               p2 = "",
-               m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
-        
-        if(!m){
-           throw "Element.alignTo with an invalid alignment " + p;
+
+        if (Ext.Array.indexOf(axis, 'left') > -1) {
+            yAxis = 'left';
+        } else if (Ext.Array.indexOf(axis, 'right') > -1) {
+            yAxis = 'right';
+        } else {
+            if (axes.get('left')) {
+                yAxis = 'left';
+            } else if (axes.get('right')) {
+                yAxis = 'right';
+            }
         }
-        
-        p1 = m[1]; 
-        p2 = m[2]; 
-        c = !!m[3];
 
-        
-        
-        a1 = me.getAnchorXY(p1, true);
-        a2 = el.getAnchorXY(p2, false);
+        return {
+            xAxis: xAxis,
+            yAxis: yAxis
+        };
+    }
 
-        x = a2[0] - a1[0] + o[0];
-        y = a2[1] - a1[1] + o[1];
 
-        if(c){    
-              w = me.getWidth();
-           h = me.getHeight();
-           r = el.getRegion();       
-           
-           
-           
-           p1y = p1.charAt(0);
-           p1x = p1.charAt(p1.length-1);
-           p2y = p2.charAt(0);
-           p2x = p2.charAt(p2.length-1);
-           swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
-           swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));          
-           
+});
 
-           if (x + w > dw + scrollX) {
-                x = swapX ? r.left-w : dw+scrollX-w;
-           }
-           if (x < scrollX) {
-               x = swapX ? r.right : scrollX;
-           }
-           if (y + h > dh + scrollY) {
-                y = swapY ? r.top-h : dh+scrollY-h;
+
+Ext.define('Ext.chart.series.Area', {
+
+    
+
+    extend: 'Ext.chart.series.Cartesian',
+
+    alias: 'series.area',
+
+    requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
+
+    
+
+    type: 'area',
+
+    
+    stacked: true,
+
+    
+    style: {},
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            surface = me.chart.surface,
+            i, l;
+        Ext.apply(me, config, {
+            __excludes: [],
+            highlightCfg: {
+                lineWidth: 3,
+                stroke: '#55c',
+                opacity: 0.8,
+                color: '#f00'
             }
-           if (y < scrollY){
-               y = swapY ? r.bottom : scrollY;
-           }
+        });
+        if (me.highlight) {
+            me.highlightSprite = surface.add({
+                type: 'path',
+                path: ['M', 0, 0],
+                zIndex: 1000,
+                opacity: 0.3,
+                lineWidth: 5,
+                hidden: true,
+                stroke: '#444'
+            });
         }
-        return [x,y];
+        me.group = surface.getGroup(me.seriesId);
     },
 
     
-    alignTo : function(element, position, offsets, animate){
-           var me = this;
-        return me.setXY(me.getAlignToXY(element, position, offsets),
-                               me.preanim && !!animate ? me.preanim(arguments, 3) : false);
-    },
-    
-    
-    adjustForConstraints : function(xy, parent, offsets){
-        return this.getConstrainToXY(parent || document, false, offsets, xy) ||  xy;
+    shrink: function(xValues, yValues, size) {
+        var len = xValues.length,
+            ratio = Math.floor(len / size),
+            i, j,
+            xSum = 0,
+            yCompLen = this.areas.length,
+            ySum = [],
+            xRes = [],
+            yRes = [];
+        
+        for (j = 0; j < yCompLen; ++j) {
+            ySum[j] = 0;
+        }
+        for (i = 0; i < len; ++i) {
+            xSum += xValues[i];
+            for (j = 0; j < yCompLen; ++j) {
+                ySum[j] += yValues[i][j];
+            }
+            if (i % ratio == 0) {
+                
+                xRes.push(xSum/ratio);
+                for (j = 0; j < yCompLen; ++j) {
+                    ySum[j] /= ratio;
+                }
+                yRes.push(ySum);
+                
+                xSum = 0;
+                for (j = 0, ySum = []; j < yCompLen; ++j) {
+                    ySum[j] = 0;
+                }
+            }
+        }
+        return {
+            x: xRes,
+            y: yRes
+        };
     },
 
     
-    getConstrainToXY : function(el, local, offsets, proposedXY){   
-           var os = {top:0, left:0, bottom:0, right: 0};
+    getBounds: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            areas = [].concat(me.yField),
+            areasLen = areas.length,
+            xValues = [],
+            yValues = [],
+            infinity = Infinity,
+            minX = infinity,
+            minY = infinity,
+            maxX = -infinity,
+            maxY = -infinity,
+            math = Math,
+            mmin = math.min,
+            mmax = math.max,
+            bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
+
+        me.setBBox();
+        bbox = me.bbox;
+
+        
+        if (me.axis) {
+            axis = chart.axes.get(me.axis);
+            if (axis) {
+                out = axis.calcEnds();
+                minY = out.from || axis.prevMin;
+                maxY = mmax(out.to || axis.prevMax, 0);
+            }
+        }
+
+        if (me.yField && !Ext.isNumber(minY)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.yField)
+            });
+            out = axis.calcEnds();
+            minY = out.from || axis.prevMin;
+            maxY = mmax(out.to || axis.prevMax, 0);
+        }
 
-        return function(el, local, offsets, proposedXY){
-            el = Ext.get(el);
-            offsets = offsets ? Ext.applyIf(offsets, os) : os;
+        if (!Ext.isNumber(minY)) {
+            minY = 0;
+        }
+        if (!Ext.isNumber(maxY)) {
+            maxY = 0;
+        }
 
-            var vw, vh, vx = 0, vy = 0;
-            if(el.dom == document.body || el.dom == document){
-                vw =Ext.lib.Dom.getViewWidth();
-                vh = Ext.lib.Dom.getViewHeight();
-            }else{
-                vw = el.dom.clientWidth;
-                vh = el.dom.clientHeight;
-                if(!local){
-                    var vxy = el.getXY();
-                    vx = vxy[0];
-                    vy = vxy[1];
+        store.each(function(record, i) {
+            xValue = record.get(me.xField);
+            yValue = [];
+            if (typeof xValue != 'number') {
+                xValue = i;
+            }
+            xValues.push(xValue);
+            acumY = 0;
+            for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
+                areaElem = record.get(areas[areaIndex]);
+                if (typeof areaElem == 'number') {
+                    minY = mmin(minY, areaElem);
+                    yValue.push(areaElem);
+                    acumY += areaElem;
                 }
             }
+            minX = mmin(minX, xValue);
+            maxX = mmax(maxX, xValue);
+            maxY = mmax(maxY, acumY);
+            yValues.push(yValue);
+        }, me);
 
-            var s = el.getScroll();
-
-            vx += offsets.left + s.left;
-            vy += offsets.top + s.top;
+        xScale = bbox.width / ((maxX - minX) || 1);
+        yScale = bbox.height / ((maxY - minY) || 1);
 
-            vw -= offsets.right;
-            vh -= offsets.bottom;
+        ln = xValues.length;
+        if ((ln > bbox.width) && me.areas) {
+            sumValues = me.shrink(xValues, yValues, bbox.width);
+            xValues = sumValues.x;
+            yValues = sumValues.y;
+        }
 
-            var vr = vx + vw,
-                vb = vy + vh,
-                xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]),
-                x = xy[0], y = xy[1],
-                offset = this.getConstrainOffset(),
-                w = this.dom.offsetWidth + offset, 
-                h = this.dom.offsetHeight + offset;
+        return {
+            bbox: bbox,
+            minX: minX,
+            minY: minY,
+            xValues: xValues,
+            yValues: yValues,
+            xScale: xScale,
+            yScale: yScale,
+            areasLen: areasLen
+        };
+    },
 
-            
-            var moved = false;
+    
+    getPaths: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            first = true,
+            bounds = me.getBounds(),
+            bbox = bounds.bbox,
+            items = me.items = [],
+            componentPaths = [],
+            componentPath,
+            paths = [],
+            i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
+
+        ln = bounds.xValues.length;
+        
+        for (i = 0; i < ln; i++) {
+            xValue = bounds.xValues[i];
+            yValue = bounds.yValues[i];
+            x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
+            acumY = 0;
+            for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
+                
+                if (me.__excludes[areaIndex]) {
+                    continue;
+                }
+                if (!componentPaths[areaIndex]) {
+                    componentPaths[areaIndex] = [];
+                }
+                areaElem = yValue[areaIndex];
+                acumY += areaElem;
+                y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
+                if (!paths[areaIndex]) {
+                    paths[areaIndex] = ['M', x, y];
+                    componentPaths[areaIndex].push(['L', x, y]);
+                } else {
+                    paths[areaIndex].push('L', x, y);
+                    componentPaths[areaIndex].push(['L', x, y]);
+                }
+                if (!items[areaIndex]) {
+                    items[areaIndex] = {
+                        pointsUp: [],
+                        pointsDown: [],
+                        series: me
+                    };
+                }
+                items[areaIndex].pointsUp.push([x, y]);
+            }
+        }
 
+        
+        for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
             
-            if((x + w) > vr){
-                x = vr - w;
-                moved = true;
-            }
-            if((y + h) > vb){
-                y = vb - h;
-                moved = true;
+            if (me.__excludes[areaIndex]) {
+                continue;
             }
+            path = paths[areaIndex];
             
-            if(x < vx){
-                x = vx;
-                moved = true;
+            if (areaIndex == 0 || first) {
+                first = false;
+                path.push('L', x, bbox.y + bbox.height,
+                          'L', bbox.x, bbox.y + bbox.height,
+                          'Z');
             }
-            if(y < vy){
-                y = vy;
-                moved = true;
+            
+            else {
+                componentPath = componentPaths[prevAreaIndex];
+                componentPath.reverse();
+                path.push('L', x, componentPath[0][2]);
+                for (i = 0; i < ln; i++) {
+                    path.push(componentPath[i][0],
+                              componentPath[i][1],
+                              componentPath[i][2]);
+                    items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
+                }
+                path.push('L', bbox.x, path[2], 'Z');
             }
-            return moved ? [x, y] : false;
+            prevAreaIndex = areaIndex;
+        }
+        return {
+            paths: paths,
+            areasLen: bounds.areasLen
         };
-    }(),
-           
-           
-               
-
+    },
 
+    
+    drawSeries: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            surface = chart.surface,
+            animate = chart.animate,
+            group = me.group,
+            endLineStyle = Ext.apply(me.seriesStyle, me.style),
+            colorArrayStyle = me.colorArrayStyle,
+            colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+            areaIndex, areaElem, paths, path, rendererAttributes;
+
+        me.unHighlightItem();
+        me.cleanHighlights();
+
+        if (!store || !store.getCount()) {
+            return;
+        }
 
+        paths = me.getPaths();
 
+        if (!me.areas) {
+            me.areas = [];
+        }
 
+        for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
+            
+            if (me.__excludes[areaIndex]) {
+                continue;
+            }
+            if (!me.areas[areaIndex]) {
+                me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
+                    type: 'path',
+                    group: group,
+                    
+                    path: paths.paths[areaIndex],
+                    stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
+                    fill: colorArrayStyle[areaIndex % colorArrayLength]
+                }, endLineStyle || {}));
+            }
+            areaElem = me.areas[areaIndex];
+            path = paths.paths[areaIndex];
+            if (animate) {
+                
+                rendererAttributes = me.renderer(areaElem, false, {
+                    path: path,
+                    
+                    fill: colorArrayStyle[areaIndex % colorArrayLength],
+                    stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
+                }, areaIndex, store);
+                
+                me.animation = me.onAnimate(areaElem, {
+                    to: rendererAttributes
+                });
+            } else {
+                rendererAttributes = me.renderer(areaElem, false, {
+                    path: path,
+                    
+                    hidden: false,
+                    fill: colorArrayStyle[areaIndex % colorArrayLength],
+                    stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
+                }, areaIndex, store);
+                me.areas[areaIndex].setAttributes(rendererAttributes, true);
+            }
+        }
+        me.renderLabels();
+        me.renderCallouts();
+    },
 
+    
+    onAnimate: function(sprite, attr) {
+        sprite.show();
+        return this.callParent(arguments);
+    },
 
+    
+    onCreateLabel: function(storeItem, item, i, display) {
+        var me = this,
+            group = me.labelsGroup,
+            config = me.label,
+            bbox = me.bbox,
+            endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
 
+        return me.chart.surface.add(Ext.apply({
+            'type': 'text',
+            'text-anchor': 'middle',
+            'group': group,
+            'x': item.point[0],
+            'y': bbox.y + bbox.height / 2
+        }, endLabelStyle || {}));
+    },
 
+    
+    onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.label,
+            format = config.renderer,
+            field = config.field,
+            bbox = me.bbox,
+            x = item.point[0],
+            y = item.point[1],
+            bb, width, height;
+
+        label.setAttributes({
+            text: format(storeItem.get(field[index])),
+            hidden: true
+        }, true);
 
+        bb = label.getBBox();
+        width = bb.width / 2;
+        height = bb.height / 2;
+
+        x = x - width < bbox.x? bbox.x + width : x;
+        x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+        y = y - height < bbox.y? bbox.y + height : y;
+        y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+
+        if (me.chart.animate && !me.chart.resizing) {
+            label.show(true);
+            me.onAnimate(label, {
+                to: {
+                    x: x,
+                    y: y
+                }
+            });
+        } else {
+            label.setAttributes({
+                x: x,
+                y: y
+            }, true);
+            if (resizing) {
+                me.animation.on('afteranimate', function() {
+                    label.show(true);
+                });
+            } else {
+                label.show(true);
+            }
+        }
+    },
 
+    
+    onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            resizing = chart.resizing,
+            config = me.callouts,
+            items = me.items,
+            prev = (i == 0) ? false : items[i -1].point,
+            next = (i == items.length -1) ? false : items[i +1].point,
+            cur = item.point,
+            dir, norm, normal, a, aprev, anext,
+            bbox = callout.label.getBBox(),
+            offsetFromViz = 30,
+            offsetToSide = 10,
+            offsetBox = 3,
+            boxx, boxy, boxw, boxh,
+            p, clipRect = me.clipRect,
+            x, y;
 
+        
+        if (!prev) {
+            prev = cur;
+        }
+        if (!next) {
+            next = cur;
+        }
+        a = (next[1] - prev[1]) / (next[0] - prev[0]);
+        aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
+        anext = (next[1] - cur[1]) / (next[0] - cur[0]);
 
+        norm = Math.sqrt(1 + a * a);
+        dir = [1 / norm, a / norm];
+        normal = [-dir[1], dir[0]];
 
+        
+        if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
+            normal[0] *= -1;
+            normal[1] *= -1;
+        } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
+            normal[0] *= -1;
+            normal[1] *= -1;
+        }
 
+        
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
+        
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
+        
+        
+        if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+            normal[0] *= -1;
+        }
+        if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+            normal[1] *= -1;
+        }
 
+        
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
+        
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
+        
+        callout.lines.setAttributes({
+            path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+        }, true);
+        
+        callout.box.setAttributes({
+            x: boxx,
+            y: boxy,
+            width: boxw,
+            height: boxh
+        }, true);
+        
+        callout.label.setAttributes({
+            x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+            y: y
+        }, true);
+        for (p in callout) {
+            callout[p].show(true);
+        }
+    },
 
+    isItemInPoint: function(x, y, item, i) {
+        var me = this,
+            pointsUp = item.pointsUp,
+            pointsDown = item.pointsDown,
+            abs = Math.abs,
+            dist = Infinity, p, pln, point;
+
+        for (p = 0, pln = pointsUp.length; p < pln; p++) {
+            point = [pointsUp[p][0], pointsUp[p][1]];
+            if (dist > abs(x - point[0])) {
+                dist = abs(x - point[0]);
+            } else {
+                point = pointsUp[p -1];
+                if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
+                    item.storeIndex = p -1;
+                    item.storeField = me.yField[i];
+                    item.storeItem = me.chart.store.getAt(p -1);
+                    item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
+                    return true;
+                } else {
+                    break;
+                }
+            }
+        }
+        return false;
+    },
 
+    
+    highlightSeries: function() {
+        var area, to, fillColor;
+        if (this._index !== undefined) {
+            area = this.areas[this._index];
+            if (area.__highlightAnim) {
+                area.__highlightAnim.paused = true;
+            }
+            area.__highlighted = true;
+            area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
+            area.__prevFill = area.__prevFill || area.attr.fill;
+            area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
+            fillColor = Ext.draw.Color.fromString(area.__prevFill);
+            to = {
+                lineWidth: (area.__prevLineWidth || 0) + 2
+            };
+            if (fillColor) {
+                to.fill = fillColor.getLighter(0.2).toString();
+            }
+            else {
+                to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
+            }
+            if (this.chart.animate) {
+                area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
+                    target: area,
+                    to: to
+                }, this.chart.animate));
+            }
+            else {
+                area.setAttributes(to, true);
+            }
+        }
+    },
 
+    
+    unHighlightSeries: function() {
+        var area;
+        if (this._index !== undefined) {
+            area = this.areas[this._index];
+            if (area.__highlightAnim) {
+                area.__highlightAnim.paused = true;
+            }
+            if (area.__highlighted) {
+                area.__highlighted = false;
+                area.__highlightAnim = Ext.create('Ext.fx.Anim', {
+                    target: area,
+                    to: {
+                        fill: area.__prevFill,
+                        opacity: area.__prevOpacity,
+                        lineWidth: area.__prevLineWidth
+                    }
+                });
+            }
+        }
+    },
 
+    
+    highlightItem: function(item) {
+        var me = this,
+            points, path;
+        if (!item) {
+            this.highlightSeries();
+            return;
+        }
+        points = item._points;
+        path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
+                : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
+        me.highlightSprite.setAttributes({
+            path: path,
+            hidden: false
+        }, true);
+    },
 
+    
+    unHighlightItem: function(item) {
+        if (!item) {
+            this.unHighlightSeries();
+        }
 
+        if (this.highlightSprite) {
+            this.highlightSprite.hide(true);
+        }
+    },
 
+    
+    hideAll: function() {
+        if (!isNaN(this._index)) {
+            this.__excludes[this._index] = true;
+            this.areas[this._index].hide(true);
+            this.drawSeries();
+        }
+    },
 
+    
+    showAll: function() {
+        if (!isNaN(this._index)) {
+            this.__excludes[this._index] = false;
+            this.areas[this._index].show(true);
+            this.drawSeries();
+        }
+    },
 
+    
+    getLegendColor: function(index) {
+        var me = this;
+        return me.colorArrayStyle[index % me.colorArrayStyle.length];
+    }
+});
 
+Ext.define('Ext.chart.series.Area', {
 
+    
 
+    extend: 'Ext.chart.series.Cartesian',
 
+    alias: 'series.area',
 
+    requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
 
+    
 
+    type: 'area',
 
+    
+    stacked: true,
 
+    
+    style: {},
 
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            surface = me.chart.surface,
+            i, l;
+        Ext.apply(me, config, {
+            __excludes: [],
+            highlightCfg: {
+                lineWidth: 3,
+                stroke: '#55c',
+                opacity: 0.8,
+                color: '#f00'
+            }
+        });
+        if (me.highlight) {
+            me.highlightSprite = surface.add({
+                type: 'path',
+                path: ['M', 0, 0],
+                zIndex: 1000,
+                opacity: 0.3,
+                lineWidth: 5,
+                hidden: true,
+                stroke: '#444'
+            });
+        }
+        me.group = surface.getGroup(me.seriesId);
+    },
 
+    
+    shrink: function(xValues, yValues, size) {
+        var len = xValues.length,
+            ratio = Math.floor(len / size),
+            i, j,
+            xSum = 0,
+            yCompLen = this.areas.length,
+            ySum = [],
+            xRes = [],
+            yRes = [];
+        
+        for (j = 0; j < yCompLen; ++j) {
+            ySum[j] = 0;
+        }
+        for (i = 0; i < len; ++i) {
+            xSum += xValues[i];
+            for (j = 0; j < yCompLen; ++j) {
+                ySum[j] += yValues[i][j];
+            }
+            if (i % ratio == 0) {
+                
+                xRes.push(xSum/ratio);
+                for (j = 0; j < yCompLen; ++j) {
+                    ySum[j] /= ratio;
+                }
+                yRes.push(ySum);
+                
+                xSum = 0;
+                for (j = 0, ySum = []; j < yCompLen; ++j) {
+                    ySum[j] = 0;
+                }
+            }
+        }
+        return {
+            x: xRes,
+            y: yRes
+        };
+    },
 
+    
+    getBounds: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            areas = [].concat(me.yField),
+            areasLen = areas.length,
+            xValues = [],
+            yValues = [],
+            infinity = Infinity,
+            minX = infinity,
+            minY = infinity,
+            maxX = -infinity,
+            maxY = -infinity,
+            math = Math,
+            mmin = math.min,
+            mmax = math.max,
+            bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
+
+        me.setBBox();
+        bbox = me.bbox;
+
+        
+        if (me.axis) {
+            axis = chart.axes.get(me.axis);
+            if (axis) {
+                out = axis.calcEnds();
+                minY = out.from || axis.prevMin;
+                maxY = mmax(out.to || axis.prevMax, 0);
+            }
+        }
+
+        if (me.yField && !Ext.isNumber(minY)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.yField)
+            });
+            out = axis.calcEnds();
+            minY = out.from || axis.prevMin;
+            maxY = mmax(out.to || axis.prevMax, 0);
+        }
 
+        if (!Ext.isNumber(minY)) {
+            minY = 0;
+        }
+        if (!Ext.isNumber(maxY)) {
+            maxY = 0;
+        }
 
+        store.each(function(record, i) {
+            xValue = record.get(me.xField);
+            yValue = [];
+            if (typeof xValue != 'number') {
+                xValue = i;
+            }
+            xValues.push(xValue);
+            acumY = 0;
+            for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
+                areaElem = record.get(areas[areaIndex]);
+                if (typeof areaElem == 'number') {
+                    minY = mmin(minY, areaElem);
+                    yValue.push(areaElem);
+                    acumY += areaElem;
+                }
+            }
+            minX = mmin(minX, xValue);
+            maxX = mmax(maxX, xValue);
+            maxY = mmax(maxY, acumY);
+            yValues.push(yValue);
+        }, me);
 
+        xScale = bbox.width / ((maxX - minX) || 1);
+        yScale = bbox.height / ((maxY - minY) || 1);
 
+        ln = xValues.length;
+        if ((ln > bbox.width) && me.areas) {
+            sumValues = me.shrink(xValues, yValues, bbox.width);
+            xValues = sumValues.x;
+            yValues = sumValues.y;
+        }
 
+        return {
+            bbox: bbox,
+            minX: minX,
+            minY: minY,
+            xValues: xValues,
+            yValues: yValues,
+            xScale: xScale,
+            yScale: yScale,
+            areasLen: areasLen
+        };
+    },
 
+    
+    getPaths: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            first = true,
+            bounds = me.getBounds(),
+            bbox = bounds.bbox,
+            items = me.items = [],
+            componentPaths = [],
+            componentPath,
+            paths = [],
+            i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
+
+        ln = bounds.xValues.length;
+        
+        for (i = 0; i < ln; i++) {
+            xValue = bounds.xValues[i];
+            yValue = bounds.yValues[i];
+            x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
+            acumY = 0;
+            for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
+                
+                if (me.__excludes[areaIndex]) {
+                    continue;
+                }
+                if (!componentPaths[areaIndex]) {
+                    componentPaths[areaIndex] = [];
+                }
+                areaElem = yValue[areaIndex];
+                acumY += areaElem;
+                y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
+                if (!paths[areaIndex]) {
+                    paths[areaIndex] = ['M', x, y];
+                    componentPaths[areaIndex].push(['L', x, y]);
+                } else {
+                    paths[areaIndex].push('L', x, y);
+                    componentPaths[areaIndex].push(['L', x, y]);
+                }
+                if (!items[areaIndex]) {
+                    items[areaIndex] = {
+                        pointsUp: [],
+                        pointsDown: [],
+                        series: me
+                    };
+                }
+                items[areaIndex].pointsUp.push([x, y]);
+            }
+        }
 
+        
+        for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
+            
+            if (me.__excludes[areaIndex]) {
+                continue;
+            }
+            path = paths[areaIndex];
+            
+            if (areaIndex == 0 || first) {
+                first = false;
+                path.push('L', x, bbox.y + bbox.height,
+                          'L', bbox.x, bbox.y + bbox.height,
+                          'Z');
+            }
+            
+            else {
+                componentPath = componentPaths[prevAreaIndex];
+                componentPath.reverse();
+                path.push('L', x, componentPath[0][2]);
+                for (i = 0; i < ln; i++) {
+                    path.push(componentPath[i][0],
+                              componentPath[i][1],
+                              componentPath[i][2]);
+                    items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
+                }
+                path.push('L', bbox.x, path[2], 'Z');
+            }
+            prevAreaIndex = areaIndex;
+        }
+        return {
+            paths: paths,
+            areasLen: bounds.areasLen
+        };
+    },
 
+    
+    drawSeries: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            surface = chart.surface,
+            animate = chart.animate,
+            group = me.group,
+            endLineStyle = Ext.apply(me.seriesStyle, me.style),
+            colorArrayStyle = me.colorArrayStyle,
+            colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+            areaIndex, areaElem, paths, path, rendererAttributes;
+
+        me.unHighlightItem();
+        me.cleanHighlights();
+
+        if (!store || !store.getCount()) {
+            return;
+        }
 
+        paths = me.getPaths();
 
+        if (!me.areas) {
+            me.areas = [];
+        }
 
+        for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
+            
+            if (me.__excludes[areaIndex]) {
+                continue;
+            }
+            if (!me.areas[areaIndex]) {
+                me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
+                    type: 'path',
+                    group: group,
+                    
+                    path: paths.paths[areaIndex],
+                    stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
+                    fill: colorArrayStyle[areaIndex % colorArrayLength]
+                }, endLineStyle || {}));
+            }
+            areaElem = me.areas[areaIndex];
+            path = paths.paths[areaIndex];
+            if (animate) {
+                
+                rendererAttributes = me.renderer(areaElem, false, {
+                    path: path,
+                    
+                    fill: colorArrayStyle[areaIndex % colorArrayLength],
+                    stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
+                }, areaIndex, store);
+                
+                me.animation = me.onAnimate(areaElem, {
+                    to: rendererAttributes
+                });
+            } else {
+                rendererAttributes = me.renderer(areaElem, false, {
+                    path: path,
+                    
+                    hidden: false,
+                    fill: colorArrayStyle[areaIndex % colorArrayLength],
+                    stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
+                }, areaIndex, store);
+                me.areas[areaIndex].setAttributes(rendererAttributes, true);
+            }
+        }
+        me.renderLabels();
+        me.renderCallouts();
+    },
 
     
-    getConstrainOffset : function(){
-        return 0;
+    onAnimate: function(sprite, attr) {
+        sprite.show();
+        return this.callParent(arguments);
     },
+
     
-    
-    getCenterXY : function(){
-        return this.getAlignToXY(document, 'c-c');
+    onCreateLabel: function(storeItem, item, i, display) {
+        var me = this,
+            group = me.labelsGroup,
+            config = me.label,
+            bbox = me.bbox,
+            endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
+
+        return me.chart.surface.add(Ext.apply({
+            'type': 'text',
+            'text-anchor': 'middle',
+            'group': group,
+            'x': item.point[0],
+            'y': bbox.y + bbox.height / 2
+        }, endLabelStyle || {}));
     },
 
     
-    center : function(centerIn){
-        return this.alignTo(centerIn || document, 'c-c');        
-    }    
-});
+    onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.label,
+            format = config.renderer,
+            field = config.field,
+            bbox = me.bbox,
+            x = item.point[0],
+            y = item.point[1],
+            bb, width, height;
+
+        label.setAttributes({
+            text: format(storeItem.get(field[index])),
+            hidden: true
+        }, true);
 
-Ext.Element.addMethods(function(){
-       var PARENTNODE = 'parentNode',
-               NEXTSIBLING = 'nextSibling',
-               PREVIOUSSIBLING = 'previousSibling',
-               DQ = Ext.DomQuery,
-               GET = Ext.get;
-       
-       return {
-               
-           findParent : function(simpleSelector, maxDepth, returnEl){
-               var p = this.dom,
-                       b = document.body, 
-                       depth = 0,                      
-                       stopEl;         
-            if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
-                return null;
-            }
-               maxDepth = maxDepth || 50;
-               if (isNaN(maxDepth)) {
-                   stopEl = Ext.getDom(maxDepth);
-                   maxDepth = Number.MAX_VALUE;
-               }
-               while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
-                   if(DQ.is(p, simpleSelector)){
-                       return returnEl ? GET(p) : p;
-                   }
-                   depth++;
-                   p = p.parentNode;
-               }
-               return null;
-           },
-       
-           
-           findParentNode : function(simpleSelector, maxDepth, returnEl){
-               var p = Ext.fly(this.dom.parentNode, '_internal');
-               return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
-           },
-       
-           
-           up : function(simpleSelector, maxDepth){
-               return this.findParentNode(simpleSelector, maxDepth, true);
-           },
-       
-           
-           select : function(selector){
-               return Ext.Element.select(selector, this.dom);
-           },
-       
-           
-           query : function(selector){
-               return DQ.select(selector, this.dom);
-           },
-       
-           
-           child : function(selector, returnDom){
-               var n = DQ.selectNode(selector, this.dom);
-               return returnDom ? n : GET(n);
-           },
-       
-           
-           down : function(selector, returnDom){
-               var n = DQ.selectNode(" > " + selector, this.dom);
-               return returnDom ? n : GET(n);
-           },
-       
-                
-           parent : function(selector, returnDom){
-               return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
-           },
-       
-            
-           next : function(selector, returnDom){
-               return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
-           },
-       
-           
-           prev : function(selector, returnDom){
-               return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
-           },
-       
-       
-           
-           first : function(selector, returnDom){
-               return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
-           },
-       
-           
-           last : function(selector, returnDom){
-               return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
-           },
-           
-           matchNode : function(dir, start, selector, returnDom){
-               var n = this.dom[start];
-               while(n){
-                   if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
-                       return !returnDom ? GET(n) : n;
-                   }
-                   n = n[dir];
-               }
-               return null;
-           }   
-    }
-}());
-Ext.Element.addMethods({
-    
-    select : function(selector, unique){
-        return Ext.Element.select(selector, unique, this.dom);
-    }
-});
-Ext.Element.addMethods(
-function() {
-       var GETDOM = Ext.getDom,
-               GET = Ext.get,
-               DH = Ext.DomHelper;
-       
-       return {
-           
-           appendChild: function(el){        
-               return GET(el).appendTo(this);        
-           },
-       
-           
-           appendTo: function(el){        
-               GETDOM(el).appendChild(this.dom);        
-               return this;
-           },
-       
-           
-           insertBefore: function(el){                   
-               (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
-               return this;
-           },
-       
-           
-           insertAfter: function(el){
-               (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
-               return this;
-           },
-       
-           
-           insertFirst: function(el, returnDom){
-            el = el || {};
-            if(el.nodeType || el.dom || typeof el == 'string'){ 
-                el = GETDOM(el);
-                this.dom.insertBefore(el, this.dom.firstChild);
-                return !returnDom ? GET(el) : el;
-            }else{ 
-                return this.createChild(el, this.dom.firstChild, returnDom);
-            }
-        },
-       
-           
-           replace: function(el){
-               el = GET(el);
-               this.insertBefore(el);
-               el.remove();
-               return this;
-           },
-       
-           
-           replaceWith: function(el){
-                   var me = this;
-                
-            if(el.nodeType || el.dom || typeof el == 'string'){
-                el = GETDOM(el);
-                me.dom.parentNode.insertBefore(el, me.dom);
-            }else{
-                el = DH.insertBefore(me.dom, el);
-            }
-               
-               delete Ext.elCache[me.id];
-               Ext.removeNode(me.dom);      
-               me.id = Ext.id(me.dom = el);
-               Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
-            return me;
-           },
-           
-               
-               createChild: function(config, insertBefore, returnDom){
-                   config = config || {tag:'div'};
-                   return insertBefore ? 
-                          DH.insertBefore(insertBefore, config, returnDom !== true) :  
-                          DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
-               },
-               
-               
-               wrap: function(config, returnDom){        
-                   var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
-                   newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
-                   return newEl;
-               },
-               
-               
-               insertHtml : function(where, html, returnEl){
-                   var el = DH.insertHtml(where, this.dom, html);
-                   return returnEl ? Ext.get(el) : el;
-               }
-       }
-}());
-Ext.apply(Ext.Element.prototype, function() {
-       var GETDOM = Ext.getDom,
-               GET = Ext.get,
-               DH = Ext.DomHelper;
-       
-       return {        
-               
-           insertSibling: function(el, where, returnDom){
-               var me = this,
-                       rt,
-                isAfter = (where || 'before').toLowerCase() == 'after',
-                insertEl;
-                       
-               if(Ext.isArray(el)){
-                insertEl = me;
-                   Ext.each(el, function(e) {
-                           rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
-                    if(isAfter){
-                        insertEl = rt;
-                    }
-                   });
-                   return rt;
-               }
-                       
-               el = el || {};
-               
-            if(el.nodeType || el.dom){
-                rt = me.dom.parentNode.insertBefore(GETDOM(el), isAfter ? me.dom.nextSibling : me.dom);
-                if (!returnDom) {
-                    rt = GET(rt);
-                }
-            }else{
-                if (isAfter && !me.dom.nextSibling) {
-                    rt = DH.append(me.dom.parentNode, el, !returnDom);
-                } else {                    
-                    rt = DH[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
+        bb = label.getBBox();
+        width = bb.width / 2;
+        height = bb.height / 2;
+
+        x = x - width < bbox.x? bbox.x + width : x;
+        x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+        y = y - height < bbox.y? bbox.y + height : y;
+        y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+
+        if (me.chart.animate && !me.chart.resizing) {
+            label.show(true);
+            me.onAnimate(label, {
+                to: {
+                    x: x,
+                    y: y
                 }
+            });
+        } else {
+            label.setAttributes({
+                x: x,
+                y: y
+            }, true);
+            if (resizing) {
+                me.animation.on('afteranimate', function() {
+                    label.show(true);
+                });
+            } else {
+                label.show(true);
             }
-               return rt;
-           }
-    };
-}());
-Ext.Element.addMethods(function(){
-    
-    var propCache = {},
-        camelRe = /(-[a-z])/gi,
-        view = document.defaultView,
-        propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
-        opacityRe = /alpha\(opacity=(.*)\)/i,
-        trimRe = /^\s+|\s+$/g,
-        spacesRe = /\s+/,
-        wordsRe = /\w/g,
-        PADDING = "padding",
-        MARGIN = "margin",
-        BORDER = "border",
-        LEFT = "-left",
-        RIGHT = "-right",
-        TOP = "-top",
-        BOTTOM = "-bottom",
-        WIDTH = "-width",
-        MATH = Math,
-        HIDDEN = 'hidden',
-        ISCLIPPED = 'isClipped',
-        OVERFLOW = 'overflow',
-        OVERFLOWX = 'overflow-x',
-        OVERFLOWY = 'overflow-y',
-        ORIGINALCLIP = 'originalClip',
-        
-        borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
-        paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
-        margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
-        data = Ext.Element.data;
-
+        }
+    },
 
     
-    function camelFn(m, a) {
-        return a.charAt(1).toUpperCase();
-    }
-
-    function chkCache(prop) {
-        return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
-    }
-
-    return {
-        
-        adjustWidth : function(width) {
-            var me = this;
-            var isNum = (typeof width == "number");
-            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
-               width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
-            }
-            return (isNum && width < 0) ? 0 : width;
-        },
+    onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            resizing = chart.resizing,
+            config = me.callouts,
+            items = me.items,
+            prev = (i == 0) ? false : items[i -1].point,
+            next = (i == items.length -1) ? false : items[i +1].point,
+            cur = item.point,
+            dir, norm, normal, a, aprev, anext,
+            bbox = callout.label.getBBox(),
+            offsetFromViz = 30,
+            offsetToSide = 10,
+            offsetBox = 3,
+            boxx, boxy, boxw, boxh,
+            p, clipRect = me.clipRect,
+            x, y;
 
         
-        adjustHeight : function(height) {
-            var me = this;
-            var isNum = (typeof height == "number");
-            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
-               height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
-            }
-            return (isNum && height < 0) ? 0 : height;
-        },
+        if (!prev) {
+            prev = cur;
+        }
+        if (!next) {
+            next = cur;
+        }
+        a = (next[1] - prev[1]) / (next[0] - prev[0]);
+        aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
+        anext = (next[1] - cur[1]) / (next[0] - cur[0]);
 
+        norm = Math.sqrt(1 + a * a);
+        dir = [1 / norm, a / norm];
+        normal = [-dir[1], dir[0]];
 
         
-        addClass : function(className){
-            var me = this,
-                i,
-                len,
-                v,
-                cls = [];
-            
-            if (!Ext.isArray(className)) {
-                if (typeof className == 'string' && !this.hasClass(className)) {
-                    me.dom.className += " " + className;
-                }
-            }
-            else {
-                for (i = 0, len = className.length; i < len; i++) {
-                    v = className[i];
-                    if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
-                        cls.push(v);
-                    }
-                }
-                if (cls.length) {
-                    me.dom.className += " " + cls.join(" ");
-                }
-            }
-            return me;
-        },
+        if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
+            normal[0] *= -1;
+            normal[1] *= -1;
+        } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
+            normal[0] *= -1;
+            normal[1] *= -1;
+        }
 
         
-        removeClass : function(className){
-            var me = this,
-                i,
-                idx,
-                len,
-                cls,
-                elClasses;
-            if (!Ext.isArray(className)){
-                className = [className];
-            }
-            if (me.dom && me.dom.className) {
-                elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
-                for (i = 0, len = className.length; i < len; i++) {
-                    cls = className[i];
-                    if (typeof cls == 'string') {
-                        cls = cls.replace(trimRe, '');
-                        idx = elClasses.indexOf(cls);
-                        if (idx != -1) {
-                            elClasses.splice(idx, 1);
-                        }
-                    }
-                }
-                me.dom.className = elClasses.join(" ");
-            }
-            return me;
-        },
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
         
-        radioClass : function(className){
-            var cn = this.dom.parentNode.childNodes,
-                v,
-                i,
-                len;
-            className = Ext.isArray(className) ? className : [className];
-            for (i = 0, len = cn.length; i < len; i++) {
-                v = cn[i];
-                if (v && v.nodeType == 1) {
-                    Ext.fly(v, '_internal').removeClass(className);
-                }
-            };
-            return this.addClass(className);
-        },
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
         
-        toggleClass : function(className){
-            return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
-        },
-
         
-        hasClass : function(className){
-            return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
-        },
+        if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+            normal[0] *= -1;
+        }
+        if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+            normal[1] *= -1;
+        }
 
         
-        replaceClass : function(oldClassName, newClassName){
-            return this.removeClass(oldClassName).addClass(newClassName);
-        },
-
-        isStyle : function(style, val) {
-            return this.getStyle(style) == val;
-        },
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
         
-        getStyle : function(){
-            return view && view.getComputedStyle ?
-                function(prop){
-                    var el = this.dom,
-                        v,
-                        cs,
-                        out,
-                        display,
-                        wk = Ext.isWebKit,
-                        display;
-
-                    if(el == document){
-                        return null;
-                    }
-                    prop = chkCache(prop);
-                    
-                    if(wk && (/marginRight/.test(prop))) {
-                        display = this.getStyle('display');
-                        el.style.display = 'inline-block';
-                    }
-                    out = (v = el.style[prop]) ? v :
-                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
-
-                    
-                    if(wk){
-                        if(out == 'rgba(0, 0, 0, 0)'){
-                            out = 'transparent';
-                        }else if(display){
-                            el.style.display = display;
-                        }
-                    }
-                    return out;
-                } :
-                function(prop){
-                    var el = this.dom,
-                        m,
-                        cs;
-
-                    if(el == document) return null;
-                    if (prop == 'opacity') {
-                        if (el.style.filter.match) {
-                            if(m = el.style.filter.match(opacityRe)){
-                                var fv = parseFloat(m[1]);
-                                if(!isNaN(fv)){
-                                    return fv ? fv / 100 : 0;
-                                }
-                            }
-                        }
-                        return 1;
-                    }
-                    prop = chkCache(prop);
-                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
-                };
-        }(),
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
         
-        getColor : function(attr, defaultValue, prefix){
-            var v = this.getStyle(attr),
-                color = (typeof prefix != 'undefined') ? prefix : '#',
-                h;
+        callout.lines.setAttributes({
+            path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+        }, true);
+        
+        callout.box.setAttributes({
+            x: boxx,
+            y: boxy,
+            width: boxw,
+            height: boxh
+        }, true);
+        
+        callout.label.setAttributes({
+            x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+            y: y
+        }, true);
+        for (p in callout) {
+            callout[p].show(true);
+        }
+    },
 
-            if(!v || (/transparent|inherit/.test(v))) {
-                return defaultValue;
+    isItemInPoint: function(x, y, item, i) {
+        var me = this,
+            pointsUp = item.pointsUp,
+            pointsDown = item.pointsDown,
+            abs = Math.abs,
+            dist = Infinity, p, pln, point;
+
+        for (p = 0, pln = pointsUp.length; p < pln; p++) {
+            point = [pointsUp[p][0], pointsUp[p][1]];
+            if (dist > abs(x - point[0])) {
+                dist = abs(x - point[0]);
+            } else {
+                point = pointsUp[p -1];
+                if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
+                    item.storeIndex = p -1;
+                    item.storeField = me.yField[i];
+                    item.storeItem = me.chart.store.getAt(p -1);
+                    item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
+                    return true;
+                } else {
+                    break;
+                }
             }
-            if(/^r/.test(v)){
-                Ext.each(v.slice(4, v.length -1).split(','), function(s){
-                    h = parseInt(s, 10);
-                    color += (h < 16 ? '0' : '') + h.toString(16);
-                });
-            }else{
-                v = v.replace('#', '');
-                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
+        }
+        return false;
+    },
+
+    
+    highlightSeries: function() {
+        var area, to, fillColor;
+        if (this._index !== undefined) {
+            area = this.areas[this._index];
+            if (area.__highlightAnim) {
+                area.__highlightAnim.paused = true;
             }
-            return(color.length > 5 ? color.toLowerCase() : defaultValue);
-        },
+            area.__highlighted = true;
+            area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
+            area.__prevFill = area.__prevFill || area.attr.fill;
+            area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
+            fillColor = Ext.draw.Color.fromString(area.__prevFill);
+            to = {
+                lineWidth: (area.__prevLineWidth || 0) + 2
+            };
+            if (fillColor) {
+                to.fill = fillColor.getLighter(0.2).toString();
+            }
+            else {
+                to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
+            }
+            if (this.chart.animate) {
+                area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
+                    target: area,
+                    to: to
+                }, this.chart.animate));
+            }
+            else {
+                area.setAttributes(to, true);
+            }
+        }
+    },
 
-        
-        setStyle : function(prop, value){
-            var tmp, style;
-            
-            if (typeof prop != 'object') {
-                tmp = {};
-                tmp[prop] = value;
-                prop = tmp;
+    
+    unHighlightSeries: function() {
+        var area;
+        if (this._index !== undefined) {
+            area = this.areas[this._index];
+            if (area.__highlightAnim) {
+                area.__highlightAnim.paused = true;
             }
-            for (style in prop) {
-                value = prop[style];
-                style == 'opacity' ?
-                    this.setOpacity(value) :
-                    this.dom.style[chkCache(style)] = value;
+            if (area.__highlighted) {
+                area.__highlighted = false;
+                area.__highlightAnim = Ext.create('Ext.fx.Anim', {
+                    target: area,
+                    to: {
+                        fill: area.__prevFill,
+                        opacity: area.__prevOpacity,
+                        lineWidth: area.__prevLineWidth
+                    }
+                });
             }
-            return this;
-        },
+        }
+    },
 
-        
-         setOpacity : function(opacity, animate){
-            var me = this,
-                s = me.dom.style;
+    
+    highlightItem: function(item) {
+        var me = this,
+            points, path;
+        if (!item) {
+            this.highlightSeries();
+            return;
+        }
+        points = item._points;
+        path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
+                : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
+        me.highlightSprite.setAttributes({
+            path: path,
+            hidden: false
+        }, true);
+    },
 
-            if(!animate || !me.anim){
-                if(Ext.isIE){
-                    var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
-                    val = s.filter.replace(opacityRe, '').replace(trimRe, '');
+    
+    unHighlightItem: function(item) {
+        if (!item) {
+            this.unHighlightSeries();
+        }
 
-                    s.zoom = 1;
-                    s.filter = val + (val.length > 0 ? ' ' : '') + opac;
-                }else{
-                    s.opacity = opacity;
-                }
-            }else{
-                me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
-            }
-            return me;
-        },
+        if (this.highlightSprite) {
+            this.highlightSprite.hide(true);
+        }
+    },
 
-        
-        clearOpacity : function(){
-            var style = this.dom.style;
-            if(Ext.isIE){
-                if(!Ext.isEmpty(style.filter)){
-                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
-                }
-            }else{
-                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
-            }
-            return this;
-        },
+    
+    hideAll: function() {
+        if (!isNaN(this._index)) {
+            this.__excludes[this._index] = true;
+            this.areas[this._index].hide(true);
+            this.drawSeries();
+        }
+    },
+
+    
+    showAll: function() {
+        if (!isNaN(this._index)) {
+            this.__excludes[this._index] = false;
+            this.areas[this._index].show(true);
+            this.drawSeries();
+        }
+    },
+
+    
+    getLegendColor: function(index) {
+        var me = this;
+        return me.colorArrayStyle[index % me.colorArrayStyle.length];
+    }
+});
+
+
+Ext.define('Ext.chart.series.Bar', {
+
+    
 
-        
-        getHeight : function(contentHeight){
-            var me = this,
-                dom = me.dom,
-                hidden = Ext.isIE && me.isStyle('display', 'none'),
-                h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
+    extend: 'Ext.chart.series.Cartesian',
 
-            h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
-            return h < 0 ? 0 : h;
-        },
+    alternateClassName: ['Ext.chart.BarSeries', 'Ext.chart.BarChart', 'Ext.chart.StackedBarChart'],
 
-        
-        getWidth : function(contentWidth){
-            var me = this,
-                dom = me.dom,
-                hidden = Ext.isIE && me.isStyle('display', 'none'),
-                w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
-            w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
-            return w < 0 ? 0 : w;
-        },
+    requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
 
-        
-        setWidth : function(width, animate){
-            var me = this;
-            width = me.adjustWidth(width);
-            !animate || !me.anim ?
-                me.dom.style.width = me.addUnits(width) :
-                me.anim({width : {to : width}}, me.preanim(arguments, 1));
-            return me;
-        },
+    
 
-        
-         setHeight : function(height, animate){
-            var me = this;
-            height = me.adjustHeight(height);
-            !animate || !me.anim ?
-                me.dom.style.height = me.addUnits(height) :
-                me.anim({height : {to : height}}, me.preanim(arguments, 1));
-            return me;
-        },
+    type: 'bar',
 
-        
-        getBorderWidth : function(side){
-            return this.addStyles(side, borders);
-        },
+    alias: 'series.bar',
+    
+    column: false,
 
-        
-        getPadding : function(side){
-            return this.addStyles(side, paddings);
-        },
+    
+    style: {},
 
-        
-        clip : function(){
-            var me = this,
-                dom = me.dom;
+    
+    gutter: 38.2,
 
-            if(!data(dom, ISCLIPPED)){
-                data(dom, ISCLIPPED, true);
-                data(dom, ORIGINALCLIP, {
-                    o: me.getStyle(OVERFLOW),
-                    x: me.getStyle(OVERFLOWX),
-                    y: me.getStyle(OVERFLOWY)
-                });
-                me.setStyle(OVERFLOW, HIDDEN);
-                me.setStyle(OVERFLOWX, HIDDEN);
-                me.setStyle(OVERFLOWY, HIDDEN);
-            }
-            return me;
-        },
+    
+    groupGutter: 38.2,
 
-        
-        unclip : function(){
-            var me = this,
-                dom = me.dom;
+    
+    xPadding: 0,
 
-            if(data(dom, ISCLIPPED)){
-                data(dom, ISCLIPPED, false);
-                var o = data(dom, ORIGINALCLIP);
-                if(o.o){
-                    me.setStyle(OVERFLOW, o.o);
-                }
-                if(o.x){
-                    me.setStyle(OVERFLOWX, o.x);
+    
+    yPadding: 10,
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            surface = me.chart.surface,
+            shadow = me.chart.shadow,
+            i, l;
+        Ext.apply(me, config, {
+            highlightCfg: {
+                lineWidth: 3,
+                stroke: '#55c',
+                opacity: 0.8,
+                color: '#f00'
+            },
+
+            shadowAttributes: [{
+                "stroke-width": 6,
+                "stroke-opacity": 0.05,
+                stroke: 'rgb(200, 200, 200)',
+                translate: {
+                    x: 1.2,
+                    y: 1.2
                 }
-                if(o.y){
-                    me.setStyle(OVERFLOWY, o.y);
+            }, {
+                "stroke-width": 4,
+                "stroke-opacity": 0.1,
+                stroke: 'rgb(150, 150, 150)',
+                translate: {
+                    x: 0.9,
+                    y: 0.9
                 }
-            }
-            return me;
-        },
-
-        
-        addStyles : function(sides, styles){
-            var ttlSize = 0,
-                sidesArr = sides.match(wordsRe),
-                side,
-                size,
-                i,
-                len = sidesArr.length;
-            for (i = 0; i < len; i++) {
-                side = sidesArr[i];
-                size = side && parseInt(this.getStyle(styles[side]), 10);
-                if (size) {
-                    ttlSize += MATH.abs(size);
+            }, {
+                "stroke-width": 2,
+                "stroke-opacity": 0.15,
+                stroke: 'rgb(100, 100, 100)',
+                translate: {
+                    x: 0.6,
+                    y: 0.6
                 }
+            }]
+        });
+        me.group = surface.getGroup(me.seriesId + '-bars');
+        if (shadow) {
+            for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+                me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
             }
-            return ttlSize;
-        },
+        }
+    },
 
-        margins : margins
-    };
-}()
-);
+    
+    getBarGirth: function() {
+        var me = this,
+            store = me.chart.getChartStore(),
+            column = me.column,
+            ln = store.getCount(),
+            gutter = me.gutter / 100;
 
+        return (me.chart.chartBBox[column ? 'width' : 'height'] - me[column ? 'xPadding' : 'yPadding'] * 2) / (ln * (gutter + 1) - gutter);
+    },
 
+    
+    getGutters: function() {
+        var me = this,
+            column = me.column,
+            gutter = Math.ceil(me[column ? 'xPadding' : 'yPadding'] + me.getBarGirth() / 2);
+        return me.column ? [gutter, 0] : [0, gutter];
+    },
 
-Ext.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
+    
+    getBounds: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            bars = [].concat(me.yField),
+            barsLen = bars.length,
+            groupBarsLen = barsLen,
+            groupGutter = me.groupGutter / 100,
+            column = me.column,
+            xPadding = me.xPadding,
+            yPadding = me.yPadding,
+            stacked = me.stacked,
+            barWidth = me.getBarGirth(),
+            math = Math,
+            mmax = math.max,
+            mabs = math.abs,
+            groupBarWidth, bbox, minY, maxY, axis, out,
+            scale, zero, total, rec, j, plus, minus;
+
+        me.setBBox(true);
+        bbox = me.bbox;
+
+        
+        if (me.__excludes) {
+            for (j = 0, total = me.__excludes.length; j < total; j++) {
+                if (me.__excludes[j]) {
+                    groupBarsLen--;
+                }
+            }
+        }
 
-Ext.Element.addMethods(function(){
-    var INTERNAL = "_internal",
-        pxMatch = /(\d+\.?\d+)px/;
-    return {
-        
-        applyStyles : function(style){
-            Ext.DomHelper.applyStyles(this.dom, style);
-            return this;
-        },
+        if (me.axis) {
+            axis = chart.axes.get(me.axis);
+            if (axis) {
+                out = axis.calcEnds();
+                minY = out.from;
+                maxY = out.to;
+            }
+        }
 
-        
-        getStyles : function(){
-            var ret = {};
-            Ext.each(arguments, function(v) {
-               ret[v] = this.getStyle(v);
-            },
-            this);
-            return ret;
-        },
+        if (me.yField && !Ext.isNumber(minY)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.yField)
+            });
+            out = axis.calcEnds();
+            minY = out.from;
+            maxY = out.to;
+        }
 
-        
-        setOverflow : function(v){
-            var dom = this.dom;
-            if(v=='auto' && Ext.isMac && Ext.isGecko2){ 
-                dom.style.overflow = 'hidden';
-                (function(){dom.style.overflow = 'auto';}).defer(1);
-            }else{
-                dom.style.overflow = v;
-            }
-        },
+        if (!Ext.isNumber(minY)) {
+            minY = 0;
+        }
+        if (!Ext.isNumber(maxY)) {
+            maxY = 0;
+        }
+        scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (maxY - minY);
+        groupBarWidth = barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter);
+        zero = (column) ? bbox.y + bbox.height - yPadding : bbox.x + xPadding;
 
-       
-        boxWrap : function(cls){
-            cls = cls || 'x-box';
-            var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + String.format(Ext.Element.boxMarkup, cls) + "</div>"));        
-            Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
-            return el;
-        },
+        if (stacked) {
+            total = [[], []];
+            store.each(function(record, i) {
+                total[0][i] = total[0][i] || 0;
+                total[1][i] = total[1][i] || 0;
+                for (j = 0; j < barsLen; j++) {
+                    if (me.__excludes && me.__excludes[j]) {
+                        continue;
+                    }
+                    rec = record.get(bars[j]);
+                    total[+(rec > 0)][i] += mabs(rec);
+                }
+            });
+            total[+(maxY > 0)].push(mabs(maxY));
+            total[+(minY > 0)].push(mabs(minY));
+            minus = mmax.apply(math, total[0]);
+            plus = mmax.apply(math, total[1]);
+            scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (plus + minus);
+            zero = zero + minus * scale * (column ? -1 : 1);
+        }
+        else if (minY / maxY < 0) {
+            zero = zero - minY * scale * (column ? -1 : 1);
+        }
+        return {
+            bars: bars,
+            bbox: bbox,
+            barsLen: barsLen,
+            groupBarsLen: groupBarsLen,
+            barWidth: barWidth,
+            groupBarWidth: groupBarWidth,
+            scale: scale,
+            zero: zero,
+            xPadding: xPadding,
+            yPadding: yPadding,
+            signed: minY / maxY < 0,
+            minY: minY,
+            maxY: maxY
+        };
+    },
 
-        
-        setSize : function(width, height, animate){
-            var me = this;
-            if(typeof width == 'object'){ 
-                height = width.height;
-                width = width.width;
+    
+    getPaths: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            bounds = me.bounds = me.getBounds(),
+            items = me.items = [],
+            gutter = me.gutter / 100,
+            groupGutter = me.groupGutter / 100,
+            animate = chart.animate,
+            column = me.column,
+            group = me.group,
+            enableShadows = chart.shadow,
+            shadowGroups = me.shadowGroups,
+            shadowAttributes = me.shadowAttributes,
+            shadowGroupsLn = shadowGroups.length,
+            bbox = bounds.bbox,
+            xPadding = me.xPadding,
+            yPadding = me.yPadding,
+            stacked = me.stacked,
+            barsLen = bounds.barsLen,
+            colors = me.colorArrayStyle,
+            colorLength = colors && colors.length || 0,
+            math = Math,
+            mmax = math.max,
+            mmin = math.min,
+            mabs = math.abs,
+            j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter,
+            shadowIndex, shadow, sprite, offset, floorY;
+
+        store.each(function(record, i, total) {
+            bottom = bounds.zero;
+            top = bounds.zero;
+            totalDim = 0;
+            totalNegDim = 0;
+            hasShadow = false;
+            for (j = 0, counter = 0; j < barsLen; j++) {
+                
+                if (me.__excludes && me.__excludes[j]) {
+                    continue;
+                }
+                yValue = record.get(bounds.bars[j]);
+                height = Math.round((yValue - mmax(bounds.minY, 0)) * bounds.scale);
+                barAttr = {
+                    fill: colors[(barsLen > 1 ? j : 0) % colorLength]
+                };
+                if (column) {
+                    Ext.apply(barAttr, {
+                        height: height,
+                        width: mmax(bounds.groupBarWidth, 0),
+                        x: (bbox.x + xPadding + i * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked),
+                        y: bottom - height
+                    });
+                }
+                else {
+                    
+                    offset = (total - 1) - i;
+                    Ext.apply(barAttr, {
+                        height: mmax(bounds.groupBarWidth, 0),
+                        width: height + (bottom == bounds.zero),
+                        x: bottom + (bottom != bounds.zero),
+                        y: (bbox.y + yPadding + offset * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1)
+                    });
+                }
+                if (height < 0) {
+                    if (column) {
+                        barAttr.y = top;
+                        barAttr.height = mabs(height);
+                    } else {
+                        barAttr.x = top + height;
+                        barAttr.width = mabs(height);
+                    }
+                }
+                if (stacked) {
+                    if (height < 0) {
+                        top += height * (column ? -1 : 1);
+                    } else {
+                        bottom += height * (column ? -1 : 1);
+                    }
+                    totalDim += mabs(height);
+                    if (height < 0) {
+                        totalNegDim += mabs(height);
+                    }
+                }
+                barAttr.x = Math.floor(barAttr.x) + 1;
+                floorY = Math.floor(barAttr.y);
+                if (!Ext.isIE9 && barAttr.y > floorY) {
+                    floorY--;
+                }
+                barAttr.y = floorY;
+                barAttr.width = Math.floor(barAttr.width);
+                barAttr.height = Math.floor(barAttr.height);
+                items.push({
+                    series: me,
+                    storeItem: record,
+                    value: [record.get(me.xField), yValue],
+                    attr: barAttr,
+                    point: column ? [barAttr.x + barAttr.width / 2, yValue >= 0 ? barAttr.y : barAttr.y + barAttr.height] :
+                                    [yValue >= 0 ? barAttr.x + barAttr.width : barAttr.x, barAttr.y + barAttr.height / 2]
+                });
+                
+                if (animate && chart.resizing) {
+                    attrs = column ? {
+                        x: barAttr.x,
+                        y: bounds.zero,
+                        width: barAttr.width,
+                        height: 0
+                    } : {
+                        x: bounds.zero,
+                        y: barAttr.y,
+                        width: 0,
+                        height: barAttr.height
+                    };
+                    if (enableShadows && (stacked && !hasShadow || !stacked)) {
+                        hasShadow = true;
+                        
+                        for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+                            shadow = shadowGroups[shadowIndex].getAt(stacked ? i : (i * barsLen + j));
+                            if (shadow) {
+                                shadow.setAttributes(attrs, true);
+                            }
+                        }
+                    }
+                    
+                    sprite = group.getAt(i * barsLen + j);
+                    if (sprite) {
+                        sprite.setAttributes(attrs, true);
+                    }
+                }
+                counter++;
             }
-            width = me.adjustWidth(width);
-            height = me.adjustHeight(height);
-            if(!animate || !me.anim){
-                me.dom.style.width = me.addUnits(width);
-                me.dom.style.height = me.addUnits(height);
-            }else{
-                me.anim({width: {to: width}, height: {to: height}}, me.preanim(arguments, 2));
+            if (stacked && items.length) {
+                items[i * counter].totalDim = totalDim;
+                items[i * counter].totalNegDim = totalNegDim;
             }
-            return me;
-        },
+        }, me);
+    },
 
-        
-        getComputedHeight : function(){
-            var me = this,
-                h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
-            if(!h){
-                h = parseFloat(me.getStyle('height')) || 0;
-                if(!me.isBorderBox()){
-                    h += me.getFrameWidth('tb');
+    
+    renderShadows: function(i, barAttr, baseAttrs, bounds) {
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            animate = chart.animate,
+            stacked = me.stacked,
+            shadowGroups = me.shadowGroups,
+            shadowAttributes = me.shadowAttributes,
+            shadowGroupsLn = shadowGroups.length,
+            store = chart.getChartStore(),
+            column = me.column,
+            items = me.items,
+            shadows = [],
+            zero = bounds.zero,
+            shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes;
+
+        if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) {
+            j = i / bounds.groupBarsLen;
+            
+            for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+                shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]);
+                shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i);
+                Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height');
+                if (!shadow) {
+                    shadow = surface.add(Ext.apply({
+                        type: 'rect',
+                        group: shadowGroups[shadowIndex]
+                    }, Ext.apply({}, baseAttrs, shadowBarAttr)));
+                }
+                if (stacked) {
+                    totalDim = items[i].totalDim;
+                    totalNegDim = items[i].totalNegDim;
+                    if (column) {
+                        shadowBarAttr.y = zero - totalNegDim;
+                        shadowBarAttr.height = totalDim;
+                    }
+                    else {
+                        shadowBarAttr.x = zero - totalNegDim;
+                        shadowBarAttr.width = totalDim;
+                    }
                 }
+                if (animate) {
+                    if (!stacked) {
+                        rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store);
+                        me.onAnimate(shadow, { to: rendererAttributes });
+                    }
+                    else {
+                        rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: true }), i, store);
+                        shadow.setAttributes(rendererAttributes, true);
+                    }
+                }
+                else {
+                    rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: false }), i, store);
+                    shadow.setAttributes(rendererAttributes, true);
+                }
+                shadows.push(shadow);
             }
-            return h;
-        },
+        }
+        return shadows;
+    },
+
+    
+    drawSeries: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            surface = chart.surface,
+            animate = chart.animate,
+            stacked = me.stacked,
+            column = me.column,
+            enableShadows = chart.shadow,
+            shadowGroups = me.shadowGroups,
+            shadowGroupsLn = shadowGroups.length,
+            group = me.group,
+            seriesStyle = me.seriesStyle,
+            items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup,
+            bounds, endSeriesStyle, barAttr, attrs, anim;
+
+        if (!store || !store.getCount()) {
+            return;
+        }
 
         
-        getComputedWidth : function(){
-            var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
-            if(!w){
-                w = parseFloat(this.getStyle('width')) || 0;
-                if(!this.isBorderBox()){
-                    w += this.getFrameWidth('lr');
+        delete seriesStyle.fill;
+        endSeriesStyle = Ext.apply(seriesStyle, this.style);
+        me.unHighlightItem();
+        me.cleanHighlights();
+
+        me.getPaths();
+        bounds = me.bounds;
+        items = me.items;
+
+        baseAttrs = column ? {
+            y: bounds.zero,
+            height: 0
+        } : {
+            x: bounds.zero,
+            width: 0
+        };
+        ln = items.length;
+        
+        for (i = 0; i < ln; i++) {
+            sprite = group.getAt(i);
+            barAttr = items[i].attr;
+
+            if (enableShadows) {
+                items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds);
+            }
+
+            
+            if (!sprite) {
+                attrs = Ext.apply({}, baseAttrs, barAttr);
+                attrs = Ext.apply(attrs, endSeriesStyle || {});
+                sprite = surface.add(Ext.apply({}, {
+                    type: 'rect',
+                    group: group
+                }, attrs));
+            }
+            if (animate) {
+                rendererAttributes = me.renderer(sprite, store.getAt(i), barAttr, i, store);
+                sprite._to = rendererAttributes;
+                anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) });
+                if (enableShadows && stacked && (i % bounds.barsLen === 0)) {
+                    j = i / bounds.barsLen;
+                    for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+                        anim.on('afteranimate', function() {
+                            this.show(true);
+                        }, shadowGroups[shadowIndex].getAt(j));
+                    }
                 }
             }
-            return w;
-        },
+            else {
+                rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(barAttr, { hidden: false }), i, store);
+                sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true);
+            }
+            items[i].sprite = sprite;
+        }
 
         
-        getFrameWidth : function(sides, onlyContentBox){
-            return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
-        },
-
+        ln = group.getCount();
+        for (j = i; j < ln; j++) {
+            group.getAt(j).hide(true);
+        }
         
-        addClassOnOver : function(className){
-            this.hover(
-                function(){
-                    Ext.fly(this, INTERNAL).addClass(className);
-                },
-                function(){
-                    Ext.fly(this, INTERNAL).removeClass(className);
+        if (enableShadows) {
+            for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
+                shadowGroup = shadowGroups[shadowIndex];
+                ln = shadowGroup.getCount();
+                for (j = i; j < ln; j++) {
+                    shadowGroup.getAt(j).hide(true);
                 }
-            );
-            return this;
-        },
+            }
+        }
+        me.renderLabels();
+    },
 
-        
-        addClassOnFocus : function(className){
-            this.on("focus", function(){
-                Ext.fly(this, INTERNAL).addClass(className);
-            }, this.dom);
-            this.on("blur", function(){
-                Ext.fly(this, INTERNAL).removeClass(className);
-            }, this.dom);
-            return this;
-        },
+    
+    onCreateLabel: function(storeItem, item, i, display) {
+        var me = this,
+            surface = me.chart.surface,
+            group = me.labelsGroup,
+            config = me.label,
+            endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}),
+            sprite;
+        return surface.add(Ext.apply({
+            type: 'text',
+            group: group
+        }, endLabelStyle || {}));
+    },
 
+    
+    onPlaceLabel: function(label, storeItem, item, i, display, animate, j, index) {
         
-        addClassOnClick : function(className){
-            var dom = this.dom;
-            this.on("mousedown", function(){
-                Ext.fly(dom, INTERNAL).addClass(className);
-                var d = Ext.getDoc(),
-                    fn = function(){
-                        Ext.fly(dom, INTERNAL).removeClass(className);
-                        d.removeListener("mouseup", fn);
-                    };
-                d.on("mouseup", fn);
-            });
-            return this;
-        },
-
         
+        var me = this,
+            opt = me.bounds,
+            groupBarWidth = opt.groupBarWidth,
+            column = me.column,
+            chart = me.chart,
+            chartBBox = chart.chartBBox,
+            resizing = chart.resizing,
+            xValue = item.value[0],
+            yValue = item.value[1],
+            attr = item.attr,
+            config = me.label,
+            rotate = config.orientation == 'vertical',
+            field = [].concat(config.field),
+            format = config.renderer,
+            text = format(storeItem.get(field[index])),
+            size = me.getLabelSize(text),
+            width = size.width,
+            height = size.height,
+            zero = opt.zero,
+            outside = 'outside',
+            insideStart = 'insideStart',
+            insideEnd = 'insideEnd',
+            offsetX = 10,
+            offsetY = 6,
+            signed = opt.signed,
+            x, y, finalAttr;
+
+        label.setAttributes({
+            text: text
+        });
 
-        getViewSize : function(){
-            var doc = document,
-                d = this.dom,
-                isDoc = (d == doc || d == doc.body);
-
-            
-            if (isDoc) {
-                var extdom = Ext.lib.Dom;
-                return {
-                    width : extdom.getViewWidth(),
-                    height : extdom.getViewHeight()
-                };
-
-            
-            } else {
-                return {
-                    width : d.clientWidth,
-                    height : d.clientHeight
+        label.isOutside = false;
+        if (column) {
+            if (display == outside) {
+                if (height + offsetY + attr.height > (yValue >= 0 ? zero - chartBBox.y : chartBBox.y + chartBBox.height - zero)) {
+                    display = insideEnd;
                 }
-            }
-        },
-
-        
-
-        getStyleSize : function(){
-            var me = this,
-                w, h,
-                doc = document,
-                d = this.dom,
-                isDoc = (d == doc || d == doc.body),
-                s = d.style;
-
-            
-            if (isDoc) {
-                var extdom = Ext.lib.Dom;
-                return {
-                    width : extdom.getViewWidth(),
-                    height : extdom.getViewHeight()
+            } else {
+                if (height + offsetY > attr.height) {
+                    display = outside;
+                    label.isOutside = true;
                 }
             }
-            
-            if(s.width && s.width != 'auto'){
-                w = parseFloat(s.width);
-                if(me.isBorderBox()){
-                   w -= me.getFrameWidth('lr');
+            x = attr.x + groupBarWidth / 2;
+            y = display == insideStart ?
+                    (zero + ((height / 2 + 3) * (yValue >= 0 ? -1 : 1))) :
+                    (yValue >= 0 ? (attr.y + ((height / 2 + 3) * (display == outside ? -1 : 1))) :
+                                   (attr.y + attr.height + ((height / 2 + 3) * (display === outside ? 1 : -1))));
+        }
+        else {
+            if (display == outside) {
+                if (width + offsetX + attr.width > (yValue >= 0 ? chartBBox.x + chartBBox.width - zero : zero - chartBBox.x)) {
+                    display = insideEnd;
                 }
             }
-            
-            if(s.height && s.height != 'auto'){
-                h = parseFloat(s.height);
-                if(me.isBorderBox()){
-                   h -= me.getFrameWidth('tb');
+            else {
+                if (width + offsetX > attr.width) {
+                    display = outside;
+                    label.isOutside = true;
                 }
             }
-            
-            return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
-        },
-
-        
-        getSize : function(contentSize){
-            return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
-        },
-
+            x = display == insideStart ?
+                (zero + ((width / 2 + 5) * (yValue >= 0 ? 1 : -1))) :
+                (yValue >= 0 ? (attr.x + attr.width + ((width / 2 + 5) * (display === outside ? 1 : -1))) :
+                (attr.x + ((width / 2 + 5) * (display === outside ? -1 : 1))));
+            y = attr.y + groupBarWidth / 2;
+        }
         
-        repaint : function(){
-            var dom = this.dom;
-            this.addClass("x-repaint");
-            setTimeout(function(){
-                Ext.fly(dom).removeClass("x-repaint");
-            }, 1);
-            return this;
-        },
-
+        finalAttr = {
+            x: x,
+            y: y
+        };
         
-        unselectable : function(){
-            this.dom.unselectable = "on";
-            return this.swallowEvent("selectstart", true).
-                        applyStyles("-moz-user-select:none;-khtml-user-select:none;").
-                        addClass("x-unselectable");
-        },
-
+        if (rotate) {
+            finalAttr.rotate = {
+                x: x,
+                y: y,
+                degrees: 270
+            };
+        }
         
-        getMargins : function(side){
-            var me = this,
-                key,
-                hash = {t:"top", l:"left", r:"right", b: "bottom"},
-                o = {};
-
-            if (!side) {
-                for (key in me.margins){
-                    o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
-                }
-                return o;
+        if (animate && resizing) {
+            if (column) {
+                x = attr.x + attr.width / 2;
+                y = zero;
             } else {
-                return me.addStyles.call(me, side, me.margins);
+                x = zero;
+                y = attr.y + attr.height / 2;
+            }
+            label.setAttributes({
+                x: x,
+                y: y
+            }, true);
+            if (rotate) {
+                label.setAttributes({
+                    rotate: {
+                        x: x,
+                        y: y,
+                        degrees: 270
+                    }
+                }, true);
             }
         }
-    };
-}());
+        
+        if (animate) {
+            me.onAnimate(label, { to: finalAttr });
+        }
+        else {
+            label.setAttributes(Ext.apply(finalAttr, {
+                hidden: false
+            }), true);
+        }
+    },
 
-(function(){
-var D = Ext.lib.Dom,
-        LEFT = "left",
-        RIGHT = "right",
-        TOP = "top",
-        BOTTOM = "bottom",
-        POSITION = "position",
-        STATIC = "static",
-        RELATIVE = "relative",
-        AUTO = "auto",
-        ZINDEX = "z-index";
+    
+    getLabelSize: function(value) {
+        var tester = this.testerLabel,
+            config = this.label,
+            endLabelStyle = Ext.apply({}, config, this.seriesLabelStyle || {}),
+            rotated = config.orientation === 'vertical',
+            bbox, w, h,
+            undef;
+        if (!tester) {
+            tester = this.testerLabel = this.chart.surface.add(Ext.apply({
+                type: 'text',
+                opacity: 0
+            }, endLabelStyle));
+        }
+        tester.setAttributes({
+            text: value
+        }, true);
 
-Ext.Element.addMethods({
-       
-    getX : function(){
-        return D.getX(this.dom);
+        
+        bbox = tester.getBBox();
+        w = bbox.width;
+        h = bbox.height;
+        return {
+            width: rotated ? h : w,
+            height: rotated ? w : h
+        };
     },
 
     
-    getY : function(){
-        return D.getY(this.dom);
+    onAnimate: function(sprite, attr) {
+        sprite.show();
+        return this.callParent(arguments);
     },
 
-    
-    getXY : function(){
-        return D.getXY(this.dom);
+    isItemInPoint: function(x, y, item) {
+        var bbox = item.sprite.getBBox();
+        return bbox.x <= x && bbox.y <= y
+            && (bbox.x + bbox.width) >= x
+            && (bbox.y + bbox.height) >= y;
     },
 
     
-    getOffsetsTo : function(el){
-        var o = this.getXY(),
-               e = Ext.fly(el, '_internal').getXY();
-        return [o[0]-e[0],o[1]-e[1]];
+    hideAll: function() {
+        var axes = this.chart.axes;
+        if (!isNaN(this._index)) {
+            if (!this.__excludes) {
+                this.__excludes = [];
+            }
+            this.__excludes[this._index] = true;
+            this.drawSeries();
+            axes.each(function(axis) {
+                axis.drawAxis();
+            });
+        }
     },
 
     
-    setX : function(x, animate){           
-           return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
+    showAll: function() {
+        var axes = this.chart.axes;
+        if (!isNaN(this._index)) {
+            if (!this.__excludes) {
+                this.__excludes = [];
+            }
+            this.__excludes[this._index] = false;
+            this.drawSeries();
+            axes.each(function(axis) {
+                axis.drawAxis();
+            });
+        }
     },
 
     
-    setY : function(y, animate){           
-           return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
+    getLegendColor: function(index) {
+        var me = this,
+            colorLength = me.colorArrayStyle.length;
+
+        if (me.style && me.style.fill) {
+            return me.style.fill;
+        } else {
+            return me.colorArrayStyle[index % colorLength];
+        }
     },
 
-    
-    setLeft : function(left){
-        this.setStyle(LEFT, this.addUnits(left));
-        return this;
+    highlightItem: function(item) {
+        this.callParent(arguments);
+        this.renderLabels();
     },
 
-    
-    setTop : function(top){
-        this.setStyle(TOP, this.addUnits(top));
-        return this;
+    unHighlightItem: function() {
+        this.callParent(arguments);
+        this.renderLabels();
     },
 
+    cleanHighlights: function() {
+        this.callParent(arguments);
+        this.renderLabels();
+    }
+});
+
+Ext.define('Ext.chart.series.Column', {
+
     
-    setRight : function(right){
-        this.setStyle(RIGHT, this.addUnits(right));
-        return this;
-    },
+
+    alternateClassName: ['Ext.chart.ColumnSeries', 'Ext.chart.ColumnChart', 'Ext.chart.StackedColumnChart'],
+
+    extend: 'Ext.chart.series.Bar',
 
     
-    setBottom : function(bottom){
-        this.setStyle(BOTTOM, this.addUnits(bottom));
-        return this;
-    },
+
+    type: 'column',
+    alias: 'series.column',
+
+    column: true,
 
     
-    setXY : function(pos, animate){
-           var me = this;
-        if(!animate || !me.anim){
-            D.setXY(me.dom, pos);
-        }else{
-            me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
-        }
-        return me;
-    },
+    xPadding: 10,
 
     
-    setLocation : function(x, y, animate){
-        return this.setXY([x, y], this.animTest(arguments, animate, 2));
-    },
+    yPadding: 0
+});
+
+Ext.define('Ext.chart.series.Gauge', {
 
     
-    moveTo : function(x, y, animate){
-        return this.setXY([x, y], this.animTest(arguments, animate, 2));        
-    },    
+
+    extend: 'Ext.chart.series.Series',
+
     
+
+    type: "gauge",
+    alias: 'series.gauge',
+
+    rad: Math.PI / 180,
+
     
-    getLeft : function(local){
-           return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
-    },
+    highlightDuration: 150,
 
     
-    getRight : function(local){
-           var me = this;
-           return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
-    },
+    angleField: false,
 
     
-    getTop : function(local) {
-           return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
-    },
+    needle: false,
+    
+    
+    donut: false,
 
     
-    getBottom : function(local){
-           var me = this;
-           return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
-    },
+    showInLegend: false,
 
     
-    position : function(pos, zIndex, x, y){
-           var me = this;
-           
-        if(!pos && me.isStyle(POSITION, STATIC)){           
-            me.setStyle(POSITION, RELATIVE);           
-        } else if(pos) {
-            me.setStyle(POSITION, pos);
+    style: {},
+    
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            store = chart.store,
+            shadow = chart.shadow, i, l, cfg;
+        Ext.apply(me, config, {
+            shadowAttributes: [{
+                "stroke-width": 6,
+                "stroke-opacity": 1,
+                stroke: 'rgb(200, 200, 200)',
+                translate: {
+                    x: 1.2,
+                    y: 2
+                }
+            },
+            {
+                "stroke-width": 4,
+                "stroke-opacity": 1,
+                stroke: 'rgb(150, 150, 150)',
+                translate: {
+                    x: 0.9,
+                    y: 1.5
+                }
+            },
+            {
+                "stroke-width": 2,
+                "stroke-opacity": 1,
+                stroke: 'rgb(100, 100, 100)',
+                translate: {
+                    x: 0.6,
+                    y: 1
+                }
+            }]
+        });
+        me.group = surface.getGroup(me.seriesId);
+        if (shadow) {
+            for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+                me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+            }
         }
-        if(zIndex){
-            me.setStyle(ZINDEX, zIndex);
+        surface.customAttributes.segment = function(opt) {
+            return me.getSegment(opt);
+        };
+    },
+    
+    //@private updates some onbefore render parameters.
+
+    initialize: function() {
+        var me = this,
+            store = me.chart.getChartStore();
+        
+        me.yField = [];
+        if (me.label.field) {
+            store.each(function(rec) {
+                me.yField.push(rec.get(me.label.field));
+            });
         }
-        if(x || y) me.setXY([x || false, y || false]);
     },
 
     
-    clearPositioning : function(value){
-        value = value || '';
-        this.setStyle({
-            left : value,
-            right : value,
-            top : value,
-            bottom : value,
-            "z-index" : "",
-            position : STATIC
-        });
-        return this;
+    getSegment: function(opt) {
+        var me = this,
+            rad = me.rad,
+            cos = Math.cos,
+            sin = Math.sin,
+            abs = Math.abs,
+            x = me.centerX,
+            y = me.centerY,
+            x1 = 0, x2 = 0, x3 = 0, x4 = 0,
+            y1 = 0, y2 = 0, y3 = 0, y4 = 0,
+            delta = 1e-2,
+            r = opt.endRho - opt.startRho,
+            startAngle = opt.startAngle,
+            endAngle = opt.endAngle,
+            midAngle = (startAngle + endAngle) / 2 * rad,
+            margin = opt.margin || 0,
+            flag = abs(endAngle - startAngle) > 180,
+            a1 = Math.min(startAngle, endAngle) * rad,
+            a2 = Math.max(startAngle, endAngle) * rad,
+            singleSlice = false;
+
+        x += margin * cos(midAngle);
+        y += margin * sin(midAngle);
+
+        x1 = x + opt.startRho * cos(a1);
+        y1 = y + opt.startRho * sin(a1);
+
+        x2 = x + opt.endRho * cos(a1);
+        y2 = y + opt.endRho * sin(a1);
+
+        x3 = x + opt.startRho * cos(a2);
+        y3 = y + opt.startRho * sin(a2);
+
+        x4 = x + opt.endRho * cos(a2);
+        y4 = y + opt.endRho * sin(a2);
+
+        if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
+            singleSlice = true;
+        }
+        
+        if (singleSlice) {
+            return {
+                path: [
+                ["M", x1, y1],
+                ["L", x2, y2],
+                ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
+                ["Z"]]
+            };
+        } else {
+            return {
+                path: [
+                ["M", x1, y1],
+                ["L", x2, y2],
+                ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
+                ["L", x3, y3],
+                ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
+                ["Z"]]
+            };
+        }
     },
 
     
-    getPositioning : function(){
-        var l = this.getStyle(LEFT);
-        var t = this.getStyle(TOP);
-        return {
-            "position" : this.getStyle(POSITION),
-            "left" : l,
-            "right" : l ? "" : this.getStyle(RIGHT),
-            "top" : t,
-            "bottom" : t ? "" : this.getStyle(BOTTOM),
-            "z-index" : this.getStyle(ZINDEX)
+    calcMiddle: function(item) {
+        var me = this,
+            rad = me.rad,
+            slice = item.slice,
+            x = me.centerX,
+            y = me.centerY,
+            startAngle = slice.startAngle,
+            endAngle = slice.endAngle,
+            radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
+            donut = +me.donut,
+            a1 = Math.min(startAngle, endAngle) * rad,
+            a2 = Math.max(startAngle, endAngle) * rad,
+            midAngle = -(a1 + (a2 - a1) / 2),
+            xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
+            ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
+
+        item.middle = {
+            x: xm,
+            y: ym
         };
     },
+
     
-    
-    setPositioning : function(pc){
-           var me = this,
-               style = me.dom.style;
-               
-        me.setStyle(pc);
+    drawSeries: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            group = me.group,
+            animate = me.chart.animate,
+            axis = me.chart.axes.get(0),
+            minimum = axis && axis.minimum || me.minimum || 0,
+            maximum = axis && axis.maximum || me.maximum || 0,
+            field = me.angleField || me.field || me.xField,
+            surface = chart.surface,
+            chartBBox = chart.chartBBox,
+            rad = me.rad,
+            donut = +me.donut,
+            values = {},
+            items = [],
+            seriesStyle = me.seriesStyle,
+            seriesLabelStyle = me.seriesLabelStyle,
+            colorArrayStyle = me.colorArrayStyle,
+            colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+            gutterX = chart.maxGutter[0],
+            gutterY = chart.maxGutter[1],
+            cos = Math.cos,
+            sin = Math.sin,
+            rendererAttributes, centerX, centerY, slice, slices, sprite, value,
+            item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
+            p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
+        
+        Ext.apply(seriesStyle, me.style || {});
+
+        me.setBBox();
+        bbox = me.bbox;
+
+        
+        if (me.colorSet) {
+            colorArrayStyle = me.colorSet;
+            colorArrayLength = colorArrayStyle.length;
+        }
+        
+        
+        if (!store || !store.getCount()) {
+            return;
+        }
         
-        if(pc.right == AUTO){
-            style.right = "";
+        centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
+        centerY = me.centerY = chartBBox.y + chartBBox.height;
+        me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
+        me.slices = slices = [];
+        me.items = items = [];
+        
+        if (!me.value) {
+            record = store.getAt(0);
+            me.value = record.get(field);
         }
-        if(pc.bottom == AUTO){
-            style.bottom = "";
+        
+        value = me.value;
+        if (me.needle) {
+            sliceA = {
+                series: me,
+                value: value,
+                startAngle: -180,
+                endAngle: 0,
+                rho: me.radius
+            };
+            splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
+            slices.push(sliceA);
+        } else {
+            splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
+            sliceA = {
+                series: me,
+                value: value,
+                startAngle: -180,
+                endAngle: splitAngle,
+                rho: me.radius
+            };
+            sliceB = {
+                series: me,
+                value: me.maximum - value,
+                startAngle: splitAngle,
+                endAngle: 0,
+                rho: me.radius
+            };
+            slices.push(sliceA, sliceB);
         }
         
-        return me;
-    },    
-       
-    
-    translatePoints : function(x, y){               
-           y = isNaN(x[1]) ? y : x[1];
-        x = isNaN(x[0]) ? x : x[0];
-        var me = this,
-               relative = me.isStyle(POSITION, RELATIVE),
-               o = me.getXY(),
-               l = parseInt(me.getStyle(LEFT), 10),
-               t = parseInt(me.getStyle(TOP), 10);
         
-        l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
-        t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
+        for (i = 0, ln = slices.length; i < ln; i++) {
+            slice = slices[i];
+            sprite = group.getAt(i);
+            
+            rendererAttributes = Ext.apply({
+                segment: {
+                    startAngle: slice.startAngle,
+                    endAngle: slice.endAngle,
+                    margin: 0,
+                    rho: slice.rho,
+                    startRho: slice.rho * +donut / 100,
+                    endRho: slice.rho
+                } 
+            }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
+
+            item = Ext.apply({},
+            rendererAttributes.segment, {
+                slice: slice,
+                series: me,
+                storeItem: record,
+                index: i
+            });
+            items[i] = item;
+            
+            if (!sprite) {
+                spriteOptions = Ext.apply({
+                    type: "path",
+                    group: group
+                }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
+                sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
+            }
+            slice.sprite = slice.sprite || [];
+            item.sprite = sprite;
+            slice.sprite.push(sprite);
+            if (animate) {
+                rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
+                sprite._to = rendererAttributes;
+                me.onAnimate(sprite, {
+                    to: rendererAttributes
+                });
+            } else {
+                rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
+                    hidden: false
+                }), i, store);
+                sprite.setAttributes(rendererAttributes, true);
+            }
+        }
+        
+        if (me.needle) {
+            splitAngle = splitAngle * Math.PI / 180;
+            
+            if (!me.needleSprite) {
+                me.needleSprite = me.chart.surface.add({
+                    type: 'path',
+                    path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
+                                centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
+                           'L', centerX + me.radius * cos(splitAngle),
+                                centerY + -Math.abs(me.radius * sin(splitAngle))],
+                    'stroke-width': 4,
+                    'stroke': '#222'
+                });
+            } else {
+                if (animate) {
+                    me.onAnimate(me.needleSprite, {
+                        to: {
+                        path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
+                                    centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
+                               'L', centerX + me.radius * cos(splitAngle),
+                                    centerY + -Math.abs(me.radius * sin(splitAngle))]
+                        }
+                    });
+                } else {
+                    me.needleSprite.setAttributes({
+                        type: 'path',
+                        path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
+                                    centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
+                               'L', centerX + me.radius * cos(splitAngle),
+                                    centerY + -Math.abs(me.radius * sin(splitAngle))]
+                    });
+                }
+            }
+            me.needleSprite.setAttributes({
+                hidden: false    
+            }, true);
+        }
+        
+        delete me.value;
+    },
+    
+    
+    setValue: function (value) {
+        this.value = value;
+        this.drawSeries();
+    },
+
+    
+    onCreateLabel: function(storeItem, item, i, display) {},
+
+    
+    onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
+
+    
+    onPlaceCallout: function() {},
+
+    
+    onAnimate: function(sprite, attr) {
+        sprite.show();
+        return this.callParent(arguments);
+    },
 
-        return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
+    isItemInPoint: function(x, y, item, i) {
+        return false;
     },
     
-    animTest : function(args, animate, i) {
-        return !!animate && this.preanim ? this.preanim(args, i) : false;
-    }
-});
-})();
-Ext.Element.addMethods({
     
-    setBox : function(box, adjust, animate){
-        var me = this,
-               w = box.width, 
-               h = box.height;
-        if((adjust && !me.autoBoxAdjust) && !me.isBorderBox()){
-           w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
-           h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+    showAll: function() {
+        if (!isNaN(this._index)) {
+            this.__excludes[this._index] = false;
+            this.drawSeries();
         }
-        me.setBounds(box.x, box.y, w, h, me.animTest.call(me, arguments, animate, 2));
-        return me;
     },
+    
+    
+    getLegendColor: function(index) {
+        var me = this;
+        return me.colorArrayStyle[index % me.colorArrayStyle.length];
+    }
+});
+
+
+
+Ext.define('Ext.chart.series.Line', {
 
     
-       getBox : function(contentBox, local) {      
-           var me = this,
-               xy,
-               left,
-               top,
-               getBorderWidth = me.getBorderWidth,
-               getPadding = me.getPadding, 
-               l,
-               r,
-               t,
-               b;
-        if(!local){
-            xy = me.getXY();
-        }else{
-            left = parseInt(me.getStyle("left"), 10) || 0;
-            top = parseInt(me.getStyle("top"), 10) || 0;
-            xy = [left, top];
-        }
-        var el = me.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
-        if(!contentBox){
-            bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
-        }else{
-            l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
-            r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
-            t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
-            b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
-            bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
-        }
-        bx.right = bx.x + bx.width;
-        bx.bottom = bx.y + bx.height;
-        return bx;
-       },
-       
-    
-     move : function(direction, distance, animate){
-        var me = this,         
-               xy = me.getXY(),
-               x = xy[0],
-               y = xy[1],              
-               left = [x - distance, y],
-               right = [x + distance, y],
-               top = [x, y - distance],
-               bottom = [x, y + distance],
-               hash = {
-                       l :     left,
-                       left : left,
-                       r : right,
-                       right : right,
-                       t : top,
-                       top : top,
-                       up : top,
-                       b : bottom, 
-                       bottom : bottom,
-                       down : bottom                           
-               };
-        
-           direction = direction.toLowerCase();    
-           me.moveTo(hash[direction][0], hash[direction][1], me.animTest.call(me, arguments, animate, 2));
-    },
-    
-    
-     setLeftTop : function(left, top){
-           var me = this,
-               style = me.dom.style;
-        style.left = me.addUnits(left);
-        style.top = me.addUnits(top);
-        return me;
-    },
+
+    extend: 'Ext.chart.series.Cartesian',
+
+    alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
+
+    requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
+
     
+
+    type: 'line',
+
+    alias: 'series.line',
+
     
-    getRegion : function(){
-        return Ext.lib.Dom.getRegion(this.dom);
-    },
+
     
+    selectionTolerance: 20,
+
     
-    setBounds : function(x, y, width, height, animate){
-           var me = this;
-        if (!animate || !me.anim) {
-            me.setSize(width, height);
-            me.setLocation(x, y);
-        } else {
-            me.anim({points: {to: [x, y]}, 
-                        width: {to: me.adjustWidth(width)}, 
-                        height: {to: me.adjustHeight(height)}},
-                     me.preanim(arguments, 4), 
-                     'motion');
-        }
-        return me;
-    },
+    showMarkers: true,
 
     
-    setRegion : function(region, animate) {
-        return this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.animTest.call(this, arguments, animate, 1));
-    }
-});
-Ext.Element.addMethods({
+    markerConfig: {},
+
     
-    isScrollable : function(){
-        var dom = this.dom;
-        return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
-    },
+    style: {},
 
     
-    scrollTo : function(side, value){
-        this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
-        return this;
-    },
+    smooth: false,
 
     
-    getScroll : function(){
-        var d = this.dom, 
-            doc = document,
-            body = doc.body,
-            docElement = doc.documentElement,
-            l,
-            t,
-            ret;
+    defaultSmoothness: 3,
 
-        if(d == doc || d == body){
-            if(Ext.isIE && Ext.isStrict){
-                l = docElement.scrollLeft; 
-                t = docElement.scrollTop;
-            }else{
-                l = window.pageXOffset;
-                t = window.pageYOffset;
+    
+    fill: false,
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            surface = me.chart.surface,
+            shadow = me.chart.shadow,
+            i, l;
+        Ext.apply(me, config, {
+            highlightCfg: {
+                'stroke-width': 3
+            },
+            shadowAttributes: [{
+                "stroke-width": 6,
+                "stroke-opacity": 0.05,
+                stroke: 'rgb(0, 0, 0)',
+                translate: {
+                    x: 1,
+                    y: 1
+                }
+            }, {
+                "stroke-width": 4,
+                "stroke-opacity": 0.1,
+                stroke: 'rgb(0, 0, 0)',
+                translate: {
+                    x: 1,
+                    y: 1
+                }
+            }, {
+                "stroke-width": 2,
+                "stroke-opacity": 0.15,
+                stroke: 'rgb(0, 0, 0)',
+                translate: {
+                    x: 1,
+                    y: 1
+                }
+            }]
+        });
+        me.group = surface.getGroup(me.seriesId);
+        if (me.showMarkers) {
+            me.markerGroup = surface.getGroup(me.seriesId + '-markers');
+        }
+        if (shadow) {
+            for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+                me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
             }
-            ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
-        }else{
-            ret = {left: d.scrollLeft, top: d.scrollTop};
         }
-        return ret;
-    }
-});
-Ext.Element.addMethods({
+    },
+
     
-    scrollTo : function(side, value, animate) {
+    shrink: function(xValues, yValues, size) {
         
-        var top = /top/i.test(side),
-            me = this,
-            dom = me.dom,
-            prop;
-        if (!animate || !me.anim) {
-            
-            prop = 'scroll' + (top ? 'Top' : 'Left');
-            dom[prop] = value;
-        }
-        else {
-            
-            prop = 'scroll' + (top ? 'Left' : 'Top');
-            me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}}, me.preanim(arguments, 2), 'scroll');
+        var len = xValues.length,
+            ratio = Math.floor(len / size),
+            i = 1,
+            xSum = 0,
+            ySum = 0,
+            xRes = [xValues[0]],
+            yRes = [yValues[0]];
+
+        for (; i < len; ++i) {
+            xSum += xValues[i] || 0;
+            ySum += yValues[i] || 0;
+            if (i % ratio == 0) {
+                xRes.push(xSum/ratio);
+                yRes.push(ySum/ratio);
+                xSum = 0;
+                ySum = 0;
+            }
         }
-        return me;
+        return {
+            x: xRes,
+            y: yRes
+        };
     },
+
     
-    
-    scrollIntoView : function(container, hscroll) {
-        var c = Ext.getDom(container) || Ext.getBody().dom,
-            el = this.dom,
-            o = this.getOffsetsTo(c),
-            l = o[0] + c.scrollLeft,
-            t = o[1] + c.scrollTop,
-            b = t + el.offsetHeight,
-            r = l + el.offsetWidth,
-            ch = c.clientHeight,
-            ct = parseInt(c.scrollTop, 10),
-            cl = parseInt(c.scrollLeft, 10),
-            cb = ct + ch,
-            cr = cl + c.clientWidth;
+    drawSeries: function() {
+        var me = this,
+            chart = me.chart,
+            chartAxes = chart.axes,
+            store = chart.getChartStore(),
+            storeCount = store.getCount(),
+            surface = me.chart.surface,
+            bbox = {},
+            group = me.group,
+            showMarkers = me.showMarkers,
+            markerGroup = me.markerGroup,
+            enableShadows = chart.shadow,
+            shadowGroups = me.shadowGroups,
+            shadowAttributes = me.shadowAttributes,
+            smooth = me.smooth,
+            lnsh = shadowGroups.length,
+            dummyPath = ["M"],
+            path = ["M"],
+            renderPath = ["M"],
+            smoothPath = ["M"],
+            markerIndex = chart.markerIndex,
+            axes = [].concat(me.axis),
+            shadowBarAttr,
+            xValues = [],
+            xValueMap = {},
+            yValues = [],
+            yValueMap = {},
+            onbreak = false,
+            storeIndices = [],
+            markerStyle = me.markerStyle,
+            seriesStyle = me.style,
+            colorArrayStyle = me.colorArrayStyle,
+            colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+            isNumber = Ext.isNumber,
+            seriesIdx = me.seriesIdx, 
+            boundAxes = me.getAxesForXAndYFields(),
+            boundXAxis = boundAxes.xAxis,
+            boundYAxis = boundAxes.yAxis,
+            shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
+            x, y, prevX, prevY, firstX, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
+            yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
+            endLineStyle, type, count, items;
+
+        if (me.fireEvent('beforedraw', me) === false) {
+            return;
+        }
 
-        if (el.offsetHeight > ch || t < ct) {
-            c.scrollTop = t;
+        
+        if (!storeCount || me.seriesIsHidden) {
+            items = this.items;
+            if (items) {
+                for (i = 0, ln = items.length; i < ln; ++i) {
+                    if (items[i].sprite) {
+                        items[i].sprite.hide(true);
+                    }
+                }
+            }
+            return;
         }
-        else if (b > cb) {
-            c.scrollTop = b-ch;
+
+        
+        endMarkerStyle = Ext.apply(markerStyle || {}, me.markerConfig);
+        type = endMarkerStyle.type;
+        delete endMarkerStyle.type;
+        endLineStyle = seriesStyle;
+        
+        
+        if (!endLineStyle['stroke-width']) {
+            endLineStyle['stroke-width'] = 0.5;
         }
         
-        c.scrollTop = c.scrollTop;
-
-        if (hscroll !== false) {
-            if (el.offsetWidth > c.clientWidth || l < cl) {
-                c.scrollLeft = l;
-            }
-            else if (r > cr) {
-                c.scrollLeft = r - c.clientWidth;
+        
+        if (markerIndex && markerGroup && markerGroup.getCount()) {
+            for (i = 0; i < markerIndex; i++) {
+                marker = markerGroup.getAt(i);
+                markerGroup.remove(marker);
+                markerGroup.add(marker);
+                markerAux = markerGroup.getAt(markerGroup.getCount() - 2);
+                marker.setAttributes({
+                    x: 0,
+                    y: 0,
+                    translate: {
+                        x: markerAux.attr.translation.x,
+                        y: markerAux.attr.translation.y
+                    }
+                }, true);
             }
-            c.scrollLeft = c.scrollLeft;
         }
-        return this;
-    },
 
-    
-    scrollChildIntoView : function(child, hscroll) {
-        Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
-    },
-    
-    
-     scroll : function(direction, distance, animate) {
-        if (!this.isScrollable()) {
-            return false;
+        me.unHighlightItem();
+        me.cleanHighlights();
+
+        me.setBBox();
+        bbox = me.bbox;
+        me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height];
+        for (i = 0, ln = axes.length; i < ln; i++) {
+            axis = chartAxes.get(axes[i]);
+            if (axis) {
+                ends = axis.calcEnds();
+                if (axis.position == 'top' || axis.position == 'bottom') {
+                    minX = ends.from;
+                    maxX = ends.to;
+                }
+                else {
+                    minY = ends.from;
+                    maxY = ends.to;
+                }
+            }
         }
-        var el = this.dom,
-            l = el.scrollLeft, t = el.scrollTop,
-            w = el.scrollWidth, h = el.scrollHeight,
-            cw = el.clientWidth, ch = el.clientHeight,
-            scrolled = false, v,
-            hash = {
-                l: Math.min(l + distance, w-cw),
-                r: v = Math.max(l - distance, 0),
-                t: Math.max(t - distance, 0),
-                b: Math.min(t + distance, h-ch)
-            };
-            hash.d = hash.b;
-            hash.u = hash.t;
         
-        direction = direction.substr(0, 1);
-        if ((v = hash[direction]) > -1) {
-            scrolled = true;
-            this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.preanim(arguments, 2));
+        
+        
+        if (me.xField && !isNumber(minX) &&
+            (boundXAxis == 'bottom' || boundXAxis == 'top') && 
+            !chartAxes.get(boundXAxis)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.xField)
+            }).calcEnds();
+            minX = axis.from;
+            maxX = axis.to;
+        }
+        if (me.yField && !isNumber(minY) &&
+            (boundYAxis == 'right' || boundYAxis == 'left') &&
+            !chartAxes.get(boundYAxis)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.yField)
+            }).calcEnds();
+            minY = axis.from;
+            maxY = axis.to;
+        }
+        if (isNaN(minX)) {
+            minX = 0;
+            xScale = bbox.width / ((storeCount - 1) || 1);
+        }
+        else {
+            xScale = bbox.width / ((maxX - minX) || (storeCount -1) || 1);
         }
-        return scrolled;
-    }
-});
 
-Ext.Element.VISIBILITY = 1;
+        if (isNaN(minY)) {
+            minY = 0;
+            yScale = bbox.height / ((storeCount - 1) || 1);
+        }
+        else {
+            yScale = bbox.height / ((maxY - minY) || (storeCount - 1) || 1);
+        }
 
-Ext.Element.DISPLAY = 2;
+        
+        me.eachRecord(function(record, i) {
+            xValue = record.get(me.xField);
 
-Ext.Element.addMethods(function(){
-    var VISIBILITY = "visibility",
-        DISPLAY = "display",
-        HIDDEN = "hidden",
-        OFFSETS = "offsets",
-        NONE = "none",
-        ORIGINALDISPLAY = 'originalDisplay',
-        VISMODE = 'visibilityMode',
-        ELDISPLAY = Ext.Element.DISPLAY,
-        data = Ext.Element.data,
-        getDisplay = function(dom){
-            var d = data(dom, ORIGINALDISPLAY);
-            if(d === undefined){
-                data(dom, ORIGINALDISPLAY, d = '');
+            
+            if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)
+                
+                || boundXAxis && chartAxes.get(boundXAxis) && chartAxes.get(boundXAxis).type == 'Category') {
+                    if (xValue in xValueMap) {
+                        xValue = xValueMap[xValue];
+                    } else {
+                        xValue = xValueMap[xValue] = i;
+                    }
             }
-            return d;
-        },
-        getVisMode = function(dom){
-            var m = data(dom, VISMODE);
-            if(m === undefined){
-                data(dom, VISMODE, m = 1);
+
+            
+            yValue = record.get(me.yField);
+            
+            if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
+                return;
             }
-            return m;
-        };
+            
+            if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)
+                
+                || boundYAxis && chartAxes.get(boundYAxis) && chartAxes.get(boundYAxis).type == 'Category') {
+                yValue = i;
+            }
+            storeIndices.push(i);
+            xValues.push(xValue);
+            yValues.push(yValue);
+        });
 
-    return {
-        
-        originalDisplay : "",
-        visibilityMode : 1,
+        ln = xValues.length;
+        if (ln > bbox.width) {
+            coords = me.shrink(xValues, yValues, bbox.width);
+            xValues = coords.x;
+            yValues = coords.y;
+        }
 
-        
-        setVisibilityMode : function(visMode){
-            data(this.dom, VISMODE, visMode);
-            return this;
-        },
+        me.items = [];
 
-        
-        animate : function(args, duration, onComplete, easing, animType){
-            this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
-            return this;
-        },
+        count = 0;
+        ln = xValues.length;
+        for (i = 0; i < ln; i++) {
+            xValue = xValues[i];
+            yValue = yValues[i];
+            if (yValue === false) {
+                if (path.length == 1) {
+                    path = [];
+                }
+                onbreak = true;
+                me.items.push(false);
+                continue;
+            } else {
+                x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
+                y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(2);
+                if (onbreak) {
+                    onbreak = false;
+                    path.push('M');
+                }
+                path = path.concat([x, y]);
+            }
+            if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) {
+                firstY = y;
+                firstX = x;
+            }
+            
+            if (!me.line || chart.resizing) {
+                dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]);
+            }
 
-        
-        anim : function(args, opt, animType, defaultDur, defaultEase, cb){
-            animType = animType || 'run';
-            opt = opt || {};
-            var me = this,
-                anim = Ext.lib.Anim[animType](
-                    me.dom,
-                    args,
-                    (opt.duration || defaultDur) || .35,
-                    (opt.easing || defaultEase) || 'easeOut',
-                    function(){
-                        if(cb) cb.call(me);
-                        if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
-                    },
-                    me
-                );
-            opt.anim = anim;
-            return anim;
-        },
+            
+            if (chart.animate && chart.resizing && me.line) {
+                me.line.setAttributes({
+                    path: dummyPath
+                }, true);
+                if (me.fillPath) {
+                    me.fillPath.setAttributes({
+                        path: dummyPath,
+                        opacity: 0.2
+                    }, true);
+                }
+                if (me.line.shadows) {
+                    shadows = me.line.shadows;
+                    for (j = 0, lnsh = shadows.length; j < lnsh; j++) {
+                        shadow = shadows[j];
+                        shadow.setAttributes({
+                            path: dummyPath
+                        }, true);
+                    }
+                }
+            }
+            if (showMarkers) {
+                marker = markerGroup.getAt(count++);
+                if (!marker) {
+                    marker = Ext.chart.Shape[type](surface, Ext.apply({
+                        group: [group, markerGroup],
+                        x: 0, y: 0,
+                        translate: {
+                            x: +(prevX || x),
+                            y: prevY || (bbox.y + bbox.height / 2)
+                        },
+                        value: '"' + xValue + ', ' + yValue + '"',
+                        zIndex: 4000
+                    }, endMarkerStyle));
+                    marker._to = {
+                        translate: {
+                            x: +x,
+                            y: +y
+                        }
+                    };
+                } else {
+                    marker.setAttributes({
+                        value: '"' + xValue + ', ' + yValue + '"',
+                        x: 0, y: 0,
+                        hidden: false
+                    }, true);
+                    marker._to = {
+                        translate: {
+                            x: +x, 
+                            y: +y
+                        }
+                    };
+                }
+            }
+            me.items.push({
+                series: me,
+                value: [xValue, yValue],
+                point: [x, y],
+                sprite: marker,
+                storeItem: store.getAt(storeIndices[i])
+            });
+            prevX = x;
+            prevY = y;
+        }
 
-        
-        preanim : function(a, i){
-            return !a[i] ? false : (typeof a[i] == 'object' ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
-        },
+        if (path.length <= 1) {
+            
+            return;
+        }
+
+        if (me.smooth) {
+            smoothPath = Ext.draw.Draw.smooth(path, isNumber(smooth) ? smooth : me.defaultSmoothness);
+        }
+
+        renderPath = smooth ? smoothPath : path;
 
         
-        isVisible : function() {
-            return !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE);
-        },
+        if (chart.markerIndex && me.previousPath) {
+            fromPath = me.previousPath;
+            if (!smooth) {
+                Ext.Array.erase(fromPath, 1, 2);
+            }
+        } else {
+            fromPath = path;
+        }
 
         
-         setVisible : function(visible, animate){
-            var me = this, isDisplay, isVisible, isOffsets,
-                dom = me.dom;
+        if (!me.line) {
+            me.line = surface.add(Ext.apply({
+                type: 'path',
+                group: group,
+                path: dummyPath,
+                stroke: endLineStyle.stroke || endLineStyle.fill
+            }, endLineStyle || {}));
+
+            if (enableShadows) {
+                me.line.setAttributes(Ext.apply({}, me.shadowOptions), true);
+            }
 
             
-            if (typeof animate == 'string'){
-                isDisplay = animate == DISPLAY;
-                isVisible = animate == VISIBILITY;
-                isOffsets = animate == OFFSETS;
-                animate = false;
+            me.line.setAttributes({
+                fill: 'none',
+                zIndex: 3000
+            });
+            if (!endLineStyle.stroke && colorArrayLength) {
+                me.line.setAttributes({
+                    stroke: colorArrayStyle[seriesIdx % colorArrayLength]
+                }, true);
+            }
+            if (enableShadows) {
+                
+                shadows = me.line.shadows = [];
+                for (shindex = 0; shindex < lnsh; shindex++) {
+                    shadowBarAttr = shadowAttributes[shindex];
+                    shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath });
+                    shadow = surface.add(Ext.apply({}, {
+                        type: 'path',
+                        group: shadowGroups[shindex]
+                    }, shadowBarAttr));
+                    shadows.push(shadow);
+                }
+            }
+        }
+        if (me.fill) {
+            fillPath = renderPath.concat([
+                ["L", x, bbox.y + bbox.height],
+                ["L", firstX, bbox.y + bbox.height],
+                ["L", firstX, firstY]
+            ]);
+            if (!me.fillPath) {
+                me.fillPath = surface.add({
+                    group: group,
+                    type: 'path',
+                    opacity: endLineStyle.opacity || 0.3,
+                    fill: endLineStyle.fill || colorArrayStyle[seriesIdx % colorArrayLength],
+                    path: dummyPath
+                });
+            }
+        }
+        markerCount = showMarkers && markerGroup.getCount();
+        if (chart.animate) {
+            fill = me.fill;
+            line = me.line;
+            
+            rendererAttributes = me.renderer(line, false, { path: renderPath }, i, store);
+            Ext.apply(rendererAttributes, endLineStyle || {}, {
+                stroke: endLineStyle.stroke || endLineStyle.fill
+            });
+            
+            delete rendererAttributes.fill;
+            line.show(true);
+            if (chart.markerIndex && me.previousPath) {
+                me.animation = animation = me.onAnimate(line, {
+                    to: rendererAttributes,
+                    from: {
+                        path: fromPath
+                    }
+                });
             } else {
-                isDisplay = getVisMode(this.dom) == ELDISPLAY;
-                isVisible = !isDisplay;
+                me.animation = animation = me.onAnimate(line, {
+                    to: rendererAttributes
+                });
+            }
+            
+            if (enableShadows) {
+                shadows = line.shadows;
+                for(j = 0; j < lnsh; j++) {
+                    shadows[j].show(true);
+                    if (chart.markerIndex && me.previousPath) {
+                        me.onAnimate(shadows[j], {
+                            to: { path: renderPath },
+                            from: { path: fromPath }
+                        });
+                    } else {
+                        me.onAnimate(shadows[j], {
+                            to: { path: renderPath }
+                        });
+                    }
+                }
             }
+            
+            if (fill) {
+                me.fillPath.show(true);
+                me.onAnimate(me.fillPath, {
+                    to: Ext.apply({}, {
+                        path: fillPath,
+                        fill: endLineStyle.fill || colorArrayStyle[seriesIdx % colorArrayLength],
+                        'stroke-width': 0
+                    }, endLineStyle || {})
+                });
+            }
+            
+            if (showMarkers) {
+                count = 0;
+                for(i = 0; i < ln; i++) {
+                    if (me.items[i]) {
+                        item = markerGroup.getAt(count++);
+                        if (item) {
+                            rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
+                            me.onAnimate(item, {
+                                to: Ext.apply(rendererAttributes, endMarkerStyle || {})
+                            });
+                            item.show(true);
+                        }
+                    }
+                }
+                for(; count < markerCount; count++) {
+                    item = markerGroup.getAt(count);
+                    item.hide(true);
+                }
 
-            if (!animate || !me.anim) {
-                if (isDisplay){
-                    me.setDisplayed(visible);
-                } else if (isOffsets){
-                    if (!visible){
-                        me.hideModeStyles = {
-                            position: me.getStyle('position'),
-                            top: me.getStyle('top'),
-                            left: me.getStyle('left')
-                        };
 
-                        me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
-                    } else {
-                        me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
+
+
+            }
+        } else {
+            rendererAttributes = me.renderer(me.line, false, { path: renderPath, hidden: false }, i, store);
+            Ext.apply(rendererAttributes, endLineStyle || {}, {
+                stroke: endLineStyle.stroke || endLineStyle.fill
+            });
+            
+            delete rendererAttributes.fill;
+            me.line.setAttributes(rendererAttributes, true);
+            
+            if (enableShadows) {
+                shadows = me.line.shadows;
+                for(j = 0; j < lnsh; j++) {
+                    shadows[j].setAttributes({
+                        path: renderPath,
+                        hidden: false
+                    }, true);
+                }
+            }
+            if (me.fill) {
+                me.fillPath.setAttributes({
+                    path: fillPath,
+                    hidden: false
+                }, true);
+            }
+            if (showMarkers) {
+                count = 0;
+                for(i = 0; i < ln; i++) {
+                    if (me.items[i]) {
+                        item = markerGroup.getAt(count++);
+                        if (item) {
+                            rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
+                            item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true);
+                            item.show(true);
+                        }
                     }
-                }else{
-                    me.fixDisplay();
-                    dom.style.visibility = visible ? "visible" : HIDDEN;
                 }
-            }else{
-                
-                if (visible){
-                    me.setOpacity(.01);
-                    me.setVisible(true);
+                for(; count < markerCount; count++) {
+                    item = markerGroup.getAt(count);
+                    item.hide(true);
                 }
-                me.anim({opacity: { to: (visible?1:0) }},
-                        me.preanim(arguments, 1),
-                        null,
-                        .35,
-                        'easeIn',
-                        function(){
-                             if(!visible){
-                                 dom.style[isDisplay ? DISPLAY : VISIBILITY] = (isDisplay) ? NONE : HIDDEN;
-                                 Ext.fly(dom).setOpacity(1);
-                             }
-                        });
             }
-            return me;
-        },
+        }
+
+        if (chart.markerIndex) {
+            if (me.smooth) {
+                Ext.Array.erase(path, 1, 2);
+            } else {
+                Ext.Array.splice(path, 1, 0, path[1], path[2]);
+            }
+            me.previousPath = path;
+        }
+        me.renderLabels();
+        me.renderCallouts();
+
+        me.fireEvent('draw', me);
+    },
+
+    
+    onCreateLabel: function(storeItem, item, i, display) {
+        var me = this,
+            group = me.labelsGroup,
+            config = me.label,
+            bbox = me.bbox,
+            endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
+
+        return me.chart.surface.add(Ext.apply({
+            'type': 'text',
+            'text-anchor': 'middle',
+            'group': group,
+            'x': item.point[0],
+            'y': bbox.y + bbox.height / 2
+        }, endLabelStyle || {}));
+    },
+
+    
+    onPlaceLabel: function(label, storeItem, item, i, display, animate) {
+        var me = this,
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.label,
+            format = config.renderer,
+            field = config.field,
+            bbox = me.bbox,
+            x = item.point[0],
+            y = item.point[1],
+            radius = item.sprite.attr.radius,
+            bb, width, height;
+
+        label.setAttributes({
+            text: format(storeItem.get(field)),
+            hidden: true
+        }, true);
+
+        if (display == 'rotate') {
+            label.setAttributes({
+                'text-anchor': 'start',
+                'rotation': {
+                    x: x,
+                    y: y,
+                    degrees: -45
+                }
+            }, true);
+            
+            bb = label.getBBox();
+            width = bb.width;
+            height = bb.height;
+            x = x < bbox.x? bbox.x : x;
+            x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
+            y = (y - height < bbox.y)? bbox.y + height : y;
+
+        } else if (display == 'under' || display == 'over') {
+            
+            bb = item.sprite.getBBox();
+            bb.width = bb.width || (radius * 2);
+            bb.height = bb.height || (radius * 2);
+            y = y + (display == 'over'? -bb.height : bb.height);
+            
+            bb = label.getBBox();
+            width = bb.width/2;
+            height = bb.height/2;
+            x = x - width < bbox.x? bbox.x + width : x;
+            x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+            y = y - height < bbox.y? bbox.y + height : y;
+            y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+        }
+
+        if (me.chart.animate && !me.chart.resizing) {
+            label.show(true);
+            me.onAnimate(label, {
+                to: {
+                    x: x,
+                    y: y
+                }
+            });
+        } else {
+            label.setAttributes({
+                x: x,
+                y: y
+            }, true);
+            if (resizing && me.animation) {
+                me.animation.on('afteranimate', function() {
+                    label.show(true);
+                });
+            } else {
+                label.show(true);
+            }
+        }
+    },
+
+    //@private Overriding highlights.js highlightItem method.
+
+    highlightItem: function() {
+        var me = this;
+        me.callParent(arguments);
+        if (me.line && !me.highlighted) {
+            if (!('__strokeWidth' in me.line)) {
+                me.line.__strokeWidth = me.line.attr['stroke-width'] || 0;
+            }
+            if (me.line.__anim) {
+                me.line.__anim.paused = true;
+            }
+            me.line.__anim = Ext.create('Ext.fx.Anim', {
+                target: me.line,
+                to: {
+                    'stroke-width': me.line.__strokeWidth + 3
+                }
+            });
+            me.highlighted = true;
+        }
+    },
+
+    //@private Overriding highlights.js unHighlightItem method.
+
+    unHighlightItem: function() {
+        var me = this;
+        me.callParent(arguments);
+        if (me.line && me.highlighted) {
+            me.line.__anim = Ext.create('Ext.fx.Anim', {
+                target: me.line,
+                to: {
+                    'stroke-width': me.line.__strokeWidth
+                }
+            });
+            me.highlighted = false;
+        }
+    },
+
+    //@private called when a callout needs to be placed.
+
+    onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
+        if (!display) {
+            return;
+        }
+
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            resizing = chart.resizing,
+            config = me.callouts,
+            items = me.items,
+            prev = i == 0? false : items[i -1].point,
+            next = (i == items.length -1)? false : items[i +1].point,
+            cur = [+item.point[0], +item.point[1]],
+            dir, norm, normal, a, aprev, anext,
+            offsetFromViz = config.offsetFromViz || 30,
+            offsetToSide = config.offsetToSide || 10,
+            offsetBox = config.offsetBox || 3,
+            boxx, boxy, boxw, boxh,
+            p, clipRect = me.clipRect,
+            bbox = {
+                width: config.styles.width || 10,
+                height: config.styles.height || 10
+            },
+            x, y;
 
         
-        toggle : function(animate){
-            var me = this;
-            me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
-            return me;
-        },
+        if (!prev) {
+            prev = cur;
+        }
+        if (!next) {
+            next = cur;
+        }
+        a = (next[1] - prev[1]) / (next[0] - prev[0]);
+        aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
+        anext = (next[1] - cur[1]) / (next[0] - cur[0]);
+
+        norm = Math.sqrt(1 + a * a);
+        dir = [1 / norm, a / norm];
+        normal = [-dir[1], dir[0]];
 
         
-        setDisplayed : function(value) {
-            if(typeof value == "boolean"){
-               value = value ? getDisplay(this.dom) : NONE;
-            }
-            this.setStyle(DISPLAY, value);
-            return this;
-        },
+        if (aprev > 0 && anext < 0 && normal[1] < 0
+            || aprev < 0 && anext > 0 && normal[1] > 0) {
+            normal[0] *= -1;
+            normal[1] *= -1;
+        } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0
+                   || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
+            normal[0] *= -1;
+            normal[1] *= -1;
+        }
+        
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
         
-        fixDisplay : function(){
-            var me = this;
-            if(me.isStyle(DISPLAY, NONE)){
-                me.setStyle(VISIBILITY, HIDDEN);
-                me.setStyle(DISPLAY, getDisplay(this.dom)); 
-                if(me.isStyle(DISPLAY, NONE)){ 
-                    me.setStyle(DISPLAY, "block");
-                }
-            }
-        },
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
         
-        hide : function(animate){
-            
-            if (typeof animate == 'string'){
-                this.setVisible(false, animate);
-                return this;
-            }
-            this.setVisible(false, this.preanim(arguments, 0));
-            return this;
-        },
+        
+        if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+            normal[0] *= -1;
+        }
+        if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+            normal[1] *= -1;
+        }
 
         
-        show : function(animate){
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
+
+        
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
+
+        if (chart.animate) {
             
-            if (typeof animate == 'string'){
-                this.setVisible(true, animate);
-                return this;
+            me.onAnimate(callout.lines, {
+                to: {
+                    path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+                }
+            });
+            
+            if (callout.panel) {
+                callout.panel.setPosition(boxx, boxy, true);
             }
-            this.setVisible(true, this.preanim(arguments, 0));
-            return this;
         }
-    };
-}());
-
-Ext.Element.addMethods(
-function(){
-    var VISIBILITY = "visibility",
-        DISPLAY = "display",
-        HIDDEN = "hidden",
-        NONE = "none",
-           XMASKED = "x-masked",
-               XMASKEDRELATIVE = "x-masked-relative",
-        data = Ext.Element.data;
+        else {
+            
+            callout.lines.setAttributes({
+                path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+            }, true);
+            
+            if (callout.panel) {
+                callout.panel.setPosition(boxx, boxy);
+            }
+        }
+        for (p in callout) {
+            callout[p].show(true);
+        }
+    },
 
-       return {
-               
-           isVisible : function(deep) {
-               var vis = !this.isStyle(VISIBILITY,HIDDEN) && !this.isStyle(DISPLAY,NONE),
-                       p = this.dom.parentNode;
-               if(deep !== true || !vis){
-                   return vis;
-               }
-               while(p && !/^body/i.test(p.tagName)){
-                   if(!Ext.fly(p, '_isVisible').isVisible()){
-                       return false;
-                   }
-                   p = p.parentNode;
-               }
-               return true;
-           },
-
-           
-           isDisplayed : function() {
-               return !this.isStyle(DISPLAY, NONE);
-           },
+    isItemInPoint: function(x, y, item, i) {
+        var me = this,
+            items = me.items,
+            tolerance = me.selectionTolerance,
+            result = null,
+            prevItem,
+            nextItem,
+            prevPoint,
+            nextPoint,
+            ln,
+            x1,
+            y1,
+            x2,
+            y2,
+            xIntersect,
+            yIntersect,
+            dist1, dist2, dist, midx, midy,
+            sqrt = Math.sqrt, abs = Math.abs;
+
+        nextItem = items[i];
+        prevItem = i && items[i - 1];
+
+        if (i >= ln) {
+            prevItem = items[ln - 1];
+        }
+        prevPoint = prevItem && prevItem.point;
+        nextPoint = nextItem && nextItem.point;
+        x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance;
+        y1 = prevItem ? prevPoint[1] : nextPoint[1];
+        x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance;
+        y2 = nextItem ? nextPoint[1] : prevPoint[1];
+        dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
+        dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
+        dist = Math.min(dist1, dist2);
+
+        if (dist <= tolerance) {
+            return dist == dist1? prevItem : nextItem;
+        }
+        return false;
+    },
 
-               
-           enableDisplayMode : function(display){
-               this.setVisibilityMode(Ext.Element.DISPLAY);
-               if(!Ext.isEmpty(display)){
-                data(this.dom, 'originalDisplay', display);
+    
+    toggleAll: function(show) {
+        var me = this,
+            i, ln, shadow, shadows;
+        if (!show) {
+            Ext.chart.series.Cartesian.prototype.hideAll.call(me);
+        }
+        else {
+            Ext.chart.series.Cartesian.prototype.showAll.call(me);
+        }
+        if (me.line) {
+            me.line.setAttributes({
+                hidden: !show
+            }, true);
+            
+            if (me.line.shadows) {
+                for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) {
+                    shadow = shadows[i];
+                    shadow.setAttributes({
+                        hidden: !show
+                    }, true);
+                }
             }
-               return this;
-           },
+        }
+        if (me.fillPath) {
+            me.fillPath.setAttributes({
+                hidden: !show
+            }, true);
+        }
+    },
 
-               
-           mask : function(msg, msgCls){
-                   var me = this,
-                       dom = me.dom,
-                       dh = Ext.DomHelper,
-                       EXTELMASKMSG = "ext-el-mask-msg",
-                el,
-                mask;
-
-               if(!/^body/i.test(dom.tagName) && me.getStyle('position') == 'static'){
-                   me.addClass(XMASKEDRELATIVE);
-               }
-               if((el = data(dom, 'maskMsg'))){
-                   el.remove();
-               }
-               if((el = data(dom, 'mask'))){
-                   el.remove();
-               }
-
-            mask = dh.append(dom, {cls : "ext-el-mask"}, true);
-               data(dom, 'mask', mask);
-
-               me.addClass(XMASKED);
-               mask.setDisplayed(true);
-               if(typeof msg == 'string'){
-                var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
-                data(dom, 'maskMsg', mm);
-                   mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
-                   mm.dom.firstChild.innerHTML = msg;
-                   mm.setDisplayed(true);
-                   mm.center(me);
-               }
-               if(Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto'){ 
-                   mask.setSize(undefined, me.getHeight());
-               }
-               return mask;
-           },
-
-           
-           unmask : function(){
-                   var me = this,
-                dom = me.dom,
-                       mask = data(dom, 'mask'),
-                       maskMsg = data(dom, 'maskMsg');
-               if(mask){
-                   if(maskMsg){
-                       maskMsg.remove();
-                    data(dom, 'maskMsg', undefined);
-                   }
-                   mask.remove();
-                data(dom, 'mask', undefined);
-               }
-               if(me.isMasked()){
-                me.removeClass([XMASKED, XMASKEDRELATIVE]);
-            }
-           },
-
-           
-           isMasked : function(){
-            var m = data(this.dom, 'mask');
-               return m && m.isVisible();
-           },
-
-           
-           createShim : function(){
-               var el = document.createElement('iframe'),
-                       shim;
-               el.frameBorder = '0';
-               el.className = 'ext-shim';
-               el.src = Ext.SSL_SECURE_URL;
-               shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
-               shim.autoBoxAdjust = false;
-               return shim;
-           }
-    };
-}());
-Ext.Element.addMethods({
     
-    addKeyListener : function(key, fn, scope){
-        var config;
-        if(typeof key != 'object' || Ext.isArray(key)){
-            config = {
-                key: key,
-                fn: fn,
-                scope: scope
-            };
-        }else{
-            config = {
-                key : key.key,
-                shift : key.shift,
-                ctrl : key.ctrl,
-                alt : key.alt,
-                fn: fn,
-                scope: scope
-            };
-        }
-        return new Ext.KeyMap(this, config);
+    hideAll: function() {
+        this.toggleAll(false);
     },
 
     
-    addKeyMap : function(config){
-        return new Ext.KeyMap(this, config);
+    showAll: function() {
+        this.toggleAll(true);
     }
 });
-(function(){
+
+
+Ext.define('Ext.chart.series.Pie', {
+
     
-    var NULL = null,
-        UNDEFINED = undefined,
-        TRUE = true,
-        FALSE = false,
-        SETX = "setX",
-        SETY = "setY",
-        SETXY = "setXY",
-        LEFT = "left",
-        BOTTOM = "bottom",
-        TOP = "top",
-        RIGHT = "right",
-        HEIGHT = "height",
-        WIDTH = "width",
-        POINTS = "points",
-        HIDDEN = "hidden",
-        ABSOLUTE = "absolute",
-        VISIBLE = "visible",
-        MOTION = "motion",
-        POSITION = "position",
-        EASEOUT = "easeOut",
-        
-        flyEl = new Ext.Element.Flyweight(),
-        queues = {},
-        getObject = function(o){
-            return o || {};
-        },
-        fly = function(dom){
-            flyEl.dom = dom;
-            flyEl.id = Ext.id(dom);
-            return flyEl;
-        },
-        
-        getQueue = function(id){
-            if(!queues[id]){
-                queues[id] = [];
-            }
-            return queues[id];
-        },
-        setQueue = function(id, value){
-            queues[id] = value;
-        };
-        
 
-Ext.enableFx = TRUE;
+    alternateClassName: ['Ext.chart.PieSeries', 'Ext.chart.PieChart'],
 
+    extend: 'Ext.chart.series.Series',
 
-Ext.Fx = {
     
+
+    type: "pie",
+
+    alias: 'series.pie',
+
+    rad: Math.PI / 180,
+
     
+    highlightDuration: 150,
+
     
-    switchStatements : function(key, fn, argHash){
-        return fn.apply(this, argHash[key]);
-    },
+    angleField: false,
+
     
+    lengthField: false,
+
     
-    slideIn : function(anchor, o){ 
-        o = getObject(o);
-        var me = this,
-            dom = me.dom,
-            st = dom.style,
-            xy,
-            r,
-            b,              
-            wrap,               
-            after,
-            st,
-            args, 
-            pt,
-            bw,
-            bh;
-            
-        anchor = anchor || "t";
+    donut: false,
 
-        me.queueFx(o, function(){            
-            xy = fly(dom).getXY();
-            
-            fly(dom).fixDisplay();            
-            
-            
-            r = fly(dom).getFxRestore();      
-            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
-            b.right = b.x + b.width;
-            b.bottom = b.y + b.height;
-            
-            
-            fly(dom).setWidth(b.width).setHeight(b.height);            
-            
-            
-            wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
-            
-            st.visibility = VISIBLE;
-            st.position = ABSOLUTE;
-            
-            
-            function after(){
-                 fly(dom).fxUnwrap(wrap, r.pos, o);
-                 st.width = r.width;
-                 st.height = r.height;
-                 fly(dom).afterFx(o);
+    
+    showInLegend: false,
+
+    
+
+    
+    style: {},
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            store = chart.store,
+            shadow = chart.shadow, i, l, cfg;
+        Ext.applyIf(me, {
+            highlightCfg: {
+                segment: {
+                    margin: 20
+                }
             }
-            
-            
-            pt = {to: [b.x, b.y]}; 
-            bw = {to: b.width};
-            bh = {to: b.height};
-                
-            function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
-                var ret = {};
-                fly(wrap).setWidth(ww).setHeight(wh);
-                if(fly(wrap)[sXY]){
-                    fly(wrap)[sXY](sXYval);                  
+        });
+        Ext.apply(me, config, {
+            shadowAttributes: [{
+                "stroke-width": 6,
+                "stroke-opacity": 1,
+                stroke: 'rgb(200, 200, 200)',
+                translate: {
+                    x: 1.2,
+                    y: 2
                 }
-                style[s1] = style[s2] = "0";                    
-                if(w){
-                    ret.width = w
-                };
-                if(h){
-                    ret.height = h;
+            },
+            {
+                "stroke-width": 4,
+                "stroke-opacity": 1,
+                stroke: 'rgb(150, 150, 150)',
+                translate: {
+                    x: 0.9,
+                    y: 1.5
                 }
-                if(p){
-                    ret.points = p;
+            },
+            {
+                "stroke-width": 2,
+                "stroke-opacity": 1,
+                stroke: 'rgb(100, 100, 100)',
+                translate: {
+                    x: 0.6,
+                    y: 1
                 }
-                return ret;
-            };
+            }]
+        });
+        me.group = surface.getGroup(me.seriesId);
+        if (shadow) {
+            for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+                me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+            }
+        }
+        surface.customAttributes.segment = function(opt) {
+            return me.getSegment(opt);
+        };
+        me.__excludes = me.__excludes || [];
+    },
 
-            args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
-                    t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
-                    l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
-                    r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
-                    b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
-                    tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
-                    bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
-                    br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
-                    tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
-                });
-            
-            st.visibility = VISIBLE;
-            fly(wrap).show();
+    //@private updates some onbefore render parameters.
 
-            arguments.callee.anim = fly(wrap).fxanim(args,
-                o,
-                MOTION,
-                .5,
-                EASEOUT, 
-                after);
-        });
-        return me;
+    initialize: function() {
+        var me = this,
+            store = me.chart.getChartStore();
+        
+        me.yField = [];
+        if (me.label.field) {
+            store.each(function(rec) {
+                me.yField.push(rec.get(me.label.field));
+            });
+        }
     },
+
     
-    
-    slideOut : function(anchor, o){
-        o = getObject(o);
+    getSegment: function(opt) {
         var me = this,
-            dom = me.dom,
-            st = dom.style,
-            xy = me.getXY(),
-            wrap,
-            r,
-            b,
-            a,
-            zero = {to: 0}; 
-                    
-        anchor = anchor || "t";
+            rad = me.rad,
+            cos = Math.cos,
+            sin = Math.sin,
+            x = me.centerX,
+            y = me.centerY,
+            x1 = 0, x2 = 0, x3 = 0, x4 = 0,
+            y1 = 0, y2 = 0, y3 = 0, y4 = 0,
+            x5 = 0, y5 = 0, x6 = 0, y6 = 0,
+            delta = 1e-2,
+            startAngle = opt.startAngle,
+            endAngle = opt.endAngle,
+            midAngle = (startAngle + endAngle) / 2 * rad,
+            margin = opt.margin || 0,
+            a1 = Math.min(startAngle, endAngle) * rad,
+            a2 = Math.max(startAngle, endAngle) * rad,
+            c1 = cos(a1), s1 = sin(a1),
+            c2 = cos(a2), s2 = sin(a2),
+            cm = cos(midAngle), sm = sin(midAngle),
+            flag = 0, hsqr2 = 0.7071067811865476; 
 
-        me.queueFx(o, function(){
-            
-            
-            r = fly(dom).getFxRestore(); 
-            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
-            b.right = b.x + b.width;
-            b.bottom = b.y + b.height;
-                
-            
-            fly(dom).setWidth(b.width).setHeight(b.height);
+        if (a2 - a1 < delta) {
+            return {path: ""};
+        }
 
-            
-            wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
-                
-            st.visibility = VISIBLE;
-            st.position = ABSOLUTE;
-            fly(wrap).setWidth(b.width).setHeight(b.height);            
+        if (margin !== 0) {
+            x += margin * cm;
+            y += margin * sm;
+        }
 
-            function after(){
-                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
-                fly(dom).fxUnwrap(wrap, r.pos, o);
-                st.width = r.width;
-                st.height = r.height;
-                fly(dom).afterFx(o);
-            }            
-            
-            function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
-                var ret = {};
-                
-                style[s1] = style[s2] = "0";
-                ret[p1] = v1;               
-                if(p2){
-                    ret[p2] = v2;               
-                }
-                if(p3){
-                    ret[p3] = v3;
-                }
-                
-                return ret;
+        x2 = x + opt.endRho * c1;
+        y2 = y + opt.endRho * s1;
+
+        x4 = x + opt.endRho * c2;
+        y4 = y + opt.endRho * s2;
+
+        if (Math.abs(x2 - x4) + Math.abs(y2 - y4) < delta) {
+            cm = hsqr2;
+            sm = -hsqr2;
+            flag = 1;
+        }
+
+        x6 = x + opt.endRho * cm;
+        y6 = y + opt.endRho * sm;
+
+        
+        
+
+        if (opt.startRho !== 0) {
+            x1 = x + opt.startRho * c1;
+            y1 = y + opt.startRho * s1;
+    
+            x3 = x + opt.startRho * c2;
+            y3 = y + opt.startRho * s2;
+    
+            x5 = x + opt.startRho * cm;
+            y5 = y + opt.startRho * sm;
+
+            return {
+                path: [
+                    ["M", x2, y2],
+                    ["A", opt.endRho, opt.endRho, 0, 0, 1, x6, y6], ["L", x6, y6],
+                    ["A", opt.endRho, opt.endRho, 0, flag, 1, x4, y4], ["L", x4, y4],
+                    ["L", x3, y3],
+                    ["A", opt.startRho, opt.startRho, 0, flag, 0, x5, y5], ["L", x5, y5],
+                    ["A", opt.startRho, opt.startRho, 0, 0, 0, x1, y1], ["L", x1, y1],
+                    ["Z"]
+                ]
             };
-            
-            a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
-                t  : [st, LEFT, BOTTOM, HEIGHT, zero],
-                l  : [st, RIGHT, TOP, WIDTH, zero],
-                r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
-                b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
-                tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
-                bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
-                br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
-                tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
-            });
-            
-            arguments.callee.anim = fly(wrap).fxanim(a,
-                o,
-                MOTION,
-                .5,
-                EASEOUT, 
-                after);
-        });
-        return me;
+        } else {
+            return {
+                path: [
+                    ["M", x, y],
+                    ["L", x2, y2],
+                    ["A", opt.endRho, opt.endRho, 0, 0, 1, x6, y6], ["L", x6, y6],
+                    ["A", opt.endRho, opt.endRho, 0, flag, 1, x4, y4], ["L", x4, y4],
+                    ["L", x, y],
+                    ["Z"]
+                ]
+            };
+        }
     },
 
     
-    puff : function(o){
-        o = getObject(o);
+    calcMiddle: function(item) {
         var me = this,
-            dom = me.dom,
-            st = dom.style,
-            width,
-            height,
-            r;
-
-        me.queueFx(o, function(){
-            width = fly(dom).getWidth();
-            height = fly(dom).getHeight();
-            fly(dom).clearOpacity();
-            fly(dom).show();
-
-            
-            r = fly(dom).getFxRestore();                   
-            
-            function after(){
-                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
-                fly(dom).clearOpacity();  
-                fly(dom).setPositioning(r.pos);
-                st.width = r.width;
-                st.height = r.height;
-                st.fontSize = '';
-                fly(dom).afterFx(o);
-            }   
-
-            arguments.callee.anim = fly(dom).fxanim({
-                    width : {to : fly(dom).adjustWidth(width * 2)},
-                    height : {to : fly(dom).adjustHeight(height * 2)},
-                    points : {by : [-width * .5, -height * .5]},
-                    opacity : {to : 0},
-                    fontSize: {to : 200, unit: "%"}
-                },
-                o,
-                MOTION,
-                .5,
-                EASEOUT,
-                 after);
-        });
-        return me;
+            rad = me.rad,
+            slice = item.slice,
+            x = me.centerX,
+            y = me.centerY,
+            startAngle = slice.startAngle,
+            endAngle = slice.endAngle,
+            donut = +me.donut,
+            midAngle = -(startAngle + endAngle) * rad / 2,
+            r = (item.endRho + item.startRho) / 2,
+            xm = x + r * Math.cos(midAngle),
+            ym = y - r * Math.sin(midAngle);
+
+        item.middle = {
+            x: xm,
+            y: ym
+        };
     },
 
     
-    switchOff : function(o){
-        o = getObject(o);
+    drawSeries: function() {
         var me = this,
-            dom = me.dom,
-            st = dom.style,
-            r;
+            store = me.chart.getChartStore(),
+            group = me.group,
+            animate = me.chart.animate,
+            field = me.angleField || me.field || me.xField,
+            lenField = [].concat(me.lengthField),
+            totalLenField = 0,
+            colors = me.colorSet,
+            chart = me.chart,
+            surface = chart.surface,
+            chartBBox = chart.chartBBox,
+            enableShadows = chart.shadow,
+            shadowGroups = me.shadowGroups,
+            shadowAttributes = me.shadowAttributes,
+            lnsh = shadowGroups.length,
+            rad = me.rad,
+            layers = lenField.length,
+            rhoAcum = 0,
+            donut = +me.donut,
+            layerTotals = [],
+            values = {},
+            fieldLength,
+            items = [],
+            passed = false,
+            totalField = 0,
+            maxLenField = 0,
+            cut = 9,
+            defcut = true,
+            angle = 0,
+            seriesStyle = me.seriesStyle,
+            seriesLabelStyle = me.seriesLabelStyle,
+            colorArrayStyle = me.colorArrayStyle,
+            colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
+            gutterX = chart.maxGutter[0],
+            gutterY = chart.maxGutter[1],
+            abs = Math.abs,
+            rendererAttributes,
+            shadowGroup,
+            shadowAttr,
+            shadows,
+            shadow,
+            shindex,
+            centerX,
+            centerY,
+            deltaRho,
+            first = 0,
+            slice,
+            slices,
+            sprite,
+            value,
+            item,
+            lenValue,
+            ln,
+            record,
+            i,
+            j,
+            startAngle,
+            endAngle,
+            middleAngle,
+            sliceLength,
+            path,
+            p,
+            spriteOptions, bbox;
 
-        me.queueFx(o, function(){
-            fly(dom).clearOpacity();
-            fly(dom).clip();
+        Ext.apply(seriesStyle, me.style || {});
 
-            
-            r = fly(dom).getFxRestore();
-                
-            function after(){
-                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
-                fly(dom).clearOpacity();
-                fly(dom).setPositioning(r.pos);
-                st.width = r.width;
-                st.height = r.height;   
-                fly(dom).afterFx(o);
-            };
+        me.setBBox();
+        bbox = me.bbox;
 
-            fly(dom).fxanim({opacity : {to : 0.3}}, 
-                NULL, 
-                NULL, 
-                .1, 
-                NULL, 
-                function(){                                 
-                    fly(dom).clearOpacity();
-                        (function(){                            
-                            fly(dom).fxanim({
-                                height : {to : 1},
-                                points : {by : [0, fly(dom).getHeight() * .5]}
-                            }, 
-                            o, 
-                            MOTION, 
-                            0.3, 
-                            'easeIn', 
-                            after);
-                        }).defer(100);
-                });
-        });
-        return me;
-    },
+        
+        if (me.colorSet) {
+            colorArrayStyle = me.colorSet;
+            colorArrayLength = colorArrayStyle.length;
+        }
 
-     
-    highlight : function(color, o){
-        o = getObject(o);
-        var me = this,
-            dom = me.dom,
-            attr = o.attr || "backgroundColor",
-            a = {},
-            restore;
+        
+        if (!store || !store.getCount()) {
+            return;
+        }
 
-        me.queueFx(o, function(){
-            fly(dom).clearOpacity();
-            fly(dom).show();
+        me.unHighlightItem();
+        me.cleanHighlights();
 
-            function after(){
-                dom.style[attr] = restore;
-                fly(dom).afterFx(o);
-            }            
-            restore = dom.style[attr];
-            a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
-            arguments.callee.anim = fly(dom).fxanim(a,
-                o,
-                'color',
-                1,
-                'easeIn', 
-                after);
-        });
-        return me;
-    },
+        centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
+        centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
+        me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
+        me.slices = slices = [];
+        me.items = items = [];
 
-   
-    frame : function(color, count, o){
-        o = getObject(o);
-        var me = this,
-            dom = me.dom,
-            proxy,
-            active;
+        store.each(function(record, i) {
+            if (this.__excludes && this.__excludes[i]) {
+                
+                return;
+            }
+            totalField += +record.get(field);
+            if (lenField[0]) {
+                for (j = 0, totalLenField = 0; j < layers; j++) {
+                    totalLenField += +record.get(lenField[j]);
+                }
+                layerTotals[i] = totalLenField;
+                maxLenField = Math.max(maxLenField, totalLenField);
+            }
+        }, this);
+
+        totalField = totalField || 1;
+        store.each(function(record, i) {
+            if (this.__excludes && this.__excludes[i]) {
+                value = 0;
+            } else {
+                value = record.get(field);
+                if (first == 0) {
+                    first = 1;
+                }
+            }
 
-        me.queueFx(o, function(){
-            color = color || '#C3DAF9';
-            if(color.length == 6){
-                color = '#' + color;
-            }            
-            count = count || 1;
-            fly(dom).show();
-
-            var xy = fly(dom).getXY(),
-                b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
-                queue = function(){
-                    proxy = fly(document.body || document.documentElement).createChild({
-                        style:{
-                            position : ABSOLUTE,
-                            'z-index': 35000, 
-                            border : '0px solid ' + color
-                        }
-                    });
-                    return proxy.queueFx({}, animFn);
-                };
-            
             
-            arguments.callee.anim = {
-                isAnimated: true,
-                stop: function() {
-                    count = 0;
-                    proxy.stopFx();
+            if (first == 1) {
+                first = 2;
+                me.firstAngle = angle = 360 * value / totalField / 2;
+                for (j = 0; j < i; j++) {
+                    slices[j].startAngle = slices[j].endAngle = me.firstAngle;
                 }
-            };
+            }
             
-            function animFn(){
-                var scale = Ext.isBorderBox ? 2 : 1;
-                active = proxy.anim({
-                    top : {from : b.y, to : b.y - 20},
-                    left : {from : b.x, to : b.x - 20},
-                    borderWidth : {from : 0, to : 10},
-                    opacity : {from : 1, to : 0},
-                    height : {from : b.height, to : b.height + 20 * scale},
-                    width : {from : b.width, to : b.width + 20 * scale}
-                },{
-                    duration: o.duration || 1,
-                    callback: function() {
-                        proxy.remove();
-                        --count > 0 ? queue() : fly(dom).afterFx(o);
+            endAngle = angle - 360 * value / totalField;
+            slice = {
+                series: me,
+                value: value,
+                startAngle: angle,
+                endAngle: endAngle,
+                storeItem: record
+            };
+            if (lenField[0]) {
+                lenValue = layerTotals[i];
+                slice.rho = me.radius * (lenValue / maxLenField);
+            } else {
+                slice.rho = me.radius;
+            }
+            slices[i] = slice;
+            angle = endAngle;
+        }, me);
+        
+        if (enableShadows) {
+            for (i = 0, ln = slices.length; i < ln; i++) {
+                slice = slices[i];
+                slice.shadowAttrs = [];
+                for (j = 0, rhoAcum = 0, shadows = []; j < layers; j++) {
+                    sprite = group.getAt(i * layers + j);
+                    deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
+                    
+                    rendererAttributes = {
+                        segment: {
+                            startAngle: slice.startAngle,
+                            endAngle: slice.endAngle,
+                            margin: 0,
+                            rho: slice.rho,
+                            startRho: rhoAcum + (deltaRho * donut / 100),
+                            endRho: rhoAcum + deltaRho
+                        },
+                        hidden: !slice.value && (slice.startAngle % 360) == (slice.endAngle % 360)
+                    };
+                    
+                    for (shindex = 0, shadows = []; shindex < lnsh; shindex++) {
+                        shadowAttr = shadowAttributes[shindex];
+                        shadow = shadowGroups[shindex].getAt(i);
+                        if (!shadow) {
+                            shadow = chart.surface.add(Ext.apply({}, {
+                                type: 'path',
+                                group: shadowGroups[shindex],
+                                strokeLinejoin: "round"
+                            }, rendererAttributes, shadowAttr));
+                        }
+                        if (animate) {
+                            shadowAttr = me.renderer(shadow, store.getAt(i), Ext.apply({}, rendererAttributes, shadowAttr), i, store);
+                            me.onAnimate(shadow, {
+                                to: shadowAttr
+                            });
+                        } else {
+                            shadowAttr = me.renderer(shadow, store.getAt(i), shadowAttr, i, store);
+                            shadow.setAttributes(shadowAttr, true);
+                        }
+                        shadows.push(shadow);
                     }
+                    slice.shadowAttrs[j] = shadows;
+                }
+            }
+        }
+        
+        for (i = 0, ln = slices.length; i < ln; i++) {
+            slice = slices[i];
+            for (j = 0, rhoAcum = 0; j < layers; j++) {
+                sprite = group.getAt(i * layers + j);
+                deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
+                
+                rendererAttributes = Ext.apply({
+                    segment: {
+                        startAngle: slice.startAngle,
+                        endAngle: slice.endAngle,
+                        margin: 0,
+                        rho: slice.rho,
+                        startRho: rhoAcum + (deltaRho * donut / 100),
+                        endRho: rhoAcum + deltaRho
+                    },
+                    hidden: (!slice.value && (slice.startAngle % 360) == (slice.endAngle % 360))
+                }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
+                item = Ext.apply({},
+                rendererAttributes.segment, {
+                    slice: slice,
+                    series: me,
+                    storeItem: slice.storeItem,
+                    index: i
                 });
-                arguments.callee.anim = {
-                    isAnimated: true,
-                    stop: function(){
-                        active.stop();
-                    }
-                };
-            };
-            queue();
-        });
-        return me;
-    },
-
-   
-    pause : function(seconds){        
-        var dom = this.dom,
-            t;
-
-        this.queueFx({}, function(){
-            t = setTimeout(function(){
-                fly(dom).afterFx({});
-            }, seconds * 1000);
-            arguments.callee.anim = {
-                isAnimated: true,
-                stop: function(){
-                    clearTimeout(t);
-                    fly(dom).afterFx({});
+                me.calcMiddle(item);
+                if (enableShadows) {
+                    item.shadows = slice.shadowAttrs[j];
                 }
-            };
-        });
-        return this;
-    },
+                items[i] = item;
+                
+                if (!sprite) {
+                    spriteOptions = Ext.apply({
+                        type: "path",
+                        group: group,
+                        middle: item.middle
+                    }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
+                    sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
+                }
+                slice.sprite = slice.sprite || [];
+                item.sprite = sprite;
+                slice.sprite.push(sprite);
+                slice.point = [item.middle.x, item.middle.y];
+                if (animate) {
+                    rendererAttributes = me.renderer(sprite, store.getAt(i), rendererAttributes, i, store);
+                    sprite._to = rendererAttributes;
+                    sprite._animating = true;
+                    me.onAnimate(sprite, {
+                        to: rendererAttributes,
+                        listeners: {
+                            afteranimate: {
+                                fn: function() {
+                                    this._animating = false;
+                                },
+                                scope: sprite
+                            }
+                        }
+                    });
+                } else {
+                    rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(rendererAttributes, {
+                        hidden: false
+                    }), i, store);
+                    sprite.setAttributes(rendererAttributes, true);
+                }
+                rhoAcum += deltaRho;
+            }
+        }
 
-   
-    fadeIn : function(o){
-        o = getObject(o);
-        var me = this,
-            dom = me.dom,
-            to = o.endOpacity || 1;
         
-        me.queueFx(o, function(){
-            fly(dom).setOpacity(0);
-            fly(dom).fixDisplay();
-            dom.style.visibility = VISIBLE;
-            arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
-                o, NULL, .5, EASEOUT, function(){
-                if(to == 1){
-                    fly(dom).clearOpacity();
+        ln = group.getCount();
+        for (i = 0; i < ln; i++) {
+            if (!slices[(i / layers) >> 0] && group.getAt(i)) {
+                group.getAt(i).hide(true);
+            }
+        }
+        if (enableShadows) {
+            lnsh = shadowGroups.length;
+            for (shindex = 0; shindex < ln; shindex++) {
+                if (!slices[(shindex / layers) >> 0]) {
+                    for (j = 0; j < lnsh; j++) {
+                        if (shadowGroups[j].getAt(shindex)) {
+                            shadowGroups[j].getAt(shindex).hide(true);
+                        }
+                    }
                 }
-                fly(dom).afterFx(o);
-            });
-        });
-        return me;
+            }
+        }
+        me.renderLabels();
+        me.renderCallouts();
     },
 
-   
-    fadeOut : function(o){
-        o = getObject(o);
+    
+    onCreateLabel: function(storeItem, item, i, display) {
         var me = this,
-            dom = me.dom,
-            style = dom.style,
-            to = o.endOpacity || 0;         
-        
-        me.queueFx(o, function(){  
-            arguments.callee.anim = fly(dom).fxanim({ 
-                opacity : {to : to}},
-                o, 
-                NULL, 
-                .5, 
-                EASEOUT, 
-                function(){
-                    if(to == 0){
-                        Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
-                            style.display = "none" :
-                            style.visibility = HIDDEN;
-                            
-                        fly(dom).clearOpacity();
-                    }
-                    fly(dom).afterFx(o);
-            });
-        });
-        return me;
-    },
+            group = me.labelsGroup,
+            config = me.label,
+            centerX = me.centerX,
+            centerY = me.centerY,
+            middle = item.middle,
+            endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config || {});
 
-   
-    scale : function(w, h, o){
-        this.shift(Ext.apply({}, o, {
-            width: w,
-            height: h
-        }));
-        return this;
+        return me.chart.surface.add(Ext.apply({
+            'type': 'text',
+            'text-anchor': 'middle',
+            'group': group,
+            'x': middle.x,
+            'y': middle.y
+        }, endLabelStyle));
     },
 
-   
-    shift : function(o){
-        o = getObject(o);
-        var dom = this.dom,
-            a = {};
-                
-        this.queueFx(o, function(){
-            for (var prop in o) {
-                if (o[prop] != UNDEFINED) {                                                 
-                    a[prop] = {to : o[prop]};                   
-                }
-            } 
-            
-            a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
-            a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
-            
-            if (a.x || a.y || a.xy) {
-                a.points = a.xy || 
-                           {to : [ a.x ? a.x.to : fly(dom).getX(),
-                                   a.y ? a.y.to : fly(dom).getY()]};                  
+    
+    onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.label,
+            format = config.renderer,
+            field = [].concat(config.field),
+            centerX = me.centerX,
+            centerY = me.centerY,
+            middle = item.middle,
+            opt = {
+                x: middle.x,
+                y: middle.y
+            },
+            x = middle.x - centerX,
+            y = middle.y - centerY,
+            from = {},
+            rho = 1,
+            theta = Math.atan2(y, x || 1),
+            dg = theta * 180 / Math.PI,
+            prevDg;
+        if (this.__excludes && this.__excludes[i]) {
+            opt.hidden = true;
+        }
+        function fixAngle(a) {
+            if (a < 0) {
+                a += 360;
             }
+            return a % 360;
+        }
 
-            arguments.callee.anim = fly(dom).fxanim(a,
-                o, 
-                MOTION, 
-                .35, 
-                EASEOUT, 
-                function(){
-                    fly(dom).afterFx(o);
-                });
-        });
-        return this;
-    },
+        label.setAttributes({
+            text: format(storeItem.get(field[index]))
+        }, true);
 
-    
-    ghost : function(anchor, o){
-        o = getObject(o);
-        var me = this,
-            dom = me.dom,
-            st = dom.style,
-            a = {opacity: {to: 0}, points: {}},
-            pt = a.points,
-            r,
-            w,
-            h;
+        switch (display) {
+        case 'outside':
+            rho = Math.sqrt(x * x + y * y) * 2;
             
-        anchor = anchor || "b";
+            opt.x = rho * Math.cos(theta) + centerX;
+            opt.y = rho * Math.sin(theta) + centerY;
+            break;
 
-        me.queueFx(o, function(){
-            
-            r = fly(dom).getFxRestore();
-            w = fly(dom).getWidth();
-            h = fly(dom).getHeight();
-            
-            function after(){
-                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
-                fly(dom).clearOpacity();
-                fly(dom).setPositioning(r.pos);
-                st.width = r.width;
-                st.height = r.height;
-                fly(dom).afterFx(o);
+        case 'rotate':
+            dg = fixAngle(dg);
+            dg = (dg > 90 && dg < 270) ? dg + 180: dg;
+
+            prevDg = label.attr.rotation.degrees;
+            if (prevDg != null && Math.abs(prevDg - dg) > 180) {
+                if (dg > prevDg) {
+                    dg -= 360;
+                } else {
+                    dg += 360;
+                }
+                dg = dg % 360;
+            } else {
+                dg = fixAngle(dg);
             }
-                
-            pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
-               t  : [0, -h],
-               l  : [-w, 0],
-               r  : [w, 0],
-               b  : [0, h],
-               tl : [-w, -h],
-               bl : [-w, h],
-               br : [w, h],
-               tr : [w, -h] 
+            
+            opt.rotate = {
+                degrees: dg,
+                x: opt.x,
+                y: opt.y
+            };
+            break;
+
+        default:
+            break;
+        }
+        
+        opt.translate = {
+            x: 0, y: 0
+        };
+        if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
+            me.onAnimate(label, {
+                to: opt
             });
-                
-            arguments.callee.anim = fly(dom).fxanim(a,
-                o,
-                MOTION,
-                .5,
-                EASEOUT, after);
-        });
-        return me;
+        } else {
+            label.setAttributes(opt, true);
+        }
+        label._from = from;
     },
 
     
-    syncFx : function(){
-        var me = this;
-        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
-            block : FALSE,
-            concurrent : TRUE,
-            stopFx : FALSE
-        });
-        return me;
-    },
+    onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.callouts,
+            centerX = me.centerX,
+            centerY = me.centerY,
+            middle = item.middle,
+            opt = {
+                x: middle.x,
+                y: middle.y
+            },
+            x = middle.x - centerX,
+            y = middle.y - centerY,
+            rho = 1,
+            rhoCenter,
+            theta = Math.atan2(y, x || 1),
+            bbox = callout.label.getBBox(),
+            offsetFromViz = 20,
+            offsetToSide = 10,
+            offsetBox = 10,
+            p;
 
-    
-    sequenceFx : function(){
-        var me = this;
-        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
-            block : FALSE,
-            concurrent : FALSE,
-            stopFx : FALSE
-        });
-        return me;
-    },
+        
+        rho = item.endRho + offsetFromViz;
+        rhoCenter = (item.endRho + item.startRho) / 2 + (item.endRho - item.startRho) / 3;
+        
+        opt.x = rho * Math.cos(theta) + centerX;
+        opt.y = rho * Math.sin(theta) + centerY;
 
-    
-    nextFx : function(){        
-        var ef = getQueue(this.dom.id)[0];
-        if(ef){
-            ef.call(this);
+        x = rhoCenter * Math.cos(theta);
+        y = rhoCenter * Math.sin(theta);
+
+        if (chart.animate) {
+            
+            me.onAnimate(callout.lines, {
+                to: {
+                    path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
+                }
+            });
+            
+            me.onAnimate(callout.box, {
+                to: {
+                    x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
+                    y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
+                    width: bbox.width + 2 * offsetBox,
+                    height: bbox.height + 2 * offsetBox
+                }
+            });
+            
+            me.onAnimate(callout.label, {
+                to: {
+                    x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
+                    y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
+                }
+            });
+        } else {
+            
+            callout.lines.setAttributes({
+                path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
+            },
+            true);
+            
+            callout.box.setAttributes({
+                x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
+                y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
+                width: bbox.width + 2 * offsetBox,
+                height: bbox.height + 2 * offsetBox
+            },
+            true);
+            
+            callout.label.setAttributes({
+                x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
+                y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
+            },
+            true);
+        }
+        for (p in callout) {
+            callout[p].show(true);
         }
     },
 
     
-    hasActiveFx : function(){
-        return getQueue(this.dom.id)[0];
+    onAnimate: function(sprite, attr) {
+        sprite.show();
+        return this.callParent(arguments);
     },
 
-    
-    stopFx : function(finish){
+    isItemInPoint: function(x, y, item, i) {
         var me = this,
-            id = me.dom.id;
-        if(me.hasActiveFx()){
-            var cur = getQueue(id)[0];
-            if(cur && cur.anim){
-                if(cur.anim.isAnimated){
-                    setQueue(id, [cur]); 
-                    cur.anim.stop(finish !== undefined ? finish : TRUE);
-                }else{
-                    setQueue(id, []);
+            cx = me.centerX,
+            cy = me.centerY,
+            abs = Math.abs,
+            dx = abs(x - cx),
+            dy = abs(y - cy),
+            startAngle = item.startAngle,
+            endAngle = item.endAngle,
+            rho = Math.sqrt(dx * dx + dy * dy),
+            angle = Math.atan2(y - cy, x - cx) / me.rad;
+
+        
+        if (angle > me.firstAngle) {
+            angle -= 360;
+        }
+        return (angle <= startAngle && angle > endAngle
+                && rho >= item.startRho && rho <= item.endRho);
+    },
+
+    
+    hideAll: function() {
+        var i, l, shadow, shadows, sh, lsh, sprite;
+        if (!isNaN(this._index)) {
+            this.__excludes = this.__excludes || [];
+            this.__excludes[this._index] = true;
+            sprite = this.slices[this._index].sprite;
+            for (sh = 0, lsh = sprite.length; sh < lsh; sh++) {
+                sprite[sh].setAttributes({
+                    hidden: true
+                }, true);
+            }
+            if (this.slices[this._index].shadowAttrs) {
+                for (i = 0, shadows = this.slices[this._index].shadowAttrs, l = shadows.length; i < l; i++) {
+                    shadow = shadows[i];
+                    for (sh = 0, lsh = shadow.length; sh < lsh; sh++) {
+                        shadow[sh].setAttributes({
+                            hidden: true
+                        }, true);
+                    }
                 }
             }
+            this.drawSeries();
         }
-        return me;
     },
 
     
-    beforeFx : function(o){
-        if(this.hasActiveFx() && !o.concurrent){
-           if(o.stopFx){
-               this.stopFx();
-               return TRUE;
-           }
-           return FALSE;
+    showAll: function() {
+        if (!isNaN(this._index)) {
+            this.__excludes[this._index] = false;
+            this.drawSeries();
         }
-        return TRUE;
     },
 
     
-    hasFxBlock : function(){
-        var q = getQueue(this.dom.id);
-        return q && q[0] && q[0].block;
-    },
+    highlightItem: function(item) {
+        var me = this,
+            rad = me.rad;
+        item = item || this.items[this._index];
 
-    
-    queueFx : function(o, fn){
-        var me = fly(this.dom);
-        if(!me.hasFxBlock()){
-            Ext.applyIf(o, me.fxDefaults);
-            if(!o.concurrent){
-                var run = me.beforeFx(o);
-                fn.block = o.block;
-                getQueue(me.dom.id).push(fn);
-                if(run){
-                    me.nextFx();
-                }
-            }else{
-                fn.call(me);
-            }
+        
+        
+        
+        
+        this.unHighlightItem();
+
+        if (!item || item.sprite && item.sprite._animating) {
+            return;
         }
-        return me;
-    },
+        me.callParent([item]);
+        if (!me.highlight) {
+            return;
+        }
+        if ('segment' in me.highlightCfg) {
+            var highlightSegment = me.highlightCfg.segment,
+                animate = me.chart.animate,
+                attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop;
+            
+            if (me.labelsGroup) {
+                var group = me.labelsGroup,
+                    display = me.label.display,
+                    label = group.getAt(item.index),
+                    middle = (item.startAngle + item.endAngle) / 2 * rad,
+                    r = highlightSegment.margin || 0,
+                    x = r * Math.cos(middle),
+                    y = r * Math.sin(middle);
 
-    
-    fxWrap : function(pos, o, vis){ 
-        var dom = this.dom,
-            wrap,
-            wrapXY;
-        if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
-            if(o.fixPosition){
-                wrapXY = fly(dom).getXY();
-            }
-            var div = document.createElement("div");
-            div.style.visibility = vis;
-            wrap = dom.parentNode.insertBefore(div, dom);
-            fly(wrap).setPositioning(pos);
-            if(fly(wrap).isStyle(POSITION, "static")){
-                fly(wrap).position("relative");
+                
+                
+                
+                
+                
+                if (Math.abs(x) < 1e-10) {
+                    x = 0;
+                }
+                if (Math.abs(y) < 1e-10) {
+                    y = 0;
+                }
+
+                if (animate) {
+                    label.stopAnimation();
+                    label.animate({
+                        to: {
+                            translate: {
+                                x: x,
+                                y: y
+                            }
+                        },
+                        duration: me.highlightDuration
+                    });
+                }
+                else {
+                    label.setAttributes({
+                        translate: {
+                            x: x,
+                            y: y
+                        }
+                    }, true);
+                }
             }
-            fly(dom).clearPositioning('auto');
-            fly(wrap).clip();
-            wrap.appendChild(dom);
-            if(wrapXY){
-                fly(wrap).setXY(wrapXY);
+            
+            if (me.chart.shadow && item.shadows) {
+                i = 0;
+                shadows = item.shadows;
+                ln = shadows.length;
+                for (; i < ln; i++) {
+                    shadow = shadows[i];
+                    to = {};
+                    itemHighlightSegment = item.sprite._from.segment;
+                    for (prop in itemHighlightSegment) {
+                        if (! (prop in highlightSegment)) {
+                            to[prop] = itemHighlightSegment[prop];
+                        }
+                    }
+                    attrs = {
+                        segment: Ext.applyIf(to, me.highlightCfg.segment)
+                    };
+                    if (animate) {
+                        shadow.stopAnimation();
+                        shadow.animate({
+                            to: attrs,
+                            duration: me.highlightDuration
+                        });
+                    }
+                    else {
+                        shadow.setAttributes(attrs, true);
+                    }
+                }
             }
         }
-        return wrap;
     },
 
     
-    fxUnwrap : function(wrap, pos, o){      
-        var dom = this.dom;
-        fly(dom).clearPositioning();
-        fly(dom).setPositioning(pos);
-        if(!o.wrap){
-            var pn = fly(wrap).dom.parentNode;
-            pn.insertBefore(dom, wrap); 
-            fly(wrap).remove();
+    unHighlightItem: function() {
+        var me = this;
+        if (!me.highlight) {
+            return;
         }
-    },
 
-    
-    getFxRestore : function(){
-        var st = this.dom.style;
-        return {pos: this.getPositioning(), width: st.width, height : st.height};
-    },
+        if (('segment' in me.highlightCfg) && me.items) {
+            var items = me.items,
+                animate = me.chart.animate,
+                shadowsEnabled = !!me.chart.shadow,
+                group = me.labelsGroup,
+                len = items.length,
+                i = 0,
+                j = 0,
+                display = me.label.display,
+                shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs;
 
-    
-    afterFx : function(o){
-        var dom = this.dom,
-            id = dom.id;
-        if(o.afterStyle){
-            fly(dom).setStyle(o.afterStyle);            
-        }
-        if(o.afterCls){
-            fly(dom).addClass(o.afterCls);
-        }
-        if(o.remove == TRUE){
-            fly(dom).remove();
-        }
-        if(o.callback){
-            o.callback.call(o.scope, fly(dom));
-        }
-        if(!o.concurrent){
-            getQueue(id).shift();
-            fly(dom).nextFx();
+            for (; i < len; i++) {
+                item = items[i];
+                if (!item) {
+                    continue;
+                }
+                sprite = item.sprite;
+                if (sprite && sprite._highlighted) {
+                    
+                    if (group) {
+                        label = group.getAt(item.index);
+                        attrs = Ext.apply({
+                            translate: {
+                                x: 0,
+                                y: 0
+                            }
+                        },
+                        display == 'rotate' ? {
+                            rotate: {
+                                x: label.attr.x,
+                                y: label.attr.y,
+                                degrees: label.attr.rotation.degrees
+                            }
+                        }: {});
+                        if (animate) {
+                            label.stopAnimation();
+                            label.animate({
+                                to: attrs,
+                                duration: me.highlightDuration
+                            });
+                        }
+                        else {
+                            label.setAttributes(attrs, true);
+                        }
+                    }
+                    if (shadowsEnabled) {
+                        shadows = item.shadows;
+                        shadowLen = shadows.length;
+                        for (; j < shadowLen; j++) {
+                            to = {};
+                            ihs = item.sprite._to.segment;
+                            hs = item.sprite._from.segment;
+                            Ext.apply(to, hs);
+                            for (p in ihs) {
+                                if (! (p in hs)) {
+                                    to[p] = ihs[p];
+                                }
+                            }
+                            shadow = shadows[j];
+                            if (animate) {
+                                shadow.stopAnimation();
+                                shadow.animate({
+                                    to: {
+                                        segment: to
+                                    },
+                                    duration: me.highlightDuration
+                                });
+                            }
+                            else {
+                                shadow.setAttributes({ segment: to }, true);
+                            }
+                        }
+                    }
+                }
+            }
         }
+        me.callParent(arguments);
     },
 
     
-    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
-        animType = animType || 'run';
-        opt = opt || {};
-        var anim = Ext.lib.Anim[animType](
-                this.dom, 
-                args,
-                (opt.duration || defaultDur) || .35,
-                (opt.easing || defaultEase) || EASEOUT,
-                cb,            
-                this
-            );
-        opt.anim = anim;
-        return anim;
+    getLegendColor: function(index) {
+        var me = this;
+        return (me.colorSet && me.colorSet[index % me.colorSet.length]) || me.colorArrayStyle[index % me.colorArrayStyle.length];
     }
-};
+});
 
 
-Ext.Fx.resize = Ext.Fx.scale;
 
+Ext.define('Ext.chart.series.Radar', {
 
+    
 
-Ext.Element.addMethods(Ext.Fx);
-})();
+    extend: 'Ext.chart.series.Series',
+
+    requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
 
-Ext.CompositeElementLite = function(els, root){
     
-    this.elements = [];
-    this.add(els, root);
-    this.el = new Ext.Element.Flyweight();
-};
 
-Ext.CompositeElementLite.prototype = {
-    isComposite: true,
+    type: "radar",
+    alias: 'series.radar',
 
-    
-    getElement : function(el){
-        
-        var e = this.el;
-        e.dom = el;
-        e.id = el.id;
-        return e;
-    },
 
-    
-    transformElement : function(el){
-        return Ext.getDom(el);
-    },
+    rad: Math.PI / 180,
+
+    showInLegend: false,
 
     
-    getCount : function(){
-        return this.elements.length;
+    style: {},
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            surface = me.chart.surface, i, l;
+        me.group = surface.getGroup(me.seriesId);
+        if (me.showMarkers) {
+            me.markerGroup = surface.getGroup(me.seriesId + '-markers');
+        }
     },
+
     
-    add : function(els, root){
+    drawSeries: function() {
         var me = this,
-            elements = me.elements;
-        if(!els){
-            return this;
-        }
-        if(typeof els == "string"){
-            els = Ext.Element.selectorFunction(els, root);
-        }else if(els.isComposite){
-            els = els.elements;
-        }else if(!Ext.isIterable(els)){
-            els = [els];
+            store = me.chart.getChartStore(),
+            group = me.group,
+            sprite,
+            chart = me.chart,
+            animate = chart.animate,
+            field = me.field || me.yField,
+            surface = chart.surface,
+            chartBBox = chart.chartBBox,
+            rendererAttributes,
+            centerX, centerY,
+            items,
+            radius,
+            maxValue = 0,
+            fields = [],
+            max = Math.max,
+            cos = Math.cos,
+            sin = Math.sin,
+            pi2 = Math.PI * 2,
+            l = store.getCount(),
+            startPath, path, x, y, rho,
+            i, nfields,
+            seriesStyle = me.seriesStyle,
+            seriesLabelStyle = me.seriesLabelStyle,
+            first = chart.resizing || !me.radar,
+            axis = chart.axes && chart.axes.get(0),
+            aggregate = !(axis && axis.maximum);
+
+        me.setBBox();
+
+        maxValue = aggregate? 0 : (axis.maximum || 0);
+
+        Ext.apply(seriesStyle, me.style || {});
+
+        
+        if (!store || !store.getCount()) {
+            return;
         }
 
-        for(var i = 0, len = els.length; i < len; ++i){
-            elements.push(me.transformElement(els[i]));
-        }
-        return me;
-    },
+        me.unHighlightItem();
+        me.cleanHighlights();
 
-    invoke : function(fn, args){
-        var me = this,
-            els = me.elements,
-            len = els.length,
-            e,
-            i;
+        centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
+        centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
+        me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;
+        me.items = items = [];
 
-        for(i = 0; i < len; i++) {
-            e = els[i];
-            if(e){
-                Ext.Element.prototype[fn].apply(me.getElement(e), args);
+        if (aggregate) {
+            
+            chart.series.each(function(series) {
+                fields.push(series.yField);
+            });
+            
+            store.each(function(record, i) {
+                for (i = 0, nfields = fields.length; i < nfields; i++) {
+                    maxValue = max(+record.get(fields[i]), maxValue);
+                }
+            });
+        }
+        
+        maxValue = maxValue || 1;
+        
+        startPath = []; path = [];
+        store.each(function(record, i) {
+            rho = radius * record.get(field) / maxValue;
+            x = rho * cos(i / l * pi2);
+            y = rho * sin(i / l * pi2);
+            if (i == 0) {
+                path.push('M', x + centerX, y + centerY);
+                startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);
+            } else {
+                path.push('L', x + centerX, y + centerY);
+                startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);
             }
+            items.push({
+                sprite: false, 
+                point: [centerX + x, centerY + y],
+                series: me
+            });
+        });
+        path.push('Z');
+        
+        if (!me.radar) {
+            me.radar = surface.add(Ext.apply({
+                type: 'path',
+                group: group,
+                path: startPath
+            }, seriesStyle || {}));
         }
-        return me;
+        
+        if (chart.resizing) {
+            me.radar.setAttributes({
+                path: startPath
+            }, true);
+        }
+        
+        if (chart.animate) {
+            me.onAnimate(me.radar, {
+                to: Ext.apply({
+                    path: path
+                }, seriesStyle || {})
+            });
+        } else {
+            me.radar.setAttributes(Ext.apply({
+                path: path
+            }, seriesStyle || {}), true);
+        }
+        
+        if (me.showMarkers) {
+            me.drawMarkers();
+        }
+        me.renderLabels();
+        me.renderCallouts();
     },
+
     
-    item : function(index){
+    drawMarkers: function() {
         var me = this,
-            el = me.elements[index],
-            out = null;
-
-        if(el){
-            out = me.getElement(el);
+            chart = me.chart,
+            surface = chart.surface,
+            markerStyle = Ext.apply({}, me.markerStyle || {}),
+            endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
+            items = me.items,
+            type = endMarkerStyle.type,
+            markerGroup = me.markerGroup,
+            centerX = me.centerX,
+            centerY = me.centerY,
+            item, i, l, marker;
+
+        delete endMarkerStyle.type;
+
+        for (i = 0, l = items.length; i < l; i++) {
+            item = items[i];
+            marker = markerGroup.getAt(i);
+            if (!marker) {
+                marker = Ext.chart.Shape[type](surface, Ext.apply({
+                    group: markerGroup,
+                    x: 0,
+                    y: 0,
+                    translate: {
+                        x: centerX,
+                        y: centerY
+                    }
+                }, endMarkerStyle));
+            }
+            else {
+                marker.show();
+            }
+            if (chart.resizing) {
+                marker.setAttributes({
+                    x: 0,
+                    y: 0,
+                    translate: {
+                        x: centerX,
+                        y: centerY
+                    }
+                }, true);
+            }
+            marker._to = {
+                translate: {
+                    x: item.point[0],
+                    y: item.point[1]
+                }
+            };
+            
+            if (chart.animate) {
+                me.onAnimate(marker, {
+                    to: marker._to
+                });
+            }
+            else {
+                marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);
+            }
         }
-        return out;
+    },
+
+    isItemInPoint: function(x, y, item) {
+        var point,
+            tolerance = 10,
+            abs = Math.abs;
+        point = item.point;
+        return (abs(point[0] - x) <= tolerance &&
+                abs(point[1] - y) <= tolerance);
     },
 
     
-    addListener : function(eventName, handler, scope, opt){
-        var els = this.elements,
-            len = els.length,
-            i, e;
+    onCreateLabel: function(storeItem, item, i, display) {
+        var me = this,
+            group = me.labelsGroup,
+            config = me.label,
+            centerX = me.centerX,
+            centerY = me.centerY,
+            point = item.point,
+            endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
 
-        for(i = 0; i<len; i++) {
-            e = els[i];
-            if(e) {
-                Ext.EventManager.on(e, eventName, handler, scope || e, opt);
-            }
-        }
-        return this;
+        return me.chart.surface.add(Ext.apply({
+            'type': 'text',
+            'text-anchor': 'middle',
+            'group': group,
+            'x': centerX,
+            'y': centerY
+        }, config || {}));
     },
+
     
-    each : function(fn, scope){
+    onPlaceLabel: function(label, storeItem, item, i, display, animate) {
         var me = this,
-            els = me.elements,
-            len = els.length,
-            i, e;
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.label,
+            format = config.renderer,
+            field = config.field,
+            centerX = me.centerX,
+            centerY = me.centerY,
+            opt = {
+                x: item.point[0],
+                y: item.point[1]
+            },
+            x = opt.x - centerX,
+            y = opt.y - centerY;
 
-        for(i = 0; i<len; i++) {
-            e = els[i];
-            if(e){
-                e = this.getElement(e);
-                if(fn.call(scope || e, e, me, i) === false){
-                    break;
-                }
-            }
+        label.setAttributes({
+            text: format(storeItem.get(field)),
+            hidden: true
+        },
+        true);
+
+        if (resizing) {
+            label.setAttributes({
+                x: centerX,
+                y: centerY
+            }, true);
         }
-        return me;
-    },
 
-    
-    fill : function(els){
-        var me = this;
-        me.elements = [];
-        me.add(els);
-        return me;
+        if (animate) {
+            label.show(true);
+            me.onAnimate(label, {
+                to: opt
+            });
+        } else {
+            label.setAttributes(opt, true);
+            label.show(true);
+        }
     },
 
     
-    filter : function(selector){
-        var els = [],
-            me = this,
-            fn = Ext.isFunction(selector) ? selector
-                : function(el){
-                    return el.is(selector);
-                };
-
-        me.each(function(el, self, i) {
-            if (fn(el, i) !== false) {
-                els[els.length] = me.transformElement(el);
+    toggleAll: function(show) {
+        var me = this,
+            i, ln, shadow, shadows;
+        if (!show) {
+            Ext.chart.series.Radar.superclass.hideAll.call(me);
+        }
+        else {
+            Ext.chart.series.Radar.superclass.showAll.call(me);
+        }
+        if (me.radar) {
+            me.radar.setAttributes({
+                hidden: !show
+            }, true);
+            
+            if (me.radar.shadows) {
+                for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {
+                    shadow = shadows[i];
+                    shadow.setAttributes({
+                        hidden: !show
+                    }, true);
+                }
             }
-        });
-        
-        me.elements = els;
-        return me;
+        }
     },
 
     
-    indexOf : function(el){
-        return this.elements.indexOf(this.transformElement(el));
+    hideAll: function() {
+        this.toggleAll(false);
+        this.hideMarkers(0);
     },
 
     
-    replaceElement : function(el, replacement, domReplace){
-        var index = !isNaN(el) ? el : this.indexOf(el),
-            d;
-        if(index > -1){
-            replacement = Ext.getDom(replacement);
-            if(domReplace){
-                d = this.elements[index];
-                d.parentNode.insertBefore(replacement, d);
-                Ext.removeNode(d);
-            }
-            this.elements.splice(index, 1, replacement);
-        }
-        return this;
+    showAll: function() {
+        this.toggleAll(true);
     },
 
     
-    clear : function(){
-        this.elements = [];
+    hideMarkers: function(index) {
+        var me = this,
+            count = me.markerGroup && me.markerGroup.getCount() || 0,
+            i = index || 0;
+        for (; i < count; i++) {
+            me.markerGroup.getAt(i).hide(true);
+        }
     }
-};
+});
 
-Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
 
-(function(){
-var fnName,
-    ElProto = Ext.Element.prototype,
-    CelProto = Ext.CompositeElementLite.prototype;
-
-for(fnName in ElProto){
-    if(Ext.isFunction(ElProto[fnName])){
-        (function(fnName){
-            CelProto[fnName] = CelProto[fnName] || function(){
-                return this.invoke(fnName, arguments);
-            };
-        }).call(CelProto, fnName);
 
-    }
-}
-})();
+Ext.define('Ext.chart.series.Scatter', {
 
-if(Ext.DomQuery){
-    Ext.Element.selectorFunction = Ext.DomQuery.select;
-}
+    
 
+    extend: 'Ext.chart.series.Cartesian',
 
-Ext.Element.select = function(selector, root){
-    var els;
-    if(typeof selector == "string"){
-        els = Ext.Element.selectorFunction(selector, root);
-    }else if(selector.length !== undefined){
-        els = selector;
-    }else{
-        throw "Invalid selector";
-    }
-    return new Ext.CompositeElementLite(els);
-};
+    requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.fx.Anim'],
 
-Ext.select = Ext.Element.select;
+    
 
-Ext.apply(Ext.CompositeElementLite.prototype, {
-    addElements : function(els, root){
-        if(!els){
-            return this;
-        }
-        if(typeof els == "string"){
-            els = Ext.Element.selectorFunction(els, root);
-        }
-        var yels = this.elements;
-        Ext.each(els, function(e) {
-            yels.push(Ext.get(e));
-        });
-        return this;
-    },
+    type: 'scatter',
+    alias: 'series.scatter',
 
     
-    first : function(){
-        return this.item(0);
-    },
 
     
-    last : function(){
-        return this.item(this.getCount()-1);
+    
+    
+
+    constructor: function(config) {
+        this.callParent(arguments);
+        var me = this,
+            shadow = me.chart.shadow,
+            surface = me.chart.surface, i, l;
+        Ext.apply(me, config, {
+            style: {},
+            markerConfig: {},
+            shadowAttributes: [{
+                "stroke-width": 6,
+                "stroke-opacity": 0.05,
+                stroke: 'rgb(0, 0, 0)'
+            }, {
+                "stroke-width": 4,
+                "stroke-opacity": 0.1,
+                stroke: 'rgb(0, 0, 0)'
+            }, {
+                "stroke-width": 2,
+                "stroke-opacity": 0.15,
+                stroke: 'rgb(0, 0, 0)'
+            }]
+        });
+        me.group = surface.getGroup(me.seriesId);
+        if (shadow) {
+            for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
+                me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
+            }
+        }
     },
 
     
-    contains : function(el){
-        return this.indexOf(el) != -1;
+    getBounds: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            axes = [].concat(me.axis),
+            bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends;
+
+        me.setBBox();
+        bbox = me.bbox;
+
+        for (i = 0, ln = axes.length; i < ln; i++) {
+            axis = chart.axes.get(axes[i]);
+            if (axis) {
+                ends = axis.calcEnds();
+                if (axis.position == 'top' || axis.position == 'bottom') {
+                    minX = ends.from;
+                    maxX = ends.to;
+                }
+                else {
+                    minY = ends.from;
+                    maxY = ends.to;
+                }
+            }
+        }
+        
+        if (me.xField && !Ext.isNumber(minX)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.xField)
+            }).calcEnds();
+            minX = axis.from;
+            maxX = axis.to;
+        }
+        if (me.yField && !Ext.isNumber(minY)) {
+            axis = Ext.create('Ext.chart.axis.Axis', {
+                chart: chart,
+                fields: [].concat(me.yField)
+            }).calcEnds();
+            minY = axis.from;
+            maxY = axis.to;
+        }
+
+        if (isNaN(minX)) {
+            minX = 0;
+            maxX = store.getCount() - 1;
+            xScale = bbox.width / (store.getCount() - 1);
+        }
+        else {
+            xScale = bbox.width / (maxX - minX);
+        }
+
+        if (isNaN(minY)) {
+            minY = 0;
+            maxY = store.getCount() - 1;
+            yScale = bbox.height / (store.getCount() - 1);
+        }
+        else {
+            yScale = bbox.height / (maxY - minY);
+        }
+
+        return {
+            bbox: bbox,
+            minX: minX,
+            minY: minY,
+            xScale: xScale,
+            yScale: yScale
+        };
     },
 
     
-    removeElement : function(keys, removeDom){
+    getPaths: function() {
         var me = this,
-            els = this.elements,
-            el;
-        Ext.each(keys, function(val){
-            if ((el = (els[val] || els[val = me.indexOf(val)]))) {
-                if(removeDom){
-                    if(el.dom){
-                        el.remove();
-                    }else{
-                        Ext.removeNode(el);
+            chart = me.chart,
+            enableShadows = chart.shadow,
+            store = chart.getChartStore(),
+            group = me.group,
+            bounds = me.bounds = me.getBounds(),
+            bbox = me.bbox,
+            xScale = bounds.xScale,
+            yScale = bounds.yScale,
+            minX = bounds.minX,
+            minY = bounds.minY,
+            boxX = bbox.x,
+            boxY = bbox.y,
+            boxHeight = bbox.height,
+            items = me.items = [],
+            attrs = [],
+            x, y, xValue, yValue, sprite;
+
+        store.each(function(record, i) {
+            xValue = record.get(me.xField);
+            yValue = record.get(me.yField);
+            
+            if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
+                return;
+            }
+            
+            if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)) {
+                xValue = i;
+            }
+            if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)) {
+                yValue = i;
+            }
+            x = boxX + (xValue - minX) * xScale;
+            y = boxY + boxHeight - (yValue - minY) * yScale;
+            attrs.push({
+                x: x,
+                y: y
+            });
+
+            me.items.push({
+                series: me,
+                value: [xValue, yValue],
+                point: [x, y],
+                storeItem: record
+            });
+
+            
+            if (chart.animate && chart.resizing) {
+                sprite = group.getAt(i);
+                if (sprite) {
+                    me.resetPoint(sprite);
+                    if (enableShadows) {
+                        me.resetShadow(sprite);
                     }
                 }
-                els.splice(val, 1);
             }
         });
-        return this;
-    }
-});
+        return attrs;
+    },
 
-Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
     
-    constructor : function(els, root){
-        this.elements = [];
-        this.add(els, root);
+    resetPoint: function(sprite) {
+        var bbox = this.bbox;
+        sprite.setAttributes({
+            translate: {
+                x: (bbox.x + bbox.width) / 2,
+                y: (bbox.y + bbox.height) / 2
+            }
+        }, true);
     },
+
     
-    
-    getElement : function(el){
-        
-        return el;
+    resetShadow: function(sprite) {
+        var me = this,
+            shadows = sprite.shadows,
+            shadowAttributes = me.shadowAttributes,
+            ln = me.shadowGroups.length,
+            bbox = me.bbox,
+            i, attr;
+        for (i = 0; i < ln; i++) {
+            attr = Ext.apply({}, shadowAttributes[i]);
+            if (attr.translate) {
+                attr.translate.x += (bbox.x + bbox.width) / 2;
+                attr.translate.y += (bbox.y + bbox.height) / 2;
+            }
+            else {
+                attr.translate = {
+                    x: (bbox.x + bbox.width) / 2,
+                    y: (bbox.y + bbox.height) / 2
+                };
+            }
+            shadows[i].setAttributes(attr, true);
+        }
     },
-    
-    
-    transformElement : function(el){
-        return Ext.get(el);
-    }
 
     
+    createPoint: function(attr, type) {
+        var me = this,
+            chart = me.chart,
+            group = me.group,
+            bbox = me.bbox;
 
-    
+        return Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
+            x: 0,
+            y: 0,
+            group: group,
+            translate: {
+                x: (bbox.x + bbox.width) / 2,
+                y: (bbox.y + bbox.height) / 2
+            }
+        }, attr));
+    },
 
     
-});
-
-
-Ext.Element.select = function(selector, unique, root){
-    var els;
-    if(typeof selector == "string"){
-        els = Ext.Element.selectorFunction(selector, root);
-    }else if(selector.length !== undefined){
-        els = selector;
-    }else{
-        throw "Invalid selector";
-    }
-
-    return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
-};
+    createShadow: function(sprite, endMarkerStyle, type) {
+        var me = this,
+            chart = me.chart,
+            shadowGroups = me.shadowGroups,
+            shadowAttributes = me.shadowAttributes,
+            lnsh = shadowGroups.length,
+            bbox = me.bbox,
+            i, shadow, shadows, attr;
 
+        sprite.shadows = shadows = [];
 
-Ext.select = Ext.Element.select;(function(){
-    var BEFOREREQUEST = "beforerequest",
-        REQUESTCOMPLETE = "requestcomplete",
-        REQUESTEXCEPTION = "requestexception",
-        UNDEFINED = undefined,
-        LOAD = 'load',
-        POST = 'POST',
-        GET = 'GET',
-        WINDOW = window;
+        for (i = 0; i < lnsh; i++) {
+            attr = Ext.apply({}, shadowAttributes[i]);
+            if (attr.translate) {
+                attr.translate.x += (bbox.x + bbox.width) / 2;
+                attr.translate.y += (bbox.y + bbox.height) / 2;
+            }
+            else {
+                Ext.apply(attr, {
+                    translate: {
+                        x: (bbox.x + bbox.width) / 2,
+                        y: (bbox.y + bbox.height) / 2
+                    }
+                });
+            }
+            Ext.apply(attr, endMarkerStyle);
+            shadow = Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
+                x: 0,
+                y: 0,
+                group: shadowGroups[i]
+            }, attr));
+            shadows.push(shadow);
+        }
+    },
 
     
-    Ext.data.Connection = function(config){
-        Ext.apply(this, config);
-        this.addEvents(
-            
-            BEFOREREQUEST,
-            
-            REQUESTCOMPLETE,
-            
-            REQUESTEXCEPTION
-        );
-        Ext.data.Connection.superclass.constructor.call(this);
-    };
-
-    Ext.extend(Ext.data.Connection, Ext.util.Observable, {
-        
-        
-        
-        
-        
-        timeout : 30000,
-        
-        autoAbort:false,
+    drawSeries: function() {
+        var me = this,
+            chart = me.chart,
+            store = chart.getChartStore(),
+            group = me.group,
+            enableShadows = chart.shadow,
+            shadowGroups = me.shadowGroups,
+            shadowAttributes = me.shadowAttributes,
+            lnsh = shadowGroups.length,
+            sprite, attrs, attr, ln, i, endMarkerStyle, shindex, type, shadows,
+            rendererAttributes, shadowAttribute;
+
+        endMarkerStyle = Ext.apply(me.markerStyle, me.markerConfig);
+        type = endMarkerStyle.type;
+        delete endMarkerStyle.type;
+
+        
+        if (!store || !store.getCount()) {
+            return;
+        }
 
-        
-        disableCaching: true,
+        me.unHighlightItem();
+        me.cleanHighlights();
 
-        
-        disableCachingParam: '_dc',
+        attrs = me.getPaths();
+        ln = attrs.length;
+        for (i = 0; i < ln; i++) {
+            attr = attrs[i];
+            sprite = group.getAt(i);
+            Ext.apply(attr, endMarkerStyle);
 
-        
-        request : function(o){
-            var me = this;
-            if(me.fireEvent(BEFOREREQUEST, me, o)){
-                if (o.el) {
-                    if(!Ext.isEmpty(o.indicatorText)){
-                        me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
-                    }
-                    if(me.indicatorText) {
-                        Ext.getDom(o.el).innerHTML = me.indicatorText;
-                    }
-                    o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
-                        Ext.getDom(o.el).innerHTML = response.responseText;
-                    });
+            
+            if (!sprite) {
+                sprite = me.createPoint(attr, type);
+                if (enableShadows) {
+                    me.createShadow(sprite, endMarkerStyle, type);
                 }
+            }
 
-                var p = o.params,
-                    url = o.url || me.url,
-                    method,
-                    cb = {success: me.handleResponse,
-                          failure: me.handleFailure,
-                          scope: me,
-                          argument: {options: o},
-                          timeout : o.timeout || me.timeout
-                    },
-                    form,
-                    serForm;
-
-
-                if (Ext.isFunction(p)) {
-                    p = p.call(o.scope||WINDOW, o);
+            shadows = sprite.shadows;
+            if (chart.animate) {
+                rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
+                sprite._to = rendererAttributes;
+                me.onAnimate(sprite, {
+                    to: rendererAttributes
+                });
+                
+                for (shindex = 0; shindex < lnsh; shindex++) {
+                    shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
+                    rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { 
+                        hidden: false,
+                        translate: {
+                            x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
+                            y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
+                        }
+                    }, shadowAttribute), i, store);
+                    me.onAnimate(shadows[shindex], { to: rendererAttributes });
                 }
-
-                p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
-
-                if (Ext.isFunction(url)) {
-                    url = url.call(o.scope || WINDOW, o);
+            }
+            else {
+                rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
+                sprite._to = rendererAttributes;
+                sprite.setAttributes(rendererAttributes, true);
+                
+                for (shindex = 0; shindex < lnsh; shindex++) {
+                    shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
+                    rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { 
+                        hidden: false,
+                        translate: {
+                            x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
+                            y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
+                        } 
+                    }, shadowAttribute), i, store);
+                    shadows[shindex].setAttributes(rendererAttributes, true);
                 }
+            }
+            me.items[i].sprite = sprite;
+        }
 
-                if((form = Ext.getDom(o.form))){
-                    url = url || form.action;
-                     if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) {
-                         return me.doFormUpload.call(me, o, p, url);
-                     }
-                    serForm = Ext.lib.Ajax.serializeForm(form);
-                    p = p ? (p + '&' + serForm) : serForm;
-                }
+        
+        ln = group.getCount();
+        for (i = attrs.length; i < ln; i++) {
+            group.getAt(i).hide(true);
+        }
+        me.renderLabels();
+        me.renderCallouts();
+    },
 
-                method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
+    
+    onCreateLabel: function(storeItem, item, i, display) {
+        var me = this,
+            group = me.labelsGroup,
+            config = me.label,
+            endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle),
+            bbox = me.bbox;
 
-                if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
-                    var dcp = o.disableCachingParam || me.disableCachingParam;
-                    url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
-                }
+        return me.chart.surface.add(Ext.apply({
+            type: 'text',
+            group: group,
+            x: item.point[0],
+            y: bbox.y + bbox.height / 2
+        }, endLabelStyle));
+    },
 
-                o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
+    
+    onPlaceLabel: function(label, storeItem, item, i, display, animate) {
+        var me = this,
+            chart = me.chart,
+            resizing = chart.resizing,
+            config = me.label,
+            format = config.renderer,
+            field = config.field,
+            bbox = me.bbox,
+            x = item.point[0],
+            y = item.point[1],
+            radius = item.sprite.attr.radius,
+            bb, width, height, anim;
+
+        label.setAttributes({
+            text: format(storeItem.get(field)),
+            hidden: true
+        }, true);
 
-                if(o.autoAbort === true || me.autoAbort) {
-                    me.abort();
+        if (display == 'rotate') {
+            label.setAttributes({
+                'text-anchor': 'start',
+                'rotation': {
+                    x: x,
+                    y: y,
+                    degrees: -45
                 }
-
-                if((method == GET || o.xmlData || o.jsonData) && p){
-                    url = Ext.urlAppend(url, p);
-                    p = '';
+            }, true);
+            
+            bb = label.getBBox();
+            width = bb.width;
+            height = bb.height;
+            x = x < bbox.x? bbox.x : x;
+            x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
+            y = (y - height < bbox.y)? bbox.y + height : y;
+
+        } else if (display == 'under' || display == 'over') {
+            
+            bb = item.sprite.getBBox();
+            bb.width = bb.width || (radius * 2);
+            bb.height = bb.height || (radius * 2);
+            y = y + (display == 'over'? -bb.height : bb.height);
+            
+            bb = label.getBBox();
+            width = bb.width/2;
+            height = bb.height/2;
+            x = x - width < bbox.x ? bbox.x + width : x;
+            x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
+            y = y - height < bbox.y? bbox.y + height : y;
+            y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
+        }
+
+        if (!chart.animate) {
+            label.setAttributes({
+                x: x,
+                y: y
+            }, true);
+            label.show(true);
+        }
+        else {
+            if (resizing) {
+                anim = item.sprite.getActiveAnimation();
+                if (anim) {
+                    anim.on('afteranimate', function() {
+                        label.setAttributes({
+                            x: x,
+                            y: y
+                        }, true);
+                        label.show(true);
+                    });
+                }
+                else {
+                    label.show(true);
                 }
-                return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
-            }else{
-                return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
             }
-        },
+            else {
+                me.onAnimate(label, {
+                    to: {
+                        x: x,
+                        y: y
+                    }
+                });
+            }
+        }
+    },
+
+    
+    onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
+        var me = this,
+            chart = me.chart,
+            surface = chart.surface,
+            resizing = chart.resizing,
+            config = me.callouts,
+            items = me.items,
+            cur = item.point,
+            normal,
+            bbox = callout.label.getBBox(),
+            offsetFromViz = 30,
+            offsetToSide = 10,
+            offsetBox = 3,
+            boxx, boxy, boxw, boxh,
+            p, clipRect = me.bbox,
+            x, y;
 
         
-        isLoading : function(transId){
-            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;
-        },
+        normal = [Math.cos(Math.PI /4), -Math.sin(Math.PI /4)];
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
         
-        abort : function(transId){
-            if(transId || this.isLoading()){
-                Ext.lib.Ajax.abort(transId || this.transId);
-            }
-        },
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
         
-        handleResponse : function(response){
-            this.transId = false;
-            var options = response.argument.options;
-            response.argument = options ? options.argument : null;
-            this.fireEvent(REQUESTCOMPLETE, this, response, options);
-            if(options.success){
-                options.success.call(options.scope, response, options);
-            }
-            if(options.callback){
-                options.callback.call(options.scope, options, true, response);
-            }
-        },
+        
+        if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
+            normal[0] *= -1;
+        }
+        if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
+            normal[1] *= -1;
+        }
 
         
-        handleFailure : function(response, e){
-            this.transId = false;
-            var options = response.argument.options;
-            response.argument = options ? options.argument : null;
-            this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
-            if(options.failure){
-                options.failure.call(options.scope, response, options);
-            }
-            if(options.callback){
-                options.callback.call(options.scope, options, false, response);
-            }
-        },
+        x = cur[0] + normal[0] * offsetFromViz;
+        y = cur[1] + normal[1] * offsetFromViz;
 
         
-        doFormUpload : function(o, ps, url){
-            var id = Ext.id(),
-                doc = document,
-                frame = doc.createElement('iframe'),
-                form = Ext.getDom(o.form),
-                hiddens = [],
-                hd,
-                encoding = 'multipart/form-data',
-                buf = {
-                    target: form.target,
-                    method: form.method,
-                    encoding: form.encoding,
-                    enctype: form.enctype,
-                    action: form.action
-                };
+        boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
+        boxy = y - bbox.height /2 - offsetBox;
+        boxw = bbox.width + 2 * offsetBox;
+        boxh = bbox.height + 2 * offsetBox;
 
+        if (chart.animate) {
             
-            Ext.fly(frame).set({
-                id: id,
-                name: id,
-                cls: 'x-hidden',
-                src: Ext.SSL_SECURE_URL
-            }); 
+            me.onAnimate(callout.lines, {
+                to: {
+                    path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+                }
+            }, true);
+            
+            me.onAnimate(callout.box, {
+                to: {
+                    x: boxx,
+                    y: boxy,
+                    width: boxw,
+                    height: boxh
+                }
+            }, true);
+            
+            me.onAnimate(callout.label, {
+                to: {
+                    x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+                    y: y
+                }
+            }, true);
+        } else {
+            
+            callout.lines.setAttributes({
+                path: ["M", cur[0], cur[1], "L", x, y, "Z"]
+            }, true);
+            
+            callout.box.setAttributes({
+                x: boxx,
+                y: boxy,
+                width: boxw,
+                height: boxh
+            }, true);
+            
+            callout.label.setAttributes({
+                x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
+                y: y
+            }, true);
+        }
+        for (p in callout) {
+            callout[p].show(true);
+        }
+    },
 
-            doc.body.appendChild(frame);
+    
+    onAnimate: function(sprite, attr) {
+        sprite.show();
+        return this.callParent(arguments);
+    },
 
-            
-            if(Ext.isIE){
-               document.frames[id].name = id;
-            }
+    isItemInPoint: function(x, y, item) {
+        var point,
+            tolerance = 10,
+            abs = Math.abs;
 
+        function dist(point) {
+            var dx = abs(point[0] - x),
+                dy = abs(point[1] - y);
+            return Math.sqrt(dx * dx + dy * dy);
+        }
+        point = item.point;
+        return (point[0] - tolerance <= x && point[0] + tolerance >= x &&
+            point[1] - tolerance <= y && point[1] + tolerance >= y);
+    }
+});
 
-            Ext.fly(form).set({
-                target: id,
-                method: POST,
-                enctype: encoding,
-                encoding: encoding,
-                action: url || buf.action
-            });
 
-            
-            Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
-                hd = doc.createElement('input');
-                Ext.fly(hd).set({
-                    type: 'hidden',
-                    value: v,
-                    name: k
-                });
-                form.appendChild(hd);
-                hiddens.push(hd);
-            });
 
-            function cb(){
-                var me = this,
-                    
-                    r = {responseText : '',
-                         responseXML : null,
-                         argument : o.argument},
-                    doc,
-                    firstChild;
+Ext.define('Ext.chart.theme.Base', {
 
-                try{
-                    doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
-                    if(doc){
-                        if(doc.body){
-                            if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ 
-                                r.responseText = firstChild.value;
-                            }else{
-                                r.responseText = doc.body.innerHTML;
-                            }
-                        }
-                        
-                        r.responseXML = doc.XMLDocument || doc;
-                    }
-                }
-                catch(e) {}
+    
 
-                Ext.EventManager.removeListener(frame, LOAD, cb, me);
+    requires: ['Ext.chart.theme.Theme'],
 
-                me.fireEvent(REQUESTCOMPLETE, me, r, o);
+    
 
-                function runCallback(fn, scope, args){
-                    if(Ext.isFunction(fn)){
-                        fn.apply(scope, args);
-                    }
+    constructor: function(config) {
+        Ext.chart.theme.call(this, config, {
+            background: false,
+            axis: {
+                stroke: '#444',
+                'stroke-width': 1
+            },
+            axisLabelTop: {
+                fill: '#444',
+                font: '12px Arial, Helvetica, sans-serif',
+                spacing: 2,
+                padding: 5,
+                renderer: function(v) { return v; }
+            },
+            axisLabelRight: {
+                fill: '#444',
+                font: '12px Arial, Helvetica, sans-serif',
+                spacing: 2,
+                padding: 5,
+                renderer: function(v) { return v; }
+            },
+            axisLabelBottom: {
+                fill: '#444',
+                font: '12px Arial, Helvetica, sans-serif',
+                spacing: 2,
+                padding: 5,
+                renderer: function(v) { return v; }
+            },
+            axisLabelLeft: {
+                fill: '#444',
+                font: '12px Arial, Helvetica, sans-serif',
+                spacing: 2,
+                padding: 5,
+                renderer: function(v) { return v; }
+            },
+            axisTitleTop: {
+                font: 'bold 18px Arial',
+                fill: '#444'
+            },
+            axisTitleRight: {
+                font: 'bold 18px Arial',
+                fill: '#444',
+                rotate: {
+                    x:0, y:0,
+                    degrees: 270
+                }
+            },
+            axisTitleBottom: {
+                font: 'bold 18px Arial',
+                fill: '#444'
+            },
+            axisTitleLeft: {
+                font: 'bold 18px Arial',
+                fill: '#444',
+                rotate: {
+                    x:0, y:0,
+                    degrees: 270
+                }
+            },
+            series: {
+                'stroke-width': 0
+            },
+            seriesLabel: {
+                font: '12px Arial',
+                fill: '#333'
+            },
+            marker: {
+                stroke: '#555',
+                fill: '#000',
+                radius: 3,
+                size: 3
+            },
+            colors: [ "#94ae0a", "#115fa6","#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
+            seriesThemes: [{
+                fill: "#115fa6"
+            }, {
+                fill: "#94ae0a"
+            }, {
+                fill: "#a61120"
+            }, {
+                fill: "#ff8809"
+            }, {
+                fill: "#ffd13e"
+            }, {
+                fill: "#a61187"
+            }, {
+                fill: "#24ad9a"
+            }, {
+                fill: "#7c7474"
+            }, {
+                fill: "#a66111"
+            }],
+            markerThemes: [{
+                fill: "#115fa6",
+                type: 'circle' 
+            }, {
+                fill: "#94ae0a",
+                type: 'cross'
+            }, {
+                fill: "#a61120",
+                type: 'plus'
+            }]
+        });
+    }
+}, function() {
+    var palette = ['#b1da5a', '#4ce0e7', '#e84b67', '#da5abd', '#4d7fe6', '#fec935'],
+        names = ['Green', 'Sky', 'Red', 'Purple', 'Blue', 'Yellow'],
+        i = 0, j = 0, l = palette.length, themes = Ext.chart.theme,
+        categories = [['#f0a50a', '#c20024', '#2044ba', '#810065', '#7eae29'],
+                      ['#6d9824', '#87146e', '#2a9196', '#d39006', '#1e40ac'],
+                      ['#fbbc29', '#ce2e4e', '#7e0062', '#158b90', '#57880e'],
+                      ['#ef5773', '#fcbd2a', '#4f770d', '#1d3eaa', '#9b001f'],
+                      ['#7eae29', '#fdbe2a', '#910019', '#27b4bc', '#d74dbc'],
+                      ['#44dce1', '#0b2592', '#996e05', '#7fb325', '#b821a1']],
+        cats = categories.length;
+    
+    
+    for (; i < l; i++) {
+        themes[names[i]] = (function(color) {
+            return Ext.extend(themes.Base, {
+                constructor: function(config) {
+                    themes.Base.prototype.constructor.call(this, Ext.apply({
+                        baseColor: color
+                    }, config));
+                }
+            });
+        })(palette[i]);
+    }
+    
+    
+    for (i = 0; i < cats; i++) {
+        themes['Category' + (i + 1)] = (function(category) {
+            return Ext.extend(themes.Base, {
+                constructor: function(config) {
+                    themes.Base.prototype.constructor.call(this, Ext.apply({
+                        colors: category
+                    }, config));
                 }
+            });
+        })(categories[i]);
+    }
+});
 
-                runCallback(o.success, o.scope, [r, o]);
-                runCallback(o.callback, o.scope, [o, true, r]);
 
-                if(!me.debugUploads){
-                    setTimeout(function(){Ext.removeNode(frame);}, 100);
-                }
+Ext.define('Ext.data.ArrayStore', {
+    extend: 'Ext.data.Store',
+    alias: 'store.array',
+    uses: ['Ext.data.reader.Array'],
+
+    constructor: function(config) {
+        config = config || {};
+
+        Ext.applyIf(config, {
+            proxy: {
+                type: 'memory',
+                reader: 'array'
             }
+        });
 
-            Ext.EventManager.on(frame, LOAD, cb, this);
-            form.submit();
+        this.callParent([config]);
+    },
 
-            Ext.fly(form).set(buf);
-            Ext.each(hiddens, function(h) {
-                Ext.removeNode(h);
-            });
-        }
-    });
-})();
+    loadData: function(data, append) {
+        if (this.expandData === true) {
+            var r = [],
+                i = 0,
+                ln = data.length;
+
+            for (; i < ln; i++) {
+                r[r.length] = [data[i]];
+            }
 
+            data = r;
+        }
 
-Ext.Ajax = new Ext.data.Connection({
+        this.callParent([data, append]);
+    }
+}, function() {
     
+    Ext.data.SimpleStore = Ext.data.ArrayStore;
     
+});
+
+
+Ext.define('Ext.data.Batch', {
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
     
+    autoStart: false,
+
     
+    current: -1,
+
     
+    total: 0,
+
     
+    isRunning: false,
 
     
+    isComplete: false,
 
     
+    hasException: false,
+
     
+    pauseOnException: true,
+
     
+    constructor: function(config) {
+        var me = this;
+
+        me.addEvents(
+          
+          'complete',
+
+          
+          'exception',
+
+          
+          'operationcomplete'
+        );
+
+        me.mixins.observable.constructor.call(me, config);
+
+        
+        me.operations = [];
+    },
+
     
+    add: function(operation) {
+        this.total++;
+
+        operation.setBatch(this);
+
+        this.operations.push(operation);
+    },
+
     
+    start: function() {
+        this.hasException = false;
+        this.isRunning = true;
+
+        this.runNextOperation();
+    },
+
     
+    runNextOperation: function() {
+        this.runOperation(this.current + 1);
+    },
 
     
-    autoAbort : false,
+    pause: function() {
+        this.isRunning = false;
+    },
 
     
-    serializeForm : function(form){
-        return Ext.lib.Ajax.serializeForm(form);
+    runOperation: function(index) {
+        var me = this,
+            operations = me.operations,
+            operation  = operations[index],
+            onProxyReturn;
+
+        if (operation === undefined) {
+            me.isRunning  = false;
+            me.isComplete = true;
+            me.fireEvent('complete', me, operations[operations.length - 1]);
+        } else {
+            me.current = index;
+
+            onProxyReturn = function(operation) {
+                var hasException = operation.hasException();
+
+                if (hasException) {
+                    me.hasException = true;
+                    me.fireEvent('exception', me, operation);
+                } else {
+                    me.fireEvent('operationcomplete', me, operation);
+                }
+
+                if (hasException && me.pauseOnException) {
+                    me.pause();
+                } else {
+                    operation.setCompleted();
+                    me.runNextOperation();
+                }
+            };
+
+            operation.setStarted();
+
+            me.proxy[operation.action](operation, onProxyReturn, me);
+        }
     }
 });
 
-Ext.UpdateManager = Ext.Updater = Ext.extend(Ext.util.Observable,
-function() {
-    var BEFOREUPDATE = "beforeupdate",
-        UPDATE = "update",
-        FAILURE = "failure";
+Ext.define('Ext.data.BelongsToAssociation', {
+    extend: 'Ext.data.Association',
+
+    alias: 'association.belongsto',
 
     
-    function processSuccess(response){
-        var me = this;
-        me.transaction = null;
-        if (response.argument.form && response.argument.reset) {
-            try { 
-                response.argument.form.reset();
-            } catch(e){}
-        }
-        if (me.loadScripts) {
-            me.renderer.render(me.el, response, me,
-               updateComplete.createDelegate(me, [response]));
-        } else {
-            me.renderer.render(me.el, response, me);
-            updateComplete.call(me, response);
-        }
-    }
 
     
-    function updateComplete(response, type, success){
-        this.fireEvent(type || UPDATE, this.el, response);
-        if(Ext.isFunction(response.argument.callback)){
-            response.argument.callback.call(response.argument.scope, this.el, Ext.isEmpty(success) ? true : false, response, response.argument.options);
-        }
-    }
 
     
-    function processFailure(response){
-        updateComplete.call(this, response, FAILURE, !!(this.transaction = null));
-    }
 
-    return {
-        constructor: function(el, forceNew){
-            var me = this;
-            el = Ext.get(el);
-            if(!forceNew && el.updateManager){
-                return el.updateManager;
-            }
-            
-            me.el = el;
-            
-            me.defaultUrl = null;
+    
+    constructor: function(config) {
+        this.callParent(arguments);
+
+        var me             = this,
+            ownerProto     = me.ownerModel.prototype,
+            associatedName = me.associatedName,
+            getterName     = me.getterName || 'get' + associatedName,
+            setterName     = me.setterName || 'set' + associatedName;
+
+        Ext.applyIf(me, {
+            name        : associatedName,
+            foreignKey  : associatedName.toLowerCase() + "_id",
+            instanceName: associatedName + 'BelongsToInstance',
+            associationKey: associatedName.toLowerCase()
+        });
 
-            me.addEvents(
-                
-                BEFOREUPDATE,
-                
-                UPDATE,
-                
-                FAILURE
-            );
+        ownerProto[getterName] = me.createGetter();
+        ownerProto[setterName] = me.createSetter();
+    },
 
-            Ext.apply(me, Ext.Updater.defaults);
-            
-            
-            
-            
-            
-            
+    
+    createSetter: function() {
+        var me              = this,
+            ownerModel      = me.ownerModel,
+            associatedModel = me.associatedModel,
+            foreignKey      = me.foreignKey,
+            primaryKey      = me.primaryKey;
 
-            
-            me.transaction = null;
-            
-            me.refreshDelegate = me.refresh.createDelegate(me);
-            
-            me.updateDelegate = me.update.createDelegate(me);
-            
-            me.formUpdateDelegate = (me.formUpdate || function(){}).createDelegate(me);
+        
+        return function(value, options, scope) {
+            this.set(foreignKey, value);
 
-            
-            me.renderer = me.renderer || me.getDefaultRenderer();
+            if (typeof options == 'function') {
+                options = {
+                    callback: options,
+                    scope: scope || this
+                };
+            }
 
-            Ext.Updater.superclass.constructor.call(me);
-        },
+            if (Ext.isObject(options)) {
+                return this.save(options);
+            }
+        };
+    },
 
-        
-        setRenderer : function(renderer){
-            this.renderer = renderer;
-        },
+    
+    createGetter: function() {
+        var me              = this,
+            ownerModel      = me.ownerModel,
+            associatedName  = me.associatedName,
+            associatedModel = me.associatedModel,
+            foreignKey      = me.foreignKey,
+            primaryKey      = me.primaryKey,
+            instanceName    = me.instanceName;
 
         
-        getRenderer : function(){
-           return this.renderer;
-        },
+        return function(options, scope) {
+            options = options || {};
 
-        
-        getDefaultRenderer: function() {
-            return new Ext.Updater.BasicRenderer();
-        },
+            var model = this,
+                foreignKeyId = model.get(foreignKey),
+                instance,
+                args;
 
-        
-        setDefaultUrl : function(defaultUrl){
-            this.defaultUrl = defaultUrl;
-        },
+            if (model[instanceName] === undefined) {
+                instance = Ext.ModelManager.create({}, associatedName);
+                instance.set(primaryKey, foreignKeyId);
 
-        
-        getEl : function(){
-            return this.el;
-        },
+                if (typeof options == 'function') {
+                    options = {
+                        callback: options,
+                        scope: scope || model
+                    };
+                }
 
-        
-        update : function(url, params, callback, discardUrl){
-            var me = this,
-                cfg,
-                callerScope;
-
-            if(me.fireEvent(BEFOREUPDATE, me.el, url, params) !== false){
-                if(Ext.isObject(url)){ 
-                    cfg = url;
-                    url = cfg.url;
-                    params = params || cfg.params;
-                    callback = callback || cfg.callback;
-                    discardUrl = discardUrl || cfg.discardUrl;
-                    callerScope = cfg.scope;
-                    if(!Ext.isEmpty(cfg.nocache)){me.disableCaching = cfg.nocache;};
-                    if(!Ext.isEmpty(cfg.text)){me.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
-                    if(!Ext.isEmpty(cfg.scripts)){me.loadScripts = cfg.scripts;};
-                    if(!Ext.isEmpty(cfg.timeout)){me.timeout = cfg.timeout;};
-                }
-                me.showLoading();
-
-                if(!discardUrl){
-                    me.defaultUrl = url;
-                }
-                if(Ext.isFunction(url)){
-                    url = url.call(me);
-                }
-
-                var o = Ext.apply({}, {
-                    url : url,
-                    params: (Ext.isFunction(params) && callerScope) ? params.createDelegate(callerScope) : params,
-                    success: processSuccess,
-                    failure: processFailure,
-                    scope: me,
-                    callback: undefined,
-                    timeout: (me.timeout*1000),
-                    disableCaching: me.disableCaching,
-                    argument: {
-                        "options": cfg,
-                        "url": url,
-                        "form": null,
-                        "callback": callback,
-                        "scope": callerScope || window,
-                        "params": params
-                    }
-                }, cfg);
+                associatedModel.load(foreignKeyId, options);
+                model[instanceName] = associatedModel;
+                return associatedModel;
+            } else {
+                instance = model[instanceName];
+                args = [instance];
+                scope = scope || model;
 
-                me.transaction = Ext.Ajax.request(o);
-            }
-        },
+                
+                
+                
+                Ext.callback(options, scope, args);
+                Ext.callback(options.success, scope, args);
+                Ext.callback(options.failure, scope, args);
+                Ext.callback(options.callback, scope, args);
 
-        
-        formUpdate : function(form, url, reset, callback){
-            var me = this;
-            if(me.fireEvent(BEFOREUPDATE, me.el, form, url) !== false){
-                if(Ext.isFunction(url)){
-                    url = url.call(me);
-                }
-                form = Ext.getDom(form);
-                me.transaction = Ext.Ajax.request({
-                    form: form,
-                    url:url,
-                    success: processSuccess,
-                    failure: processFailure,
-                    scope: me,
-                    timeout: (me.timeout*1000),
-                    argument: {
-                        "url": url,
-                        "form": form,
-                        "callback": callback,
-                        "reset": reset
-                    }
-                });
-                me.showLoading.defer(1, me);
+                return instance;
             }
-        },
+        };
+    },
 
-        
-        startAutoRefresh : function(interval, url, params, callback, refreshNow){
-            var me = this;
-            if(refreshNow){
-                me.update(url || me.defaultUrl, params, callback, true);
-            }
-            if(me.autoRefreshProcId){
-                clearInterval(me.autoRefreshProcId);
-            }
-            me.autoRefreshProcId = setInterval(me.update.createDelegate(me, [url || me.defaultUrl, params, callback, true]), interval * 1000);
-        },
+    
+    read: function(record, reader, associationData){
+        record[this.instanceName] = reader.read([associationData]).records[0];
+    }
+});
 
-        
-        stopAutoRefresh : function(){
-            if(this.autoRefreshProcId){
-                clearInterval(this.autoRefreshProcId);
-                delete this.autoRefreshProcId;
-            }
-        },
 
-        
-        isAutoRefreshing : function(){
-           return !!this.autoRefreshProcId;
-        },
+Ext.define('Ext.data.BufferStore', {
+    extend: 'Ext.data.Store',
+    alias: 'store.buffer',
+    sortOnLoad: false,
+    filterOnLoad: false,
+    
+    constructor: function() {
+        Ext.Error.raise('The BufferStore class has been deprecated. Instead, specify the buffered config option on Ext.data.Store');
+    }
+});
 
-        
-        showLoading : function(){
-            if(this.showLoadIndicator){
-                this.el.dom.innerHTML = this.indicatorText;
-            }
-        },
+Ext.define('Ext.direct.Manager', {
+
+    
+    singleton: true,
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    requires: ['Ext.util.MixedCollection'],
+
+    statics: {
+        exceptions: {
+            TRANSPORT: 'xhr',
+            PARSE: 'parse',
+            LOGIN: 'login',
+            SERVER: 'exception'
+        }
+    },
+
+    
+
+    constructor: function(){
+        var me = this;
+
+        me.addEvents(
+            
+            'event',
+            
+            'exception'
+        );
+        me.transactions = Ext.create('Ext.util.MixedCollection');
+        me.providers = Ext.create('Ext.util.MixedCollection');
+
+        me.mixins.observable.constructor.call(me);
+    },
+
+    
+    addProvider : function(provider){
+        var me = this,
+            args = arguments,
+            i = 0,
+            len;
 
-        
-        abort : function(){
-            if(this.transaction){
-                Ext.Ajax.abort(this.transaction);
+        if (args.length > 1) {
+            for (len = args.length; i < len; ++i) {
+                me.addProvider(args[i]);
             }
-        },
+            return;
+        }
 
         
-        isUpdating : function(){
-            return this.transaction ? Ext.Ajax.isLoading(this.transaction) : false;
-        },
+        if (!provider.isProvider) {
+            provider = Ext.create('direct.' + provider.type + 'provider', provider);
+        }
+        me.providers.add(provider);
+        provider.on('data', me.onProviderData, me);
 
-        
-        refresh : function(callback){
-            if(this.defaultUrl){
-                this.update(this.defaultUrl, null, callback, true);
-            }
+
+        if (!provider.isConnected()) {
+            provider.connect();
         }
-    }
-}());
 
+        return provider;
+    },
 
-Ext.Updater.defaults = {
-   
-    timeout : 30,
     
-    disableCaching : false,
-    
-    showLoadIndicator : true,
-    
-    indicatorText : '<div class="loading-indicator">Loading...</div>',
-     
-    loadScripts : false,
-    
-    sslBlankUrl : Ext.SSL_SECURE_URL
-};
+    getProvider : function(id){
+        return id.isProvider ? id : this.providers.get(id);
+    },
 
+    
+    removeProvider : function(provider){
+        var me = this,
+            providers = me.providers;
 
+        provider = provider.isProvider ? provider : providers.get(provider);
 
-Ext.Updater.updateElement = function(el, url, params, options){
-    var um = Ext.get(el).getUpdater();
-    Ext.apply(um, options);
-    um.update(url, params, options ? options.callback : null);
-};
+        if (provider) {
+            provider.un('data', me.onProviderData, me);
+            providers.remove(provider);
+            return provider;
+        }
+        return null;
+    },
 
+    
+    addTransaction: function(transaction){
+        this.transactions.add(transaction);
+        return transaction;
+    },
 
-Ext.Updater.BasicRenderer = function(){};
+    
+    removeTransaction: function(transaction){
+        transaction = this.getTransaction(transaction);
+        this.transactions.remove(transaction);
+        return transaction;
+    },
 
-Ext.Updater.BasicRenderer.prototype = {
     
-     render : function(el, response, updateManager, callback){
-        el.update(response.responseText, updateManager.loadScripts, callback);
-    }
-};
+    getTransaction: function(transaction){
+        return transaction.isTransaction ? transaction : this.transactions.get(transaction);
+    },
 
+    onProviderData : function(provider, event){
+        var me = this,
+            i = 0,
+            len;
 
+        if (Ext.isArray(event)) {
+            for (len = event.length; i < len; ++i) {
+                me.onProviderData(provider, event[i]);
+            }
+            return;
+        }
+        if (event.name && event.name != 'event' && event.name != 'exception') {
+            me.fireEvent(event.name, event);
+        } else if (event.status === false) {
+            me.fireEvent('exception', event);
+        }
+        me.fireEvent('event', event, provider);
+    }
+}, function(){
+    
+    Ext.Direct = Ext.direct.Manager;
+});
 
-(function() {
 
+Ext.define('Ext.data.proxy.Direct', {
+    
 
-Date.useStrict = false;
+    extend: 'Ext.data.proxy.Server',
+    alternateClassName: 'Ext.data.DirectProxy',
 
+    alias: 'proxy.direct',
 
+    requires: ['Ext.direct.Manager'],
 
+    
 
+    
+    paramOrder: undefined,
 
-function xf(format) {
-    var args = Array.prototype.slice.call(arguments, 1);
-    return format.replace(/\{(\d+)\}/g, function(m, i) {
-        return args[i];
-    });
-}
+    
+    paramsAsHash: true,
 
+    
+    directFn : undefined,
 
+    
 
-Date.formatCodeToRegex = function(character, currentGroup) {
     
-    var p = Date.parseCodes[character];
 
-    if (p) {
-      p = typeof p == 'function'? p() : p;
-      Date.parseCodes[character] = p; 
-    }
+    
+    paramOrderRe: /[\s,|]/,
 
-    return p ? Ext.applyIf({
-      c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
-    }, p) : {
-        g:0,
-        c:null,
-        s:Ext.escapeRe(character) 
-    }
-};
+    constructor: function(config){
+        var me = this;
+
+        Ext.apply(me, config);
+        if (Ext.isString(me.paramOrder)) {
+            me.paramOrder = me.paramOrder.split(me.paramOrderRe);
+        }
+        me.callParent(arguments);
+    },
+
+    doRequest: function(operation, callback, scope) {
+        var me = this,
+            writer = me.getWriter(),
+            request = me.buildRequest(operation, callback, scope),
+            fn = me.api[request.action]  || me.directFn,
+            args = [],
+            params = request.params,
+            paramOrder = me.paramOrder,
+            method,
+            i = 0,
+            len;
 
 
-var $f = Date.formatCodeToRegex;
+        if (operation.allowWrite()) {
+            request = writer.write(request);
+        }
 
-Ext.apply(Date, {
-    
-    parseFunctions: {
-        "M$": function(input, strict) {
-            
+        if (operation.action == 'read') {
             
-            var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
-            var r = (input || '').match(re);
-            return r? new Date(((r[1] || '') + r[2]) * 1) : null;
+            method = fn.directCfg.method;
+
+            if (method.ordered) {
+                if (method.len > 0) {
+                    if (paramOrder) {
+                        for (len = paramOrder.length; i < len; ++i) {
+                            args.push(params[paramOrder[i]]);
+                        }
+                    } else if (me.paramsAsHash) {
+                        args.push(params);
+                    }
+                }
+            } else {
+                args.push(params);
+            }
+        } else {
+            args.push(request.jsonData);
         }
+
+        Ext.apply(request, {
+            args: args,
+            directFn: fn
+        });
+        args.push(me.createRequestCallback(request, operation, callback, scope), me);
+        fn.apply(window, args);
     },
-    parseRegexes: [],
 
     
-    formatFunctions: {
-        "M$": function() {
-            
-            return '\\/Date(' + this.getTime() + ')\\/';
-        }
+    applyEncoding: function(value){
+        return value;
     },
 
-    y2kYear : 50,
+    createRequestCallback: function(request, operation, callback, scope){
+        var me = this;
 
-    
-    MILLI : "ms",
+        return function(data, event){
+            me.processResponse(event.status, operation, request, event, callback, scope);
+        };
+    },
 
     
-    SECOND : "s",
+    extractResponseData: function(response){
+        return Ext.isDefined(response.result) ? response.result : response.data;
+    },
 
     
-    MINUTE : "mi",
+    setException: function(operation, response) {
+        operation.setException(response.message);
+    },
 
     
-    HOUR : "h",
+    buildUrl: function(){
+        return '';
+    }
+});
 
+
+Ext.define('Ext.data.DirectStore', {
     
-    DAY : "d",
+    
+    extend: 'Ext.data.Store',
+    
+    alias: 'store.direct',
+    
+    requires: ['Ext.data.proxy.Direct'],
+   
+    
+
+    constructor : function(config){
+        config = Ext.apply({}, config);
+        if (!config.proxy) {
+            var proxy = {
+                type: 'direct',
+                reader: {
+                    type: 'json'
+                }
+            };
+            Ext.copyTo(proxy, config, 'paramOrder,paramsAsHash,directFn,api,simpleSortMode');
+            Ext.copyTo(proxy.reader, config, 'totalProperty,root,idProperty');
+            config.proxy = proxy;
+        }
+        this.callParent([config]);
+    }    
+});
+
+
+Ext.define('Ext.util.Inflector', {
 
     
-    MONTH : "mo",
+
+    singleton: true,
 
     
-    YEAR : "y",
 
     
-    defaults: {},
+    plurals: [
+        [(/(quiz)$/i),                "$1zes"  ],
+        [(/^(ox)$/i),                 "$1en"   ],
+        [(/([m|l])ouse$/i),           "$1ice"  ],
+        [(/(matr|vert|ind)ix|ex$/i),  "$1ices" ],
+        [(/(x|ch|ss|sh)$/i),          "$1es"   ],
+        [(/([^aeiouy]|qu)y$/i),       "$1ies"  ],
+        [(/(hive)$/i),                "$1s"    ],
+        [(/(?:([^f])fe|([lr])f)$/i),  "$1$2ves"],
+        [(/sis$/i),                   "ses"    ],
+        [(/([ti])um$/i),              "$1a"    ],
+        [(/(buffal|tomat|potat)o$/i), "$1oes"  ],
+        [(/(bu)s$/i),                 "$1ses"  ],
+        [(/(alias|status|sex)$/i),    "$1es"   ],
+        [(/(octop|vir)us$/i),         "$1i"    ],
+        [(/(ax|test)is$/i),           "$1es"   ],
+        [(/^person$/),                "people" ],
+        [(/^man$/),                   "men"    ],
+        [(/^(child)$/),               "$1ren"  ],
+        [(/s$/i),                     "s"      ],
+        [(/$/),                       "s"      ]
+    ],
 
     
-    dayNames : [
-        "Sunday",
-        "Monday",
-        "Tuesday",
-        "Wednesday",
-        "Thursday",
-        "Friday",
-        "Saturday"
+    singulars: [
+      [(/(quiz)zes$/i),                                                    "$1"     ],
+      [(/(matr)ices$/i),                                                   "$1ix"   ],
+      [(/(vert|ind)ices$/i),                                               "$1ex"   ],
+      [(/^(ox)en/i),                                                       "$1"     ],
+      [(/(alias|status)es$/i),                                             "$1"     ],
+      [(/(octop|vir)i$/i),                                                 "$1us"   ],
+      [(/(cris|ax|test)es$/i),                                             "$1is"   ],
+      [(/(shoe)s$/i),                                                      "$1"     ],
+      [(/(o)es$/i),                                                        "$1"     ],
+      [(/(bus)es$/i),                                                      "$1"     ],
+      [(/([m|l])ice$/i),                                                   "$1ouse" ],
+      [(/(x|ch|ss|sh)es$/i),                                               "$1"     ],
+      [(/(m)ovies$/i),                                                     "$1ovie" ],
+      [(/(s)eries$/i),                                                     "$1eries"],
+      [(/([^aeiouy]|qu)ies$/i),                                            "$1y"    ],
+      [(/([lr])ves$/i),                                                    "$1f"    ],
+      [(/(tive)s$/i),                                                      "$1"     ],
+      [(/(hive)s$/i),                                                      "$1"     ],
+      [(/([^f])ves$/i),                                                    "$1fe"   ],
+      [(/(^analy)ses$/i),                                                  "$1sis"  ],
+      [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
+      [(/([ti])a$/i),                                                      "$1um"   ],
+      [(/(n)ews$/i),                                                       "$1ews"  ],
+      [(/people$/i),                                                       "person" ],
+      [(/s$/i),                                                            ""       ]
     ],
 
     
-    monthNames : [
-        "January",
-        "February",
-        "March",
-        "April",
-        "May",
-        "June",
-        "July",
-        "August",
-        "September",
-        "October",
-        "November",
-        "December"
+     uncountable: [
+        "sheep",
+        "fish",
+        "series",
+        "species",
+        "money",
+        "rice",
+        "information",
+        "equipment",
+        "grass",
+        "mud",
+        "offspring",
+        "deer",
+        "means"
     ],
 
     
-    monthNumbers : {
-        Jan:0,
-        Feb:1,
-        Mar:2,
-        Apr:3,
-        May:4,
-        Jun:5,
-        Jul:6,
-        Aug:7,
-        Sep:8,
-        Oct:9,
-        Nov:10,
-        Dec:11
+    singular: function(matcher, replacer) {
+        this.singulars.unshift([matcher, replacer]);
     },
 
     
-    getShortMonthName : function(month) {
-        return Date.monthNames[month].substring(0, 3);
+    plural: function(matcher, replacer) {
+        this.plurals.unshift([matcher, replacer]);
     },
 
     
-    getShortDayName : function(day) {
-        return Date.dayNames[day].substring(0, 3);
+    clearSingulars: function() {
+        this.singulars = [];
     },
 
     
-    getMonthNumber : function(name) {
-        
-        return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
+    clearPlurals: function() {
+        this.plurals = [];
     },
 
     
-    formatCodes : {
-        d: "String.leftPad(this.getDate(), 2, '0')",
-        D: "Date.getShortDayName(this.getDay())", 
-        j: "this.getDate()",
-        l: "Date.dayNames[this.getDay()]",
-        N: "(this.getDay() ? this.getDay() : 7)",
-        S: "this.getSuffix()",
-        w: "this.getDay()",
-        z: "this.getDayOfYear()",
-        W: "String.leftPad(this.getWeekOfYear(), 2, '0')",
-        F: "Date.monthNames[this.getMonth()]",
-        m: "String.leftPad(this.getMonth() + 1, 2, '0')",
-        M: "Date.getShortMonthName(this.getMonth())", 
-        n: "(this.getMonth() + 1)",
-        t: "this.getDaysInMonth()",
-        L: "(this.isLeapYear() ? 1 : 0)",
-        o: "(this.getFullYear() + (this.getWeekOfYear() == 1 && this.getMonth() > 0 ? +1 : (this.getWeekOfYear() >= 52 && this.getMonth() < 11 ? -1 : 0)))",
-        Y: "this.getFullYear()",
-        y: "('' + this.getFullYear()).substring(2, 4)",
-        a: "(this.getHours() < 12 ? 'am' : 'pm')",
-        A: "(this.getHours() < 12 ? 'AM' : 'PM')",
-        g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
-        G: "this.getHours()",
-        h: "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
-        H: "String.leftPad(this.getHours(), 2, '0')",
-        i: "String.leftPad(this.getMinutes(), 2, '0')",
-        s: "String.leftPad(this.getSeconds(), 2, '0')",
-        u: "String.leftPad(this.getMilliseconds(), 3, '0')",
-        O: "this.getGMTOffset()",
-        P: "this.getGMTOffset(true)",
-        T: "this.getTimezone()",
-        Z: "(this.getTimezoneOffset() * -60)",
-
-        c: function() { 
-            for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
-                var e = c.charAt(i);
-                code.push(e == "T" ? "'T'" : Date.getFormatCode(e)); 
-            }
-            return code.join(" + ");
-        },
-        
-
-        U: "Math.round(this.getTime() / 1000)"
+    isTransnumeral: function(word) {
+        return Ext.Array.indexOf(this.uncountable, word) != -1;
     },
 
     
-    isValid : function(y, m, d, h, i, s, ms) {
-        
-        h = h || 0;
-        i = i || 0;
-        s = s || 0;
-        ms = ms || 0;
+    pluralize: function(word) {
+        if (this.isTransnumeral(word)) {
+            return word;
+        }
 
-        var dt = new Date(y, m - 1, d, h, i, s, ms);
+        var plurals = this.plurals,
+            length  = plurals.length,
+            tuple, regex, i;
 
-        return y == dt.getFullYear() &&
-            m == dt.getMonth() + 1 &&
-            d == dt.getDate() &&
-            h == dt.getHours() &&
-            i == dt.getMinutes() &&
-            s == dt.getSeconds() &&
-            ms == dt.getMilliseconds();
-    },
+        for (i = 0; i < length; i++) {
+            tuple = plurals[i];
+            regex = tuple[0];
 
-    
-    parseDate : function(input, format, strict) {
-        var p = Date.parseFunctions;
-        if (p[format] == null) {
-            Date.createParser(format);
+            if (regex == word || (regex.test && regex.test(word))) {
+                return word.replace(regex, tuple[1]);
+            }
         }
-        return p[format](input, Ext.isDefined(strict) ? strict : Date.useStrict);
+
+        return word;
     },
 
     
-    getFormatCode : function(character) {
-        var f = Date.formatCodes[character];
-
-        if (f) {
-          f = typeof f == 'function'? f() : f;
-          Date.formatCodes[character] = f; 
+    singularize: function(word) {
+        if (this.isTransnumeral(word)) {
+            return word;
         }
 
-        
-        return f || ("'" + String.escape(character) + "'");
-    },
+        var singulars = this.singulars,
+            length    = singulars.length,
+            tuple, regex, i;
 
-    
-    createFormat : function(format) {
-        var code = [],
-            special = false,
-            ch = '';
+        for (i = 0; i < length; i++) {
+            tuple = singulars[i];
+            regex = tuple[0];
 
-        for (var i = 0; i < format.length; ++i) {
-            ch = format.charAt(i);
-            if (!special && ch == "\\") {
-                special = true;
-            } else if (special) {
-                special = false;
-                code.push("'" + String.escape(ch) + "'");
-            } else {
-                code.push(Date.getFormatCode(ch))
+            if (regex == word || (regex.test && regex.test(word))) {
+                return word.replace(regex, tuple[1]);
             }
         }
-        Date.formatFunctions[format] = new Function("return " + code.join('+'));
+
+        return word;
     },
 
     
-    createParser : function() {
-        var code = [
-            "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
-                "def = Date.defaults,",
-                "results = String(input).match(Date.parseRegexes[{0}]);", 
-
-            "if(results){",
-                "{1}",
-
-                "if(u != null){", 
-                    "v = new Date(u * 1000);", 
-                "}else{",
-                    
-                    
-                    
-                    "dt = (new Date()).clearTime();",
-
-                    
-                    "y = Ext.num(y, Ext.num(def.y, dt.getFullYear()));",
-                    "m = Ext.num(m, Ext.num(def.m - 1, dt.getMonth()));",
-                    "d = Ext.num(d, Ext.num(def.d, dt.getDate()));",
-
-                    
-                    "h  = Ext.num(h, Ext.num(def.h, dt.getHours()));",
-                    "i  = Ext.num(i, Ext.num(def.i, dt.getMinutes()));",
-                    "s  = Ext.num(s, Ext.num(def.s, dt.getSeconds()));",
-                    "ms = Ext.num(ms, Ext.num(def.ms, dt.getMilliseconds()));",
-
-                    "if(z >= 0 && y >= 0){",
-                        
-                        
-
-                        
-                        "v = new Date(y, 0, 1, h, i, s, ms);",
-
-                        
-                        "v = !strict? v : (strict === true && (z <= 364 || (v.isLeapYear() && z <= 365))? v.add(Date.DAY, z) : null);",
-                    "}else if(strict === true && !Date.isValid(y, m + 1, d, h, i, s, ms)){", 
-                        "v = null;", 
-                    "}else{",
-                        
-                        "v = new Date(y, m, d, h, i, s, ms);",
-                    "}",
-                "}",
-            "}",
-
-            "if(v){",
-                
-                "if(zz != null){",
-                    
-                    "v = v.add(Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
-                "}else if(o){",
-                    
-                    "v = v.add(Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
-                "}",
-            "}",
-
-            "return v;"
-        ].join('\n');
-
-        return function(format) {
-            var regexNum = Date.parseRegexes.length,
-                currentGroup = 1,
-                calc = [],
-                regex = [],
-                special = false,
-                ch = "";
-
-            for (var i = 0; i < format.length; ++i) {
-                ch = format.charAt(i);
-                if (!special && ch == "\\") {
-                    special = true;
-                } else if (special) {
-                    special = false;
-                    regex.push(String.escape(ch));
-                } else {
-                    var obj = $f(ch, currentGroup);
-                    currentGroup += obj.g;
-                    regex.push(obj.s);
-                    if (obj.g && obj.c) {
-                        calc.push(obj.c);
-                    }
-                }
-            }
-
-            Date.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$");
-            Date.parseFunctions[format] = new Function("input", "strict", xf(code, regexNum, calc.join('')));
-        }
-    }(),
+    classify: function(word) {
+        return Ext.String.capitalize(this.singularize(word));
+    },
 
     
-    parseCodes : {
+    ordinalize: function(number) {
+        var parsed = parseInt(number, 10),
+            mod10  = parsed % 10,
+            mod100 = parsed % 100;
+
         
-        d: {
-            g:1,
-            c:"d = parseInt(results[{0}], 10);\n",
-            s:"(\\d{2})" 
-        },
-        j: {
-            g:1,
-            c:"d = parseInt(results[{0}], 10);\n",
-            s:"(\\d{1,2})" 
-        },
-        D: function() {
-            for (var a = [], i = 0; i < 7; a.push(Date.getShortDayName(i)), ++i); 
-            return {
-                g:0,
-                c:null,
-                s:"(?:" + a.join("|") +")"
-            }
-        },
-        l: function() {
-            return {
-                g:0,
-                c:null,
-                s:"(?:" + Date.dayNames.join("|") + ")"
-            }
-        },
-        N: {
-            g:0,
-            c:null,
-            s:"[1-7]" 
-        },
-        S: {
-            g:0,
-            c:null,
-            s:"(?:st|nd|rd|th)"
-        },
-        w: {
-            g:0,
-            c:null,
-            s:"[0-6]" 
-        },
-        z: {
-            g:1,
-            c:"z = parseInt(results[{0}], 10);\n",
-            s:"(\\d{1,3})" 
-        },
-        W: {
-            g:0,
-            c:null,
-            s:"(?:\\d{2})" 
-        },
-        F: function() {
-            return {
-                g:1,
-                c:"m = parseInt(Date.getMonthNumber(results[{0}]), 10);\n", 
-                s:"(" + Date.monthNames.join("|") + ")"
+        if (11 <= mod100 && mod100 <= 13) {
+            return number + "th";
+        } else {
+            switch(mod10) {
+                case 1 : return number + "st";
+                case 2 : return number + "nd";
+                case 3 : return number + "rd";
+                default: return number + "th";
             }
+        }
+    }
+}, function() {
+    
+    var irregulars = {
+            alumnus: 'alumni',
+            cactus : 'cacti',
+            focus  : 'foci',
+            nucleus: 'nuclei',
+            radius: 'radii',
+            stimulus: 'stimuli',
+            ellipsis: 'ellipses',
+            paralysis: 'paralyses',
+            oasis: 'oases',
+            appendix: 'appendices',
+            index: 'indexes',
+            beau: 'beaux',
+            bureau: 'bureaux',
+            tableau: 'tableaux',
+            woman: 'women',
+            child: 'children',
+            man: 'men',
+            corpus:    'corpora',
+            criterion: 'criteria',
+            curriculum:        'curricula',
+            genus: 'genera',
+            memorandum:        'memoranda',
+            phenomenon:        'phenomena',
+            foot: 'feet',
+            goose: 'geese',
+            tooth: 'teeth',
+            antenna: 'antennae',
+            formula: 'formulae',
+            nebula: 'nebulae',
+            vertebra: 'vertebrae',
+            vita: 'vitae'
         },
-        M: function() {
-            for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); 
-            return Ext.applyIf({
-                s:"(" + a.join("|") + ")"
-            }, $f("F"));
-        },
-        m: {
-            g:1,
-            c:"m = parseInt(results[{0}], 10) - 1;\n",
-            s:"(\\d{2})" 
-        },
-        n: {
-            g:1,
-            c:"m = parseInt(results[{0}], 10) - 1;\n",
-            s:"(\\d{1,2})" 
-        },
-        t: {
-            g:0,
-            c:null,
-            s:"(?:\\d{2})" 
-        },
-        L: {
-            g:0,
-            c:null,
-            s:"(?:1|0)"
-        },
-        o: function() {
-            return $f("Y");
-        },
-        Y: {
-            g:1,
-            c:"y = parseInt(results[{0}], 10);\n",
-            s:"(\\d{4})" 
-        },
-        y: {
-            g:1,
-            c:"var ty = parseInt(results[{0}], 10);\n"
-                + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
-            s:"(\\d{1,2})"
-        },
-        a: {
-            g:1,
-            c:"if (results[{0}] == 'am') {\n"
-                + "if (!h || h == 12) { h = 0; }\n"
-                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
-            s:"(am|pm)"
-        },
-        A: {
-            g:1,
-            c:"if (results[{0}] == 'AM') {\n"
-                + "if (!h || h == 12) { h = 0; }\n"
-                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
-            s:"(AM|PM)"
-        },
-        g: function() {
-            return $f("G");
-        },
-        G: {
-            g:1,
-            c:"h = parseInt(results[{0}], 10);\n",
-            s:"(\\d{1,2})" 
-        },
-        h: function() {
-            return $f("H");
-        },
-        H: {
-            g:1,
-            c:"h = parseInt(results[{0}], 10);\n",
-            s:"(\\d{2})" 
-        },
-        i: {
-            g:1,
-            c:"i = parseInt(results[{0}], 10);\n",
-            s:"(\\d{2})" 
-        },
-        s: {
-            g:1,
-            c:"s = parseInt(results[{0}], 10);\n",
-            s:"(\\d{2})" 
-        },
-        u: {
-            g:1,
-            c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
-            s:"(\\d+)" 
-        },
-        O: {
-            g:1,
-            c:[
-                "o = results[{0}];",
-                "var sn = o.substring(0,1),", 
-                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
-                    "mn = o.substring(3,5) % 60;", 
-                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
-            ].join("\n"),
-            s: "([+\-]\\d{4})" 
-        },
-        P: {
-            g:1,
-            c:[
-                "o = results[{0}];",
-                "var sn = o.substring(0,1),", 
-                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
-                    "mn = o.substring(4,6) % 60;", 
-                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + String.leftPad(hr, 2, '0') + String.leftPad(mn, 2, '0')) : null;\n" 
-            ].join("\n"),
-            s: "([+\-]\\d{2}:\\d{2})" 
-        },
-        T: {
-            g:0,
-            c:null,
-            s:"[A-Z]{1,4}" 
-        },
-        Z: {
-            g:1,
-            c:"zz = results[{0}] * 1;\n" 
-                  + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
-            s:"([+\-]?\\d{1,5})" 
-        },
-        c: function() {
-            var calc = [],
-                arr = [
-                    $f("Y", 1), 
-                    $f("m", 2), 
-                    $f("d", 3), 
-                    $f("h", 4), 
-                    $f("i", 5), 
-                    $f("s", 6), 
-                    {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
-                    {c:[ 
-                        "if(results[8]) {", 
-                            "if(results[8] == 'Z'){",
-                                "zz = 0;", 
-                            "}else if (results[8].indexOf(':') > -1){",
-                                $f("P", 8).c, 
-                            "}else{",
-                                $f("O", 8).c, 
-                            "}",
-                        "}"
-                    ].join('\n')}
-                ];
-
-            for (var i = 0, l = arr.length; i < l; ++i) {
-                calc.push(arr[i].c);
-            }
+        singular;
 
-            return {
-                g:1,
-                c:calc.join(""),
-                s:[
-                    arr[0].s, 
-                    "(?:", "-", arr[1].s, 
-                        "(?:", "-", arr[2].s, 
-                            "(?:",
-                                "(?:T| )?", 
-                                arr[3].s, ":", arr[4].s,  
-                                "(?::", arr[5].s, ")?", 
-                                "(?:(?:\\.|,)(\\d+))?", 
-                                "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
-                            ")?",
-                        ")?",
-                    ")?"
-                ].join("")
-            }
-        },
-        U: {
-            g:1,
-            c:"u = parseInt(results[{0}], 10);\n",
-            s:"(-?\\d+)" 
-        }
+    for (singular in irregulars) {
+        this.plural(singular, irregulars[singular]);
+        this.singular(irregulars[singular], singular);
     }
 });
 
-}());
+Ext.define('Ext.data.HasManyAssociation', {
+    extend: 'Ext.data.Association',
+    requires: ['Ext.util.Inflector'],
+
+    alias: 'association.hasmany',
 
-Ext.apply(Date.prototype, {
     
-    dateFormat : function(format) {
-        if (Date.formatFunctions[format] == null) {
-            Date.createFormat(format);
-        }
-        return Date.formatFunctions[format].call(this);
-    },
-
     
-    getTimezone : function() {
-        
-        
-        
-        
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    constructor: function(config) {
+        var me = this,
+            ownerProto,
+            name;
+            
+        me.callParent(arguments);
         
+        me.name = me.name || Ext.util.Inflector.pluralize(me.associatedName.toLowerCase());
         
+        ownerProto = me.ownerModel.prototype;
+        name = me.name;
         
+        Ext.applyIf(me, {
+            storeName : name + "Store",
+            foreignKey: me.ownerName.toLowerCase() + "_id"
+        });
         
+        ownerProto[name] = me.createStore();
+    },
+    
+    
+    createStore: function() {
+        var that            = this,
+            associatedModel = that.associatedModel,
+            storeName       = that.storeName,
+            foreignKey      = that.foreignKey,
+            primaryKey      = that.primaryKey,
+            filterProperty  = that.filterProperty,
+            autoLoad        = that.autoLoad,
+            storeConfig     = that.storeConfig || {};
         
+        return function() {
+            var me = this,
+                config, filter,
+                modelDefaults = {};
+                
+            if (me[storeName] === undefined) {
+                if (filterProperty) {
+                    filter = {
+                        property  : filterProperty,
+                        value     : me.get(filterProperty),
+                        exactMatch: true
+                    };
+                } else {
+                    filter = {
+                        property  : foreignKey,
+                        value     : me.get(primaryKey),
+                        exactMatch: true
+                    };
+                }
+                
+                modelDefaults[foreignKey] = me.get(primaryKey);
+                
+                config = Ext.apply({}, storeConfig, {
+                    model        : associatedModel,
+                    filters      : [filter],
+                    remoteFilter : false,
+                    modelDefaults: modelDefaults
+                });
+                
+                me[storeName] = Ext.create('Ext.data.Store', config);
+                if (autoLoad) {
+                    me[storeName].load();
+                }
+            }
+            
+            return me[storeName];
+        };
+    },
+    
+    
+    read: function(record, reader, associationData){
+        var store = record[this.name](),
+            inverse;
+    
+        store.add(reader.read(associationData).records);
+    
         
         
+        inverse = this.associatedModel.prototype.associations.findBy(function(assoc){
+            return assoc.type === 'belongsTo' && assoc.associatedName === record.$className;
+        });
+    
         
-        return this.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
-    },
+        if (inverse) {
+            store.data.each(function(associatedRecord){
+                associatedRecord[inverse.instanceName] = record;
+            });
+        }
+    }
+});
+
+Ext.define('Ext.data.JsonP', {
 
     
-    getGMTOffset : function(colon) {
-        return (this.getTimezoneOffset() > 0 ? "-" : "+")
-            + String.leftPad(Math.floor(Math.abs(this.getTimezoneOffset()) / 60), 2, "0")
-            + (colon ? ":" : "")
-            + String.leftPad(Math.abs(this.getTimezoneOffset() % 60), 2, "0");
+
+    singleton: true,
+
+    statics: {
+        requestCount: 0,
+        requests: {}
     },
 
     
-    getDayOfYear: function() {
-        var num = 0,
-            d = this.clone(),
-            m = this.getMonth(),
-            i;
 
-        for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
-            num += d.getDaysInMonth();
-        }
-        return num + this.getDate() - 1;
-    },
+    
+    timeout: 30000,
 
     
-    getWeekOfYear : function() {
-        
-        var ms1d = 864e5, 
-            ms7d = 7 * ms1d; 
+    disableCaching: true,
 
-        return function() { 
-            var DC3 = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate() + 3) / ms1d, 
-                AWN = Math.floor(DC3 / 7), 
-                Wyr = new Date(AWN * ms7d).getUTCFullYear();
+    
+    disableCachingParam: '_dc',
 
-            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
+    
+    callbackKey: 'callback',
+
+    
+    request: function(options){
+        options = Ext.apply({}, options);
+
+
+        var me = this,
+            disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching,
+            cacheParam = options.disableCachingParam || me.disableCachingParam,
+            id = ++me.statics().requestCount,
+            callbackName = options.callbackName || 'callback' + id,
+            callbackKey = options.callbackKey || me.callbackKey,
+            timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout,
+            params = Ext.apply({}, options.params),
+            url = options.url,
+            name = Ext.isSandboxed ? Ext.getUniqueGlobalNamespace() : 'Ext',
+            request,
+            script;
+
+        params[callbackKey] = name + '.data.JsonP.' + callbackName;
+        if (disableCaching) {
+            params[cacheParam] = new Date().getTime();
+        }
+
+        script = me.createScript(url, params);
+
+        me.statics().requests[id] = request = {
+            url: url,
+            params: params,
+            script: script,
+            id: id,
+            scope: options.scope,
+            success: options.success,
+            failure: options.failure,
+            callback: options.callback,
+            callbackName: callbackName
+        };
+
+        if (timeout > 0) {
+            request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
         }
-    }(),
+
+        me.setupErrorHandling(request);
+        me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
+        Ext.getHead().appendChild(script);
+        return request;
+    },
 
     
-    isLeapYear : function() {
-        var year = this.getFullYear();
-        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
+    abort: function(request){
+        var requests = this.statics().requests,
+            key;
+
+        if (request) {
+            if (!request.id) {
+                request = requests[request];
+            }
+            this.abort(request);
+        } else {
+            for (key in requests) {
+                if (requests.hasOwnProperty(key)) {
+                    this.abort(requests[key]);
+                }
+            }
+        }
     },
 
     
-    getFirstDayOfMonth : function() {
-        var day = (this.getDay() - (this.getDate() - 1)) % 7;
-        return (day < 0) ? (day + 7) : day;
+    setupErrorHandling: function(request){
+        request.script.onerror = Ext.bind(this.handleError, this, [request]);
     },
 
     
-    getLastDayOfMonth : function() {
-        return this.getLastDateOfMonth().getDay();
+    handleAbort: function(request){
+        request.errorType = 'abort';
+        this.handleResponse(null, request);
     },
 
+    
+    handleError: function(request){
+        request.errorType = 'error';
+        this.handleResponse(null, request);
+    },
 
     
-    getFirstDateOfMonth : function() {
-        return new Date(this.getFullYear(), this.getMonth(), 1);
+    cleanupErrorHandling: function(request){
+        request.script.onerror = null;
     },
 
     
-    getLastDateOfMonth : function() {
-        return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
+    handleTimeout: function(request){
+        request.errorType = 'timeout';
+        this.handleResponse(null, request);
     },
 
     
-    getDaysInMonth: function() {
-        var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+    handleResponse: function(result, request){
 
-        return function() { 
-            var m = this.getMonth();
+        var success = true;
 
-            return m == 1 && this.isLeapYear() ? 29 : daysInMonth[m];
+        if (request.timeout) {
+            clearTimeout(request.timeout);
         }
-    }(),
+        delete this[request.callbackName];
+        delete this.statics()[request.id];
+        this.cleanupErrorHandling(request);
+        Ext.fly(request.script).remove();
 
-    
-    getSuffix : function() {
-        switch (this.getDate()) {
-            case 1:
-            case 21:
-            case 31:
-                return "st";
-            case 2:
-            case 22:
-                return "nd";
-            case 3:
-            case 23:
-                return "rd";
-            default:
-                return "th";
+        if (request.errorType) {
+            success = false;
+            Ext.callback(request.failure, request.scope, [request.errorType]);
+        } else {
+            Ext.callback(request.success, request.scope, [result]);
         }
+        Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
     },
 
     
-    clone : function() {
-        return new Date(this.getTime());
-    },
+    createScript: function(url, params) {
+        var script = document.createElement('script');
+        script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
+        script.setAttribute("async", true);
+        script.setAttribute("type", "text/javascript");
+        return script;
+    }
+});
 
-    
-    isDST : function() {
-        
-        
-        return new Date(this.getFullYear(), 0, 1).getTimezoneOffset() != this.getTimezoneOffset();
-    },
+
+Ext.define('Ext.data.JsonPStore', {
+    extend: 'Ext.data.Store',
+    alias : 'store.jsonp',
 
     
-    clearTime : function(clone) {
-        if (clone) {
-            return this.clone().clearTime();
-        }
+    constructor: function(config) {
+        this.callParent(Ext.apply(config, {
+            reader: Ext.create('Ext.data.reader.Json', config),
+            proxy : Ext.create('Ext.data.proxy.JsonP', config)
+        }));
+    }
+});
 
-        
-        var d = this.getDate();
 
-        
-        this.setHours(0);
-        this.setMinutes(0);
-        this.setSeconds(0);
-        this.setMilliseconds(0);
+Ext.define('Ext.data.NodeInterface', {
+    requires: ['Ext.data.Field'],
 
-        if (this.getDate() != d) { 
-            
-            
+    
 
-            
-            for (var hr = 1, c = this.add(Date.HOUR, hr); c.getDate() != d; hr++, c = this.add(Date.HOUR, hr));
+    
 
-            this.setDate(d);
-            this.setHours(c.getHours());
-        }
+    
 
-        return this;
-    },
+    
 
     
-    add : function(interval, value) {
-        var d = this.clone();
-        if (!interval || value === 0) return d;
 
-        switch(interval.toLowerCase()) {
-            case Date.MILLI:
-                d.setMilliseconds(this.getMilliseconds() + value);
-                break;
-            case Date.SECOND:
-                d.setSeconds(this.getSeconds() + value);
-                break;
-            case Date.MINUTE:
-                d.setMinutes(this.getMinutes() + value);
-                break;
-            case Date.HOUR:
-                d.setHours(this.getHours() + value);
-                break;
-            case Date.DAY:
-                d.setDate(this.getDate() + value);
-                break;
-            case Date.MONTH:
-                var day = this.getDate();
-                if (day > 28) {
-                    day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
-                }
-                d.setDate(day);
-                d.setMonth(this.getMonth() + value);
-                break;
-            case Date.YEAR:
-                d.setFullYear(this.getFullYear() + value);
-                break;
-        }
-        return d;
-    },
+    
 
     
-    between : function(start, end) {
-        var t = this.getTime();
-        return start.getTime() <= t && t <= end.getTime();
-    }
-});
 
+    
 
+    
 
-Date.prototype.format = Date.prototype.dateFormat;
+    
 
+    
 
+    
 
-if (Ext.isSafari && (navigator.userAgent.match(/WebKit\/(\d+)/)[1] || NaN) < 420) {
-    Ext.apply(Date.prototype, {
-        _xMonth : Date.prototype.setMonth,
-        _xDate  : Date.prototype.setDate,
+    
 
-        
-        
-        setMonth : function(num) {
-            if (num <= -1) {
-                var n = Math.ceil(-num),
-                    back_year = Math.ceil(n / 12),
-                    month = (n % 12) ? 12 - n % 12 : 0;
+    
 
-                this.setFullYear(this.getFullYear() - back_year);
+    
 
-                return this._xMonth(month);
-            } else {
-                return this._xMonth(num);
-            }
-        },
+    
 
-        
-        
-        
-        setDate : function(d) {
-            
-            
-            return this.setTime(this.getTime() - (this.getDate() - d) * 864e5);
-        }
-    });
-}
+    
 
+    
 
+    
 
+    
 
+    
 
-Ext.util.MixedCollection = function(allowFunctions, keyFn){
-    this.items = [];
-    this.map = {};
-    this.keys = [];
-    this.length = 0;
-    this.addEvents(
-        
-        'clear',
-        
-        'add',
-        
-        'replace',
-        
-        'remove',
-        'sort'
-    );
-    this.allowFunctions = allowFunctions === true;
-    if(keyFn){
-        this.getKey = keyFn;
-    }
-    Ext.util.MixedCollection.superclass.constructor.call(this);
-};
+    
+
+    
 
-Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {
 
     
-    allowFunctions : false,
 
     
-    add : function(key, o){
-        if(arguments.length == 1){
-            o = arguments[0];
-            key = this.getKey(o);
-        }
-        if(typeof key != 'undefined' && key !== null){
-            var old = this.map[key];
-            if(typeof old != 'undefined'){
-                return this.replace(key, o);
-            }
-            this.map[key] = o;
-        }
-        this.length++;
-        this.items.push(o);
-        this.keys.push(key);
-        this.fireEvent('add', this.length-1, o, key);
-        return o;
-    },
 
     
-    getKey : function(o){
-         return o.id;
-    },
 
     
-    replace : function(key, o){
-        if(arguments.length == 1){
-            o = arguments[0];
-            key = this.getKey(o);
-        }
-        var old = this.map[key];
-        if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){
-             return this.add(key, o);
-        }
-        var index = this.indexOfKey(key);
-        this.items[index] = o;
-        this.map[key] = o;
-        this.fireEvent('replace', key, old, o);
-        return o;
-    },
 
     
-    addAll : function(objs){
-        if(arguments.length > 1 || Ext.isArray(objs)){
-            var args = arguments.length > 1 ? arguments : objs;
-            for(var i = 0, len = args.length; i < len; i++){
-                this.add(args[i]);
-            }
-        }else{
-            for(var key in objs){
-                if(this.allowFunctions || typeof objs[key] != 'function'){
-                    this.add(key, objs[key]);
+
+    
+
+    statics: {
+        
+        decorate: function(record) {
+            if (!record.isNode) {
+                
+                
+                var mgr = Ext.ModelManager,
+                    modelName = record.modelName,
+                    modelClass = mgr.getModel(modelName),
+                    idName = modelClass.prototype.idProperty,
+                    newFields = [],
+                    i, newField, len;
+
+                
+                modelClass.override(this.getPrototypeBody());
+                newFields = this.applyFields(modelClass, [
+                    {name: idName,       type: 'string',  defaultValue: null},
+                    {name: 'parentId',   type: 'string',  defaultValue: null},
+                    {name: 'index',      type: 'int',     defaultValue: null},
+                    {name: 'depth',      type: 'int',     defaultValue: 0},
+                    {name: 'expanded',   type: 'bool',    defaultValue: false, persist: false},
+                    {name: 'expandable', type: 'bool',    defaultValue: true, persist: false},
+                    {name: 'checked',    type: 'auto',    defaultValue: null},
+                    {name: 'leaf',       type: 'bool',    defaultValue: false, persist: false},
+                    {name: 'cls',        type: 'string',  defaultValue: null, persist: false},
+                    {name: 'iconCls',    type: 'string',  defaultValue: null, persist: false},
+                    {name: 'icon',       type: 'string',  defaultValue: null, persist: false},
+                    {name: 'root',       type: 'boolean', defaultValue: false, persist: false},
+                    {name: 'isLast',     type: 'boolean', defaultValue: false, persist: false},
+                    {name: 'isFirst',    type: 'boolean', defaultValue: false, persist: false},
+                    {name: 'allowDrop',  type: 'boolean', defaultValue: true, persist: false},
+                    {name: 'allowDrag',  type: 'boolean', defaultValue: true, persist: false},
+                    {name: 'loaded',     type: 'boolean', defaultValue: false, persist: false},
+                    {name: 'loading',    type: 'boolean', defaultValue: false, persist: false},
+                    {name: 'href',       type: 'string',  defaultValue: null, persist: false},
+                    {name: 'hrefTarget', type: 'string',  defaultValue: null, persist: false},
+                    {name: 'qtip',       type: 'string',  defaultValue: null, persist: false},
+                    {name: 'qtitle',     type: 'string',  defaultValue: null, persist: false}
+                ]);
+
+                len = newFields.length;
+                
+                for (i = 0; i < len; ++i) {
+                    newField = newFields[i];
+                    if (record.get(newField.name) === undefined) {
+                        record.data[newField.name] = newField.defaultValue;
+                    }
                 }
             }
-        }
-    },
 
-    
-    each : function(fn, scope){
-        var items = [].concat(this.items); 
-        for(var i = 0, len = items.length; i < len; i++){
-            if(fn.call(scope || items[i], items[i], i, len) === false){
-                break;
+            Ext.applyIf(record, {
+                firstChild: null,
+                lastChild: null,
+                parentNode: null,
+                previousSibling: null,
+                nextSibling: null,
+                childNodes: []
+            });
+            
+            record.commit(true);
+
+            record.enableBubble([
+                
+                "append",
+
+                
+                "remove",
+
+                
+                "move",
+
+                
+                "insert",
+
+                
+                "beforeappend",
+
+                
+                "beforeremove",
+
+                
+                "beforemove",
+
+                 
+                "beforeinsert",
+
+                
+                "expand",
+
+                
+                "collapse",
+
+                
+                "beforeexpand",
+
+                
+                "beforecollapse",
+
+                
+                "sort"
+            ]);
+
+            return record;
+        },
+
+        applyFields: function(modelClass, addFields) {
+            var modelPrototype = modelClass.prototype,
+                fields = modelPrototype.fields,
+                keys = fields.keys,
+                ln = addFields.length,
+                addField, i, name,
+                newFields = [];
+
+            for (i = 0; i < ln; i++) {
+                addField = addFields[i];
+                if (!Ext.Array.contains(keys, addField.name)) {
+                    addField = Ext.create('data.field', addField);
+
+                    newFields.push(addField);
+                    fields.add(addField);
+                }
             }
-        }
-    },
 
-    
-    eachKey : function(fn, scope){
-        for(var i = 0, len = this.keys.length; i < len; i++){
-            fn.call(scope || window, this.keys[i], this.items[i], i, len);
-        }
-    },
+            return newFields;
+        },
+
+        getPrototypeBody: function() {
+            return {
+                isNode: true,
+
+                
+                createNode: function(node) {
+                    if (Ext.isObject(node) && !node.isModel) {
+                        node = Ext.ModelManager.create(node, this.modelName);
+                    }
+                    
+                    return Ext.data.NodeInterface.decorate(node);
+                },
+
+                
+                isLeaf : function() {
+                    return this.get('leaf') === true;
+                },
+
+                
+                setFirstChild : function(node) {
+                    this.firstChild = node;
+                },
+
+                
+                setLastChild : function(node) {
+                    this.lastChild = node;
+                },
+
+                
+                updateInfo: function(silent) {
+                    var me = this,
+                        isRoot = me.isRoot(),
+                        parentNode = me.parentNode,
+                        isFirst = (!parentNode ? true : parentNode.firstChild == me),
+                        isLast = (!parentNode ? true : parentNode.lastChild == me),
+                        depth = 0,
+                        parent = me,
+                        children = me.childNodes,
+                        len = children.length,
+                        i = 0;
+
+                    while (parent.parentNode) {
+                        ++depth;
+                        parent = parent.parentNode;
+                    }
+
+                    me.beginEdit();
+                    me.set({
+                        isFirst: isFirst,
+                        isLast: isLast,
+                        depth: depth,
+                        index: parentNode ? parentNode.indexOf(me) : 0,
+                        parentId: parentNode ? parentNode.getId() : null
+                    });
+                    me.endEdit(silent);
+                    if (silent) {
+                        me.commit();
+                    }
+
+                    for (i = 0; i < len; i++) {
+                        children[i].updateInfo(silent);
+                    }
+                },
+
+                
+                isLast : function() {
+                   return this.get('isLast');
+                },
+
+                
+                isFirst : function() {
+                   return this.get('isFirst');
+                },
+
+                
+                hasChildNodes : function() {
+                    return !this.isLeaf() && this.childNodes.length > 0;
+                },
+
+                
+                isExpandable : function() {
+                    var me = this;
+
+                    if (me.get('expandable')) {
+                        return !(me.isLeaf() || (me.isLoaded() && !me.hasChildNodes()));
+                    }
+                    return false;
+                },
+
+                
+                appendChild : function(node, suppressEvents, suppressNodeUpdate) {
+                    var me = this,
+                        i, ln,
+                        index,
+                        oldParent,
+                        ps;
+
+                    
+                    if (Ext.isArray(node)) {
+                        for (i = 0, ln = node.length; i < ln; i++) {
+                            me.appendChild(node[i]);
+                        }
+                    } else {
+                        
+                        node = me.createNode(node);
+
+                        if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
+                            return false;
+                        }
+
+                        index = me.childNodes.length;
+                        oldParent = node.parentNode;
+
+                        
+                        if (oldParent) {
+                            if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
+                                return false;
+                            }
+                            oldParent.removeChild(node, null, false, true);
+                        }
+
+                        index = me.childNodes.length;
+                        if (index === 0) {
+                            me.setFirstChild(node);
+                        }
+
+                        me.childNodes.push(node);
+                        node.parentNode = me;
+                        node.nextSibling = null;
+
+                        me.setLastChild(node);
+
+                        ps = me.childNodes[index - 1];
+                        if (ps) {
+                            node.previousSibling = ps;
+                            ps.nextSibling = node;
+                            ps.updateInfo(suppressNodeUpdate);
+                        } else {
+                            node.previousSibling = null;
+                        }
+
+                        node.updateInfo(suppressNodeUpdate);
+
+                        
+                        if (!me.isLoaded()) {
+                            me.set('loaded', true);
+                        }
+                        
+                        else if (me.childNodes.length === 1) {
+                            me.set('loaded', me.isLoaded());
+                        }
+
+                        if (suppressEvents !== true) {
+                            me.fireEvent("append", me, node, index);
+
+                            if (oldParent) {
+                                node.fireEvent("move", node, oldParent, me, index);
+                            }
+                        }
+
+                        return node;
+                    }
+                },
+
+                
+                getBubbleTarget: function() {
+                    return this.parentNode;
+                },
+
+                
+                removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
+                    var me = this,
+                        index = me.indexOf(node);
+
+                    if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
+                        return false;
+                    }
+
+                    
+                    Ext.Array.erase(me.childNodes, index, 1);
+
+                    
+                    if (me.firstChild == node) {
+                        me.setFirstChild(node.nextSibling);
+                    }
+                    if (me.lastChild == node) {
+                        me.setLastChild(node.previousSibling);
+                    }
+
+                    
+                    if (node.previousSibling) {
+                        node.previousSibling.nextSibling = node.nextSibling;
+                        node.previousSibling.updateInfo(suppressNodeUpdate);
+                    }
+                    if (node.nextSibling) {
+                        node.nextSibling.previousSibling = node.previousSibling;
+                        node.nextSibling.updateInfo(suppressNodeUpdate);
+                    }
+
+                    if (suppressEvents !== true) {
+                        me.fireEvent("remove", me, node);
+                    }
+
+
+                    
+                    if (!me.childNodes.length) {
+                        me.set('loaded', me.isLoaded());
+                    }
+
+                    if (destroy) {
+                        node.destroy(true);
+                    } else {
+                        node.clear();
+                    }
+
+                    return node;
+                },
+
+                
+                copy: function(newId, deep) {
+                    var me = this,
+                        result = me.callOverridden(arguments),
+                        len = me.childNodes ? me.childNodes.length : 0,
+                        i;
+
+                    
+                    if (deep) {
+                        for (i = 0; i < len; i++) {
+                            result.appendChild(me.childNodes[i].copy(true));
+                        }
+                    }
+                    return result;
+                },
+
+                
+                clear : function(destroy) {
+                    var me = this;
+
+                    
+                    me.parentNode = me.previousSibling = me.nextSibling = null;
+                    if (destroy) {
+                        me.firstChild = me.lastChild = null;
+                    }
+                },
+
+                
+                destroy : function(silent) {
+                    
+                    var me = this,
+                        options = me.destroyOptions;
+
+                    if (silent === true) {
+                        me.clear(true);
+                        Ext.each(me.childNodes, function(n) {
+                            n.destroy(true);
+                        });
+                        me.childNodes = null;
+                        delete me.destroyOptions;
+                        me.callOverridden([options]);
+                    } else {
+                        me.destroyOptions = silent;
+                        
+                        me.remove(true);
+                    }
+                },
+
+                
+                insertBefore : function(node, refNode, suppressEvents) {
+                    var me = this,
+                        index     = me.indexOf(refNode),
+                        oldParent = node.parentNode,
+                        refIndex  = index,
+                        ps;
+
+                    if (!refNode) { 
+                        return me.appendChild(node);
+                    }
+
+                    
+                    if (node == refNode) {
+                        return false;
+                    }
+
+                    
+                    node = me.createNode(node);
+
+                    if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
+                        return false;
+                    }
+
+                    
+                    if (oldParent == me && me.indexOf(node) < index) {
+                        refIndex--;
+                    }
+
+                    
+                    if (oldParent) {
+                        if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false) {
+                            return false;
+                        }
+                        oldParent.removeChild(node);
+                    }
+
+                    if (refIndex === 0) {
+                        me.setFirstChild(node);
+                    }
+
+                    Ext.Array.splice(me.childNodes, refIndex, 0, node);
+                    node.parentNode = me;
+
+                    node.nextSibling = refNode;
+                    refNode.previousSibling = node;
+
+                    ps = me.childNodes[refIndex - 1];
+                    if (ps) {
+                        node.previousSibling = ps;
+                        ps.nextSibling = node;
+                        ps.updateInfo();
+                    } else {
+                        node.previousSibling = null;
+                    }
+
+                    node.updateInfo();
+
+                    if (!me.isLoaded()) {
+                        me.set('loaded', true);
+                    }
+                    
+                    else if (me.childNodes.length === 1) {
+                        me.set('loaded', me.isLoaded());
+                    }
+
+                    if (suppressEvents !== true) {
+                        me.fireEvent("insert", me, node, refNode);
+
+                        if (oldParent) {
+                            node.fireEvent("move", node, oldParent, me, refIndex, refNode);
+                        }
+                    }
+
+                    return node;
+                },
+
+                
+                insertChild: function(index, node) {
+                    var sibling = this.childNodes[index];
+                    if (sibling) {
+                        return this.insertBefore(node, sibling);
+                    }
+                    else {
+                        return this.appendChild(node);
+                    }
+                },
+
+                
+                remove : function(destroy, suppressEvents) {
+                    var parentNode = this.parentNode;
+
+                    if (parentNode) {
+                        parentNode.removeChild(this, destroy, suppressEvents, true);
+                    }
+                    return this;
+                },
+
+                
+                removeAll : function(destroy, suppressEvents) {
+                    var cn = this.childNodes,
+                        n;
+
+                    while ((n = cn[0])) {
+                        this.removeChild(n, destroy, suppressEvents);
+                    }
+                    return this;
+                },
+
+                
+                getChildAt : function(index) {
+                    return this.childNodes[index];
+                },
+
+                
+                replaceChild : function(newChild, oldChild, suppressEvents) {
+                    var s = oldChild ? oldChild.nextSibling : null;
+
+                    this.removeChild(oldChild, suppressEvents);
+                    this.insertBefore(newChild, s, suppressEvents);
+                    return oldChild;
+                },
+
+                
+                indexOf : function(child) {
+                    return Ext.Array.indexOf(this.childNodes, child);
+                },
+
+                
+                getPath: function(field, separator) {
+                    field = field || this.idProperty;
+                    separator = separator || '/';
+
+                    var path = [this.get(field)],
+                        parent = this.parentNode;
+
+                    while (parent) {
+                        path.unshift(parent.get(field));
+                        parent = parent.parentNode;
+                    }
+                    return separator + path.join(separator);
+                },
+
+                
+                getDepth : function() {
+                    return this.get('depth');
+                },
+
+                
+                bubble : function(fn, scope, args) {
+                    var p = this;
+                    while (p) {
+                        if (fn.apply(scope || p, args || [p]) === false) {
+                            break;
+                        }
+                        p = p.parentNode;
+                    }
+                },
+
+                cascade: function() {
+                    if (Ext.isDefined(Ext.global.console)) {
+                        Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.');
+                    }
+                    return this.cascadeBy.apply(this, arguments);
+                },
+
+                
+                cascadeBy : function(fn, scope, args) {
+                    if (fn.apply(scope || this, args || [this]) !== false) {
+                        var childNodes = this.childNodes,
+                            length     = childNodes.length,
+                            i;
+
+                        for (i = 0; i < length; i++) {
+                            childNodes[i].cascadeBy(fn, scope, args);
+                        }
+                    }
+                },
+
+                
+                eachChild : function(fn, scope, args) {
+                    var childNodes = this.childNodes,
+                        length     = childNodes.length,
+                        i;
+
+                    for (i = 0; i < length; i++) {
+                        if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
+                            break;
+                        }
+                    }
+                },
+
+                
+                findChild : function(attribute, value, deep) {
+                    return this.findChildBy(function() {
+                        return this.get(attribute) == value;
+                    }, null, deep);
+                },
+
+                
+                findChildBy : function(fn, scope, deep) {
+                    var cs = this.childNodes,
+                        len = cs.length,
+                        i = 0, n, res;
+
+                    for (; i < len; i++) {
+                        n = cs[i];
+                        if (fn.call(scope || n, n) === true) {
+                            return n;
+                        }
+                        else if (deep) {
+                            res = n.findChildBy(fn, scope, deep);
+                            if (res !== null) {
+                                return res;
+                            }
+                        }
+                    }
+
+                    return null;
+                },
+
+                
+                contains : function(node) {
+                    return node.isAncestor(this);
+                },
+
+                
+                isAncestor : function(node) {
+                    var p = this.parentNode;
+                    while (p) {
+                        if (p == node) {
+                            return true;
+                        }
+                        p = p.parentNode;
+                    }
+                    return false;
+                },
+
+                
+                sort : function(sortFn, recursive, suppressEvent) {
+                    var cs  = this.childNodes,
+                        ln = cs.length,
+                        i, n;
+
+                    if (ln > 0) {
+                        Ext.Array.sort(cs, sortFn);
+                        for (i = 0; i < ln; i++) {
+                            n = cs[i];
+                            n.previousSibling = cs[i-1];
+                            n.nextSibling = cs[i+1];
+
+                            if (i === 0) {
+                                this.setFirstChild(n);
+                                n.updateInfo();
+                            }
+                            if (i == ln - 1) {
+                                this.setLastChild(n);
+                                n.updateInfo();
+                            }
+                            if (recursive && !n.isLeaf()) {
+                                n.sort(sortFn, true, true);
+                            }
+                        }
+
+                        if (suppressEvent !== true) {
+                            this.fireEvent('sort', this, cs);
+                        }
+                    }
+                },
+
+                
+                isExpanded: function() {
+                    return this.get('expanded');
+                },
+
+                
+                isLoaded: function() {
+                    return this.get('loaded');
+                },
+
+                
+                isLoading: function() {
+                    return this.get('loading');
+                },
+
+                
+                isRoot: function() {
+                    return !this.parentNode;
+                },
 
-    
-    find : function(fn, scope){
-        for(var i = 0, len = this.items.length; i < len; i++){
-            if(fn.call(scope || window, this.items[i], this.keys[i])){
-                return this.items[i];
-            }
-        }
-        return null;
-    },
+                
+                isVisible: function() {
+                    var parent = this.parentNode;
+                    while (parent) {
+                        if (!parent.isExpanded()) {
+                            return false;
+                        }
+                        parent = parent.parentNode;
+                    }
+                    return true;
+                },
 
-    
-    insert : function(index, key, o){
-        if(arguments.length == 2){
-            o = arguments[1];
-            key = this.getKey(o);
-        }
-        if(this.containsKey(key)){
-            this.suspendEvents();
-            this.removeKey(key);
-            this.resumeEvents();
-        }
-        if(index >= this.length){
-            return this.add(key, o);
-        }
-        this.length++;
-        this.items.splice(index, 0, o);
-        if(typeof key != 'undefined' && key !== null){
-            this.map[key] = o;
-        }
-        this.keys.splice(index, 0, key);
-        this.fireEvent('add', index, o, key);
-        return o;
-    },
+                
+                expand: function(recursive, callback, scope) {
+                    var me = this;
 
-    
-    remove : function(o){
-        return this.removeAt(this.indexOf(o));
-    },
+                    
+                    
 
-    
-    removeAt : function(index){
-        if(index < this.length && index >= 0){
-            this.length--;
-            var o = this.items[index];
-            this.items.splice(index, 1);
-            var key = this.keys[index];
-            if(typeof key != 'undefined'){
-                delete this.map[key];
-            }
-            this.keys.splice(index, 1);
-            this.fireEvent('remove', o, key);
-            return o;
-        }
-        return false;
-    },
+                    
+                    if (!me.isLeaf()) {
+                        
+                        if (me.isLoading()) {
+                            me.on('expand', function(){
+                                me.expand(recursive, callback, scope);
+                            }, me, {single: true});
+                        } else {
+                            
+                            if (!me.isExpanded()) {
+                                
+                                
+                                
+                                
+                                me.fireEvent('beforeexpand', me, function(){
+                                    me.set('expanded', true);
+                                    me.fireEvent('expand', me, me.childNodes, false);
 
-    
-    removeKey : function(key){
-        return this.removeAt(this.indexOfKey(key));
-    },
+                                    
+                                    if (recursive) {
+                                        me.expandChildren(true, callback, scope);
+                                    } else {
+                                        Ext.callback(callback, scope || me, [me.childNodes]);
+                                    }
+                                }, me);
+                            } else if (recursive) {
+                                
+                                me.expandChildren(true, callback, scope);
+                            } else {
+                                Ext.callback(callback, scope || me, [me.childNodes]);
+                            }
+                        }
+                    } else {
+                        
+                        Ext.callback(callback, scope || me); 
+                    }
+                },
 
-    
-    getCount : function(){
-        return this.length;
-    },
+                
+                expandChildren: function(recursive, callback, scope) {
+                    var me = this,
+                        i = 0,
+                        nodes = me.childNodes,
+                        ln = nodes.length,
+                        node,
+                        expanding = 0;
+
+                    for (; i < ln; ++i) {
+                        node = nodes[i];
+                        if (!node.isLeaf() && !node.isExpanded()) {
+                            expanding++;
+                            nodes[i].expand(recursive, function () {
+                                expanding--;
+                                if (callback && !expanding) {
+                                    Ext.callback(callback, scope || me, [me.childNodes]);
+                                }
+                            });
+                        }
+                    }
 
-    
-    indexOf : function(o){
-        return this.items.indexOf(o);
-    },
+                    if (!expanding && callback) {
+                        Ext.callback(callback, scope || me, [me.childNodes]);                    }
+                },
 
-    
-    indexOfKey : function(key){
-        return this.keys.indexOf(key);
-    },
+                
+                collapse: function(recursive, callback, scope) {
+                    var me = this;
 
-    
-    item : function(key){
-        var mk = this.map[key],
-            item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;
-        return typeof item != 'function' || this.allowFunctions ? item : null; 
-    },
+                    
+                    if (!me.isLeaf()) {
+                        
+                        if (!me.collapsing && me.isExpanded()) {
+                            me.fireEvent('beforecollapse', me, function() {
+                                me.set('expanded', false);
+                                me.fireEvent('collapse', me, me.childNodes, false);
 
-    
-    itemAt : function(index){
-        return this.items[index];
-    },
+                                
+                                if (recursive) {
+                                    me.collapseChildren(true, callback, scope);
+                                }
+                                else {
+                                    Ext.callback(callback, scope || me, [me.childNodes]);
+                                }
+                            }, me);
+                        }
+                        
+                        else if (recursive) {
+                            me.collapseChildren(true, callback, scope);
+                        }
+                    }
+                    
+                    else {
+                        Ext.callback(callback, scope || me, [me.childNodes]);
+                    }
+                },
 
-    
-    key : function(key){
-        return this.map[key];
-    },
+                
+                collapseChildren: function(recursive, callback, scope) {
+                    var me = this,
+                        i = 0,
+                        nodes = me.childNodes,
+                        ln = nodes.length,
+                        node,
+                        collapsing = 0;
+
+                    for (; i < ln; ++i) {
+                        node = nodes[i];
+                        if (!node.isLeaf() && node.isExpanded()) {
+                            collapsing++;
+                            nodes[i].collapse(recursive, function () {
+                                collapsing--;
+                                if (callback && !collapsing) {
+                                    Ext.callback(callback, scope || me, [me.childNodes]);
+                                }
+                            });
+                        }
+                    }
 
-    
-    contains : function(o){
-        return this.indexOf(o) != -1;
-    },
+                    if (!collapsing && callback) {
+                        Ext.callback(callback, scope || me, [me.childNodes]);
+                    }
+                }
+            };
+        }
+    }
+});
 
+Ext.define('Ext.data.NodeStore', {
+    extend: 'Ext.data.Store',
+    alias: 'store.node',
+    requires: ['Ext.data.NodeInterface'],
     
-    containsKey : function(key){
-        return typeof this.map[key] != 'undefined';
-    },
-
     
-    clear : function(){
-        this.length = 0;
-        this.items = [];
-        this.keys = [];
-        this.map = {};
-        this.fireEvent('clear');
-    },
-
+    node: null,
     
-    first : function(){
-        return this.items[0];
-    },
-
     
-    last : function(){
-        return this.items[this.length-1];
-    },
-
+    recursive: false,
     
-    _sort : function(property, dir, fn){
-        var i, len,
-            dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
-
+        
+    rootVisible: false,
+    
+    constructor: function(config) {
+        var me = this,
+            node;
             
-            c     = [],
-            keys  = this.keys,
-            items = this.items;
-
+        config = config || {};
+        Ext.apply(me, config);
         
-        fn = fn || function(a, b) {
-            return a - b;
-        };
 
+        config.proxy = {type: 'proxy'};
+        me.callParent([config]);
+
+        me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
         
-        for(i = 0, len = items.length; i < len; i++){
-            c[c.length] = {
-                key  : keys[i],
-                value: items[i],
-                index: i
-            };
+        node = me.node;
+        if (node) {
+            me.node = null;
+            me.setNode(node);
         }
-
+    },
+    
+    setNode: function(node) {
+        var me = this;
         
-        c.sort(function(a, b){
-            var v = fn(a[property], b[property]) * dsc;
-            if(v === 0){
-                v = (a.index < b.index ? -1 : 1);
+        if (me.node && me.node != node) {
+            
+            me.mun(me.node, {
+                expand: me.onNodeExpand,
+                collapse: me.onNodeCollapse,
+                append: me.onNodeAppend,
+                insert: me.onNodeInsert,
+                remove: me.onNodeRemove,
+                sort: me.onNodeSort,
+                scope: me
+            });
+            me.node = null;
+        }
+        
+        if (node) {
+            Ext.data.NodeInterface.decorate(node);
+            me.removeAll();
+            if (me.rootVisible) {
+                me.add(node);
+            }
+            me.mon(node, {
+                expand: me.onNodeExpand,
+                collapse: me.onNodeCollapse,
+                append: me.onNodeAppend,
+                insert: me.onNodeInsert,
+                remove: me.onNodeRemove,
+                sort: me.onNodeSort,
+                scope: me
+            });
+            me.node = node;
+            if (node.isExpanded() && node.isLoaded()) {
+                me.onNodeExpand(node, node.childNodes, true);
             }
-            return v;
-        });
-
-        
-        for(i = 0, len = c.length; i < len; i++){
-            items[i] = c[i].value;
-            keys[i]  = c[i].key;
         }
-
-        this.fireEvent('sort', this);
     },
-
     
-    sort : function(dir, fn){
-        this._sort('value', dir, fn);
+    onNodeSort: function(node, childNodes) {
+        var me = this;
+        
+        if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) {
+            me.onNodeCollapse(node, childNodes, true);
+            me.onNodeExpand(node, childNodes, true);
+        }
     },
-
     
-    reorder: function(mapping) {
-        this.suspendEvents();
-
-        var items = this.items,
-            index = 0,
-            length = items.length,
-            order = [],
-            remaining = [],
-            oldIndex;
-
+    onNodeExpand: function(parent, records, suppressEvent) {
+        var me = this,
+            insertIndex = me.indexOf(parent) + 1,
+            ln = records ? records.length : 0,
+            i, record;
+            
+        if (!me.recursive && parent !== me.node) {
+            return;
+        }
         
-        for (oldIndex in mapping) {
-            order[mapping[oldIndex]] = items[oldIndex];
+        if (!me.isVisible(parent)) {
+            return;
         }
 
-        for (index = 0; index < length; index++) {
-            if (mapping[index] == undefined) {
-                remaining.push(items[index]);
-            }
+        if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
+            return;
         }
-
-        for (index = 0; index < length; index++) {
-            if (order[index] == undefined) {
-                order[index] = remaining.shift();
+        
+        if (ln) {
+            me.insert(insertIndex, records);
+            for (i = 0; i < ln; i++) {
+                record = records[i];
+                if (record.isExpanded()) {
+                    if (record.isLoaded()) {
+                        
+                        me.onNodeExpand(record, record.childNodes, true);
+                    }
+                    else {
+                        record.set('expanded', false);
+                        record.expand();
+                    }
+                }
             }
         }
 
-        this.clear();
-        this.addAll(order);
-
-        this.resumeEvents();
-        this.fireEvent('sort', this);
-    },
-
-    
-    keySort : function(dir, fn){
-        this._sort('key', dir, fn || function(a, b){
-            var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
-            return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
-        });
+        if (!suppressEvent) {
+            me.fireEvent('expand', parent, records);
+        }
     },
 
-    
-    getRange : function(start, end){
-        var items = this.items;
-        if(items.length < 1){
-            return [];
+    onNodeCollapse: function(parent, records, suppressEvent) {
+        var me = this,
+            ln = records.length,
+            collapseIndex = me.indexOf(parent) + 1,
+            i, record;
+            
+        if (!me.recursive && parent !== me.node) {
+            return;
         }
-        start = start || 0;
-        end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);
-        var i, r = [];
-        if(start <= end){
-            for(i = start; i <= end; i++) {
-                r[r.length] = items[i];
-            }
-        }else{
-            for(i = start; i >= end; i--) {
-                r[r.length] = items[i];
-            }
+        
+        if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
+            return;
         }
-        return r;
-    },
 
-    
-    filter : function(property, value, anyMatch, caseSensitive){
-        if(Ext.isEmpty(value, false)){
-            return this.clone();
+        for (i = 0; i < ln; i++) {
+            record = records[i];
+            me.remove(record);
+            if (record.isExpanded()) {
+                me.onNodeCollapse(record, record.childNodes, true);
+            }
+        }
+        
+        if (!suppressEvent) {
+            me.fireEvent('collapse', parent, records, collapseIndex);
         }
-        value = this.createValueMatcher(value, anyMatch, caseSensitive);
-        return this.filterBy(function(o){
-            return o && value.test(o[property]);
-        });
     },
+    
+    onNodeAppend: function(parent, node, index) {
+        var me = this,
+            refNode, sibling;
 
+        if (me.isVisible(node)) {
+            if (index === 0) {
+                refNode = parent;
+            } else {
+                sibling = node.previousSibling;
+                while (sibling.isExpanded() && sibling.lastChild) {
+                    sibling = sibling.lastChild;
+                }
+                refNode = sibling;
+            }
+            me.insert(me.indexOf(refNode) + 1, node);
+            if (!node.isLeaf() && node.isExpanded()) {
+                if (node.isLoaded()) {
+                    
+                    me.onNodeExpand(node, node.childNodes, true);
+                }
+                else {
+                    node.set('expanded', false);
+                    node.expand();
+                }
+            }
+        } 
+    },
     
-    filterBy : function(fn, scope){
-        var r = new Ext.util.MixedCollection();
-        r.getKey = this.getKey;
-        var k = this.keys, it = this.items;
-        for(var i = 0, len = it.length; i < len; i++){
-            if(fn.call(scope||this, it[i], k[i])){
-                r.add(k[i], it[i]);
+    onNodeInsert: function(parent, node, refNode) {
+        var me = this,
+            index = this.indexOf(refNode);
+            
+        if (index != -1 && me.isVisible(node)) {
+            me.insert(index, node);
+            if (!node.isLeaf() && node.isExpanded()) {
+                if (node.isLoaded()) {
+                    
+                    me.onNodeExpand(node, node.childNodes, true);
+                }
+                else {
+                    node.set('expanded', false);
+                    node.expand();
+                }
             }
         }
-        return r;
     },
-
     
-    findIndex : function(property, value, start, anyMatch, caseSensitive){
-        if(Ext.isEmpty(value, false)){
-            return -1;
+    onNodeRemove: function(parent, node, index) {
+        var me = this;
+        if (me.indexOf(node) != -1) {
+            if (!node.isLeaf() && node.isExpanded()) {
+                me.onNodeCollapse(node, node.childNodes, true);
+            }            
+            me.remove(node);
         }
-        value = this.createValueMatcher(value, anyMatch, caseSensitive);
-        return this.findIndexBy(function(o){
-            return o && value.test(o[property]);
-        }, null, start);
     },
-
     
-    findIndexBy : function(fn, scope, start){
-        var k = this.keys, it = this.items;
-        for(var i = (start||0), len = it.length; i < len; i++){
-            if(fn.call(scope||this, it[i], k[i])){
-                return i;
+    isVisible: function(node) {
+        var parent = node.parentNode;
+        while (parent) {
+            if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
+                return true;
             }
+            
+            if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
+                return false;
+            }
+            
+            parent = parent.parentNode;
         }
-        return -1;
-    },
+        return true;
+    }
+});
 
+Ext.define('Ext.data.Request', {
     
-    createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
-        if (!value.exec) { 
-            var er = Ext.escapeRe;
-            value = String(value);
-
-            if (anyMatch === true) {
-                value = er(value);
-            } else {
-                value = '^' + er(value);
-                if (exactMatch === true) {
-                    value += '$';
-                }
-            }
-            value = new RegExp(value, caseSensitive ? '' : 'i');
-         }
-         return value;
-    },
+    action: undefined,
+    
+    
+    params: undefined,
+    
+    
+    method: 'GET',
+    
+    
+    url: undefined,
 
     
-    clone : function(){
-        var r = new Ext.util.MixedCollection();
-        var k = this.keys, it = this.items;
-        for(var i = 0, len = it.length; i < len; i++){
-            r.add(k[i], it[i]);
-        }
-        r.getKey = this.getKey;
-        return r;
+    constructor: function(config) {
+        Ext.apply(this, config);
     }
 });
 
-Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;
+Ext.define('Ext.data.SequentialIdGenerator', {
+    extend: 'Ext.data.IdGenerator',
+    alias: 'idgen.sequential',
 
-Ext.util.JSON = new (function(){
-    var useHasOwn = !!{}.hasOwnProperty,
-        isNative = function() {
-            var useNative = null;
+    constructor: function() {
+        var me = this;
 
-            return function() {
-                if (useNative === null) {
-                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
-                }
-        
-                return useNative;
-            };
-        }(),
-        pad = function(n) {
-            return n < 10 ? "0" + n : n;
-        },
-        doDecode = function(json){
-            return eval("(" + json + ')');    
-        },
-        doEncode = function(o){
-            if(!Ext.isDefined(o) || o === null){
-                return "null";
-            }else if(Ext.isArray(o)){
-                return encodeArray(o);
-            }else if(Ext.isDate(o)){
-                return Ext.util.JSON.encodeDate(o);
-            }else if(Ext.isString(o)){
-                return encodeString(o);
-            }else if(typeof o == "number"){
-                
-                return isFinite(o) ? String(o) : "null";
-            }else if(Ext.isBoolean(o)){
-                return String(o);
-            }else {
-                var a = ["{"], b, i, v;
-                for (i in o) {
-                    
-                    if(!o.getElementsByTagName){
-                        if(!useHasOwn || o.hasOwnProperty(i)) {
-                            v = o[i];
-                            switch (typeof v) {
-                            case "undefined":
-                            case "function":
-                            case "unknown":
-                                break;
-                            default:
-                                if(b){
-                                    a.push(',');
-                                }
-                                a.push(doEncode(i), ":",
-                                        v === null ? "null" : doEncode(v));
-                                b = true;
-                            }
-                        }
-                    }
-                }
-                a.push("}");
-                return a.join("");
-            }    
-        },
-        m = {
-            "\b": '\\b',
-            "\t": '\\t',
-            "\n": '\\n',
-            "\f": '\\f',
-            "\r": '\\r',
-            '"' : '\\"',
-            "\\": '\\\\'
-        },
-        encodeString = function(s){
-            if (/["\\\x00-\x1f]/.test(s)) {
-                return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
-                    var c = m[b];
-                    if(c){
-                        return c;
-                    }
-                    c = b.charCodeAt();
-                    return "\\u00" +
-                        Math.floor(c / 16).toString(16) +
-                        (c % 16).toString(16);
-                }) + '"';
-            }
-            return '"' + s + '"';
-        },
-        encodeArray = function(o){
-            var a = ["["], b, i, l = o.length, v;
-                for (i = 0; i < l; i += 1) {
-                    v = o[i];
-                    switch (typeof v) {
-                        case "undefined":
-                        case "function":
-                        case "unknown":
-                            break;
-                        default:
-                            if (b) {
-                                a.push(',');
-                            }
-                            a.push(v === null ? "null" : Ext.util.JSON.encode(v));
-                            b = true;
-                    }
-                }
-                a.push("]");
-                return a.join("");
-        };
+        me.callParent(arguments);
 
-    
-    this.encodeDate = function(o){
-        return '"' + o.getFullYear() + "-" +
-                pad(o.getMonth() + 1) + "-" +
-                pad(o.getDate()) + "T" +
-                pad(o.getHours()) + ":" +
-                pad(o.getMinutes()) + ":" +
-                pad(o.getSeconds()) + '"';
-    };
+        me.parts = [ me.prefix, ''];
+    },
 
     
-    this.encode = function() {
-        var ec;
-        return function(o) {
-            if (!ec) {
-                
-                ec = isNative() ? JSON.stringify : doEncode;
-            }
-            return ec(o);
-        };
-    }();
+    prefix: '',
 
+    
+    seed: 1,
 
     
-    this.decode = function() {
-        var dc;
-        return function(json) {
-            if (!dc) {
-                
-                dc = isNative() ? JSON.parse : doDecode;
-            }
-            return dc(json);
-        };
-    }();
+    generate: function () {
+        var me = this,
+            parts = me.parts;
 
-})();
+        parts[1] = me.seed++;
+        return parts.join('');
+    }
+});
 
-Ext.encode = Ext.util.JSON.encode;
 
-Ext.decode = Ext.util.JSON.decode;
+Ext.define('Ext.data.Tree', {
+    alias: 'data.tree',
 
-Ext.util.Format = function(){
-    var trimRe = /^\s+|\s+$/g,
-        stripTagsRE = /<\/?[^>]+>/gi,
-        stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
-        nl2brRe = /\r?\n/g;
+    mixins: {
+        observable: "Ext.util.Observable"
+    },
 
-    return {
-        
-        ellipsis : function(value, len, word){
-            if(value && value.length > len){
-                if(word){
-                    var vs = value.substr(0, len - 2),
-                        index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
-                    if(index == -1 || index < (len - 15)){
-                        return value.substr(0, len - 3) + "...";
-                    }else{
-                        return vs.substr(0, index) + "...";
-                    }
-                } else{
-                    return value.substr(0, len - 3) + "...";
-                }
-            }
-            return value;
-        },
+    
+    root: null,
 
-        
-        undef : function(value){
-            return value !== undefined ? value : "";
-        },
+    
+    constructor: function(root) {
+        var me = this;
 
         
-        defaultValue : function(value, defaultValue){
-            return value !== undefined && value !== '' ? value : defaultValue;
-        },
 
-        
-        htmlEncode : function(value){
-            return !value ? value : String(value).replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
-        },
+        me.mixins.observable.constructor.call(me);
 
-        
-        htmlDecode : function(value){
-            return !value ? value : String(value).replace(/&gt;/g, ">").replace(/&lt;/g, "<").replace(/&quot;/g, '"').replace(/&amp;/g, "&");
-        },
+        if (root) {
+            me.setRootNode(root);
+        }
+    },
 
-        
-        trim : function(value){
-            return String(value).replace(trimRe, "");
-        },
+    
+    getRootNode : function() {
+        return this.root;
+    },
 
-        
-        substr : function(value, start, length){
-            return String(value).substr(start, length);
-        },
+    
+    setRootNode : function(node) {
+        var me = this;
 
-        
-        lowercase : function(value){
-            return String(value).toLowerCase();
-        },
+        me.root = node;
+        Ext.data.NodeInterface.decorate(node);
 
-        
-        uppercase : function(value){
-            return String(value).toUpperCase();
-        },
+        if (me.fireEvent('beforeappend', null, node) !== false) {
+            node.set('root', true);
+            node.updateInfo();
 
-        
-        capitalize : function(value){
-            return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
-        },
+            me.relayEvents(node, [
+                
+                "append",
 
-        
-        call : function(value, fn){
-            if(arguments.length > 2){
-                var args = Array.prototype.slice.call(arguments, 2);
-                args.unshift(value);
-                return eval(fn).apply(window, args);
-            }else{
-                return eval(fn).call(window, value);
-            }
-        },
+                
+                "remove",
 
-        
-        usMoney : function(v){
-            v = (Math.round((v-0)*100))/100;
-            v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
-            v = String(v);
-            var ps = v.split('.'),
-                whole = ps[0],
-                sub = ps[1] ? '.'+ ps[1] : '.00',
-                r = /(\d+)(\d{3})/;
-            while (r.test(whole)) {
-                whole = whole.replace(r, '$1' + ',' + '$2');
-            }
-            v = whole + sub;
-            if(v.charAt(0) == '-'){
-                return '-$' + v.substr(1);
-            }
-            return "$" +  v;
-        },
+                
+                "move",
 
-        
-        date : function(v, format){
-            if(!v){
-                return "";
-            }
-            if(!Ext.isDate(v)){
-                v = new Date(Date.parse(v));
-            }
-            return v.dateFormat(format || "m/d/Y");
-        },
+                
+                "insert",
 
-        
-        dateRenderer : function(format){
-            return function(v){
-                return Ext.util.Format.date(v, format);
-            };
-        },
+                
+                "beforeappend",
 
-        
-        stripTags : function(v){
-            return !v ? v : String(v).replace(stripTagsRE, "");
-        },
+                
+                "beforeremove",
 
-        
-        stripScripts : function(v){
-            return !v ? v : String(v).replace(stripScriptsRe, "");
-        },
+                
+                "beforemove",
 
-        
-        fileSize : function(size){
-            if(size < 1024) {
-                return size + " bytes";
-            } else if(size < 1048576) {
-                return (Math.round(((size*10) / 1024))/10) + " KB";
-            } else {
-                return (Math.round(((size*10) / 1048576))/10) + " MB";
-            }
-        },
+                
+                "beforeinsert",
 
-        
-        math : function(){
-            var fns = {};
-            return function(v, a){
-                if(!fns[a]){
-                    fns[a] = new Function('v', 'return v ' + a + ';');
-                }
-                return fns[a](v);
-            }
-        }(),
+                 
+                 "expand",
 
-        
-        round : function(value, precision) {
-            var result = Number(value);
-            if (typeof precision == 'number') {
-                precision = Math.pow(10, precision);
-                result = Math.round(value * precision) / precision;
-            }
-            return result;
-        },
+                 
+                 "collapse",
 
-        
-        number: function(v, format) {
-            if(!format){
-                return v;
-            }
-            v = Ext.num(v, NaN);
-            if (isNaN(v)){
-                return '';
-            }
-            var comma = ',',
-                dec = '.',
-                i18n = false,
-                neg = v < 0;
+                 
+                 "beforeexpand",
 
-            v = Math.abs(v);
-            if(format.substr(format.length - 2) == '/i'){
-                format = format.substr(0, format.length - 2);
-                i18n = true;
-                comma = '.';
-                dec = ',';
-            }
+                 
+                 "beforecollapse" ,
 
-            var hasComma = format.indexOf(comma) != -1,
-                psplit = (i18n ? format.replace(/[^\d\,]/g, '') : format.replace(/[^\d\.]/g, '')).split(dec);
+                 
+                 "rootchange"
+            ]);
 
-            if(1 < psplit.length){
-                v = v.toFixed(psplit[1].length);
-            }else if(2 < psplit.length){
-                throw ('NumberFormatException: invalid format, formats should have no more than 1 period: ' + format);
-            }else{
-                v = v.toFixed(0);
-            }
+            node.on({
+                scope: me,
+                insert: me.onNodeInsert,
+                append: me.onNodeAppend,
+                remove: me.onNodeRemove
+            });
 
-            var fnum = v.toString();
+            me.nodeHash = {};
+            me.registerNode(node);
+            me.fireEvent('append', null, node);
+            me.fireEvent('rootchange', node);
+        }
 
-            psplit = fnum.split('.');
+        return node;
+    },
 
-            if (hasComma) {
-                var cnum = psplit[0], parr = [], j = cnum.length, m = Math.floor(j / 3), n = cnum.length % 3 || 3;
+    
+    flatten: function(){
+        var nodes = [],
+            hash = this.nodeHash,
+            key;
 
-                for (var i = 0; i < j; i += n) {
-                    if (i != 0) {
-                        n = 3;
-                    }
-                    parr[parr.length] = cnum.substr(i, n);
-                    m -= 1;
-                }
-                fnum = parr.join(comma);
-                if (psplit[1]) {
-                    fnum += dec + psplit[1];
-                }
-            } else {
-                if (psplit[1]) {
-                    fnum = psplit[0] + dec + psplit[1];
-                }
+        for (key in hash) {
+            if (hash.hasOwnProperty(key)) {
+                nodes.push(hash[key]);
             }
-
-            return (neg ? '-' : '') + format.replace(/[\d,?\.?]+/, fnum);
-        },
-
-        
-        numberRenderer : function(format){
-            return function(v){
-                return Ext.util.Format.number(v, format);
-            };
-        },
-
-        
-        plural : function(v, s, p){
-            return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
-        },
-
-        
-        nl2br : function(v){
-            return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
         }
-    }
-}();
+        return nodes;
+    },
 
-Ext.XTemplate = function(){
-    Ext.XTemplate.superclass.constructor.apply(this, arguments);
+    
+    onNodeInsert: function(parent, node) {
+        this.registerNode(node, true);
+    },
 
-    var me = this,
-        s = me.html,
-        re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
-        nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
-        ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
-        execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
-        m,
-        id = 0,
-        tpls = [],
-        VALUES = 'values',
-        PARENT = 'parent',
-        XINDEX = 'xindex',
-        XCOUNT = 'xcount',
-        RETURN = 'return ',
-        WITHVALUES = 'with(values){ ';
-
-    s = ['<tpl>', s, '</tpl>'].join('');
-
-    while((m = s.match(re))){
-        var m2 = m[0].match(nameRe),
-            m3 = m[0].match(ifRe),
-            m4 = m[0].match(execRe),
-            exp = null,
-            fn = null,
-            exec = null,
-            name = m2 && m2[1] ? m2[1] : '';
-
-       if (m3) {
-           exp = m3 && m3[1] ? m3[1] : null;
-           if(exp){
-               fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
-           }
-       }
-       if (m4) {
-           exp = m4 && m4[1] ? m4[1] : null;
-           if(exp){
-               exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
-           }
-       }
-       if(name){
-           switch(name){
-               case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
-               case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
-               default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
-           }
-       }
-       tpls.push({
-            id: id,
-            target: name,
-            exec: exec,
-            test: fn,
-            body: m[1]||''
-        });
-       s = s.replace(m[0], '{xtpl'+ id + '}');
-       ++id;
-    }
-    for(var i = tpls.length-1; i >= 0; --i){
-        me.compileTpl(tpls[i]);
-    }
-    me.master = tpls[tpls.length-1];
-    me.tpls = tpls;
-};
-Ext.extend(Ext.XTemplate, Ext.Template, {
     
-    re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
+    onNodeAppend: function(parent, node) {
+        this.registerNode(node, true);
+    },
+
+    
+    onNodeRemove: function(parent, node) {
+        this.unregisterNode(node, true);
+    },
+
     
-    codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
+    getNodeById : function(id) {
+        return this.nodeHash[id];
+    },
 
     
-    applySubTemplate : function(id, values, parent, xindex, xcount){
-        var me = this,
-            len,
-            t = me.tpls[id],
-            vs,
-            buf = [];
-        if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
-            (t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
-            return '';
+    registerNode : function(node, includeChildren) {
+        this.nodeHash[node.getId() || node.internalId] = node;
+        if (includeChildren === true) {
+            node.eachChild(function(child){
+                this.registerNode(child, true);
+            }, this);
         }
-        vs = t.target ? t.target.call(me, values, parent) : values;
-        len = vs.length;
-        parent = t.target ? values : parent;
-        if(t.target && Ext.isArray(vs)){
-            for(var i = 0, len = vs.length; i < len; i++){
-                buf[buf.length] = t.compiled.call(me, vs[i], parent, i+1, len);
-            }
-            return buf.join('');
+    },
+
+    
+    unregisterNode : function(node, includeChildren) {
+        delete this.nodeHash[node.getId() || node.internalId];
+        if (includeChildren === true) {
+            node.eachChild(function(child){
+                this.unregisterNode(child, true);
+            }, this);
         }
-        return t.compiled.call(me, vs, parent, xindex, xcount);
     },
 
     
-    compileTpl : function(tpl){
-        var fm = Ext.util.Format,
-            useF = this.disableFormats !== true,
-            sep = Ext.isGecko ? "+" : ",",
-            body;
+    sort: function(sorterFn, recursive) {
+        this.getRootNode().sort(sorterFn, recursive);
+    },
 
-        function fn(m, name, format, args, math){
-            if(name.substr(0, 4) == 'xtpl'){
-                return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
-            }
-            var v;
-            if(name === '.'){
-                v = 'values';
-            }else if(name === '#'){
-                v = 'xindex';
-            }else if(name.indexOf('.') != -1){
-                v = name;
-            }else{
-                v = "values['" + name + "']";
-            }
-            if(math){
-                v = '(' + v + math + ')';
-            }
-            if (format && useF) {
-                args = args ? ',' + args : "";
-                if(format.substr(0, 5) != "this."){
-                    format = "fm." + format + '(';
-                }else{
-                    format = 'this.call("'+ format.substr(5) + '", ';
-                    args = ", values";
-                }
-            } else {
-                args= ''; format = "("+v+" === undefined ? '' : ";
-            }
-            return "'"+ sep + format + v + args + ")"+sep+"'";
-        }
+     
+    filter: function(filters, recursive) {
+        this.getRootNode().filter(filters, recursive);
+    }
+});
 
-        function codeFn(m, code){
-            
-            return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
-        }
+Ext.define('Ext.data.TreeStore', {
+    extend: 'Ext.data.AbstractStore',
+    alias: 'store.tree',
+    requires: ['Ext.data.Tree', 'Ext.data.NodeInterface', 'Ext.data.NodeStore'],
 
-        
-        if(Ext.isGecko){
-            body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
-                   tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
-                    "';};";
-        }else{
-            body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
-            body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
-            body.push("'].join('');};");
-            body = body.join('');
-        }
-        eval(body);
-        return this;
-    },
+    
 
     
-    applyTemplate : function(values){
-        return this.master.compiled.call(this, values, {}, 1, 1);
-    },
+    clearOnLoad : true,
 
     
-    compile : function(){return this;}
+    nodeParam: 'node',
 
     
+    defaultRootId: 'root',
+
     
+    defaultRootProperty: 'children',
+
     
+    folderSort: false,
 
-});
+    constructor: function(config) {
+        var me = this,
+            root,
+            fields;
 
-Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
+        config = Ext.apply({}, config);
 
+        
+        fields = config.fields || me.fields;
+        if (!fields) {
+            config.fields = [{name: 'text', type: 'string'}];
+        }
 
-Ext.XTemplate.from = function(el){
-    el = Ext.getDom(el);
-    return new Ext.XTemplate(el.value || el.innerHTML);
-};
+        me.callParent([config]);
 
-Ext.util.CSS = function(){
-       var rules = null;
-       var doc = document;
+        
+        me.tree = Ext.create('Ext.data.Tree');
 
-    var camelRe = /(-[a-z])/gi;
-    var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
+        me.relayEvents(me.tree, [
+            
+            "append",
 
-   return {
-   
-   createStyleSheet : function(cssText, id){
-       var ss;
-       var head = doc.getElementsByTagName("head")[0];
-       var rules = doc.createElement("style");
-       rules.setAttribute("type", "text/css");
-       if(id){
-           rules.setAttribute("id", id);
-       }
-       if(Ext.isIE){
-           head.appendChild(rules);
-           ss = rules.styleSheet;
-           ss.cssText = cssText;
-       }else{
-           try{
-                rules.appendChild(doc.createTextNode(cssText));
-           }catch(e){
-               rules.cssText = cssText;
-           }
-           head.appendChild(rules);
-           ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
-       }
-       this.cacheStyleSheet(ss);
-       return ss;
-   },
+            
+            "remove",
 
-   
-   removeStyleSheet : function(id){
-       var existing = doc.getElementById(id);
-       if(existing){
-           existing.parentNode.removeChild(existing);
-       }
-   },
+            
+            "move",
 
-   
-   swapStyleSheet : function(id, url){
-       this.removeStyleSheet(id);
-       var ss = doc.createElement("link");
-       ss.setAttribute("rel", "stylesheet");
-       ss.setAttribute("type", "text/css");
-       ss.setAttribute("id", id);
-       ss.setAttribute("href", url);
-       doc.getElementsByTagName("head")[0].appendChild(ss);
-   },
-   
-   
-   refreshCache : function(){
-       return this.getRules(true);
-   },
+            
+            "insert",
 
-   
-   cacheStyleSheet : function(ss){
-       if(!rules){
-           rules = {};
-       }
-       try{
-           var ssRules = ss.cssRules || ss.rules;
-           for(var j = ssRules.length-1; j >= 0; --j){
-               rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];
-           }
-       }catch(e){}
-   },
-   
-   
-   getRules : function(refreshCache){
-               if(rules === null || refreshCache){
-                       rules = {};
-                       var ds = doc.styleSheets;
-                       for(var i =0, len = ds.length; i < len; i++){
-                           try{
-                       this.cacheStyleSheet(ds[i]);
-                   }catch(e){} 
-               }
-               }
-               return rules;
-       },
-       
-       
-   getRule : function(selector, refreshCache){
-               var rs = this.getRules(refreshCache);
-               if(!Ext.isArray(selector)){
-                   return rs[selector.toLowerCase()];
-               }
-               for(var i = 0; i < selector.length; i++){
-                       if(rs[selector[i]]){
-                               return rs[selector[i].toLowerCase()];
-                       }
-               }
-               return null;
-       },
-       
-       
-       
-   updateRule : function(selector, property, value){
-               if(!Ext.isArray(selector)){
-                       var rule = this.getRule(selector);
-                       if(rule){
-                               rule.style[property.replace(camelRe, camelFn)] = value;
-                               return true;
-                       }
-               }else{
-                       for(var i = 0; i < selector.length; i++){
-                               if(this.updateRule(selector[i], property, value)){
-                                       return true;
-                               }
-                       }
-               }
-               return false;
-       }
-   };  
-}();
-Ext.util.ClickRepeater = Ext.extend(Ext.util.Observable, {
-    
-    constructor : function(el, config){
-        this.el = Ext.get(el);
-        this.el.unselectable();
+            
+            "beforeappend",
 
-        Ext.apply(this, config);
+            
+            "beforeremove",
 
-        this.addEvents(
-        
-        "mousedown",
-        
-        "click",
-        
-        "mouseup"
-        );
+            
+            "beforemove",
 
-        if(!this.disabled){
-            this.disabled = true;
-            this.enable();
-        }
+            
+            "beforeinsert",
 
-        
-        if(this.handler){
-            this.on("click", this.handler,  this.scope || this);
+             
+             "expand",
+
+             
+             "collapse",
+
+             
+             "beforeexpand",
+
+             
+             "beforecollapse",
+
+             
+             "rootchange"
+        ]);
+
+        me.tree.on({
+            scope: me,
+            remove: me.onNodeRemove,
+            
+            
+            beforeexpand: me.onBeforeNodeExpand,
+            beforecollapse: me.onBeforeNodeCollapse,
+            append: me.onNodeAdded,
+            insert: me.onNodeAdded
+        });
+
+        me.onBeforeSort();
+
+        root = me.root;
+        if (root) {
+            delete me.root;
+            me.setRootNode(root);
         }
 
-        Ext.util.ClickRepeater.superclass.constructor.call(this);        
-    },
-    
-    interval : 20,
-    delay: 250,
-    preventDefault : true,
-    stopDefault : false,
-    timer : 0,
+        me.addEvents(
+            
+            'sort'
+        );
 
-    
-    enable: function(){
-        if(this.disabled){
-            this.el.on('mousedown', this.handleMouseDown, this);
-            if (Ext.isIE){
-                this.el.on('dblclick', this.handleDblClick, this);
-            }
-            if(this.preventDefault || this.stopDefault){
-                this.el.on('click', this.eventOptions, this);
+        if (Ext.isDefined(me.nodeParameter)) {
+            if (Ext.isDefined(Ext.global.console)) {
+                Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.');
             }
+            me.nodeParam = me.nodeParameter;
+            delete me.nodeParameter;
         }
-        this.disabled = false;
     },
 
     
-    disable: function( force){
-        if(force || !this.disabled){
-            clearTimeout(this.timer);
-            if(this.pressClass){
-                this.el.removeClass(this.pressClass);
-            }
-            Ext.getDoc().un('mouseup', this.handleMouseUp, this);
-            this.el.removeAllListeners();
+    setProxy: function(proxy) {
+        var reader,
+            needsRoot;
+
+        if (proxy instanceof Ext.data.proxy.Proxy) {
+            
+            needsRoot = Ext.isEmpty(proxy.getReader().root);
+        } else if (Ext.isString(proxy)) {
+            
+            needsRoot = true;
+        } else {
+            
+            reader = proxy.reader;
+            needsRoot = !(reader && !Ext.isEmpty(reader.root));
+        }
+        proxy = this.callParent(arguments);
+        if (needsRoot) {
+            reader = proxy.getReader();
+            reader.root = this.defaultRootProperty;
+            
+            reader.buildExtractors(true);
         }
-        this.disabled = true;
     },
 
     
-    setDisabled: function(disabled){
-        this[disabled ? 'disable' : 'enable']();
+    onBeforeSort: function() {
+        if (this.folderSort) {
+            this.sort({
+                property: 'leaf',
+                direction: 'ASC'
+            }, 'prepend', false);
+        }
     },
 
-    eventOptions: function(e){
-        if(this.preventDefault){
-            e.preventDefault();
+    
+    onBeforeNodeExpand: function(node, callback, scope) {
+        if (node.isLoaded()) {
+            Ext.callback(callback, scope || node, [node.childNodes]);
         }
-        if(this.stopDefault){
-            e.stopEvent();
+        else if (node.isLoading()) {
+            this.on('load', function() {
+                Ext.callback(callback, scope || node, [node.childNodes]);
+            }, this, {single: true});
+        }
+        else {
+            this.read({
+                node: node,
+                callback: function() {
+                    Ext.callback(callback, scope || node, [node.childNodes]);
+                }
+            });
         }
     },
 
     
-    destroy : function() {
-        this.disable(true);
-        Ext.destroy(this.el);
-        this.purgeListeners();
+    getNewRecords: function() {
+        return Ext.Array.filter(this.tree.flatten(), this.filterNew);
     },
 
-    handleDblClick : function(e){
-        clearTimeout(this.timer);
-        this.el.blur();
-
-        this.fireEvent("mousedown", this, e);
-        this.fireEvent("click", this, e);
+    
+    getUpdatedRecords: function() {
+        return Ext.Array.filter(this.tree.flatten(), this.filterUpdated);
     },
 
     
-    handleMouseDown : function(e){
-        clearTimeout(this.timer);
-        this.el.blur();
-        if(this.pressClass){
-            this.el.addClass(this.pressClass);
-        }
-        this.mousedownTime = new Date();
-
-        Ext.getDoc().on("mouseup", this.handleMouseUp, this);
-        this.el.on("mouseout", this.handleMouseOut, this);
+    onBeforeNodeCollapse: function(node, callback, scope) {
+        callback.call(scope || node, node.childNodes);
+    },
 
-        this.fireEvent("mousedown", this, e);
-        this.fireEvent("click", this, e);
+    onNodeRemove: function(parent, node) {
+        var removed = this.removed;
 
-        
-        if (this.accelerate) {
-            this.delay = 400;
+        if (!node.isReplace && Ext.Array.indexOf(removed, node) == -1) {
+            removed.push(node);
         }
-        this.timer = this.click.defer(this.delay || this.interval, this, [e]);
     },
 
-    
-    click : function(e){
-        this.fireEvent("click", this, e);
-        this.timer = this.click.defer(this.accelerate ?
-            this.easeOutExpo(this.mousedownTime.getElapsed(),
-                400,
-                -390,
-                12000) :
-            this.interval, this, [e]);
-    },
+    onNodeAdded: function(parent, node) {
+        var proxy = this.getProxy(),
+            reader = proxy.getReader(),
+            data = node.raw || node.data,
+            dataRoot, children;
 
-    easeOutExpo : function (t, b, c, d) {
-        return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
-    },
+        Ext.Array.remove(this.removed, node);
 
-    
-    handleMouseOut : function(){
-        clearTimeout(this.timer);
-        if(this.pressClass){
-            this.el.removeClass(this.pressClass);
+        if (!node.isLeaf() && !node.isLoaded()) {
+            dataRoot = reader.getRoot(data);
+            if (dataRoot) {
+                this.fillNode(node, reader.extractData(dataRoot));
+                delete data[reader.root];
+            }
         }
-        this.el.on("mouseover", this.handleMouseReturn, this);
     },
 
     
-    handleMouseReturn : function(){
-        this.el.un("mouseover", this.handleMouseReturn, this);
-        if(this.pressClass){
-            this.el.addClass(this.pressClass);
+    setRootNode: function(root) {
+        var me = this;
+
+        root = root || {};
+        if (!root.isNode) {
+            
+            Ext.applyIf(root, {
+                id: me.defaultRootId,
+                text: 'Root',
+                allowDrag: false
+            });
+            root = Ext.ModelManager.create(root, me.model);
         }
-        this.click();
-    },
+        Ext.data.NodeInterface.decorate(root);
 
-    
-    handleMouseUp : function(e){
-        clearTimeout(this.timer);
-        this.el.un("mouseover", this.handleMouseReturn, this);
-        this.el.un("mouseout", this.handleMouseOut, this);
-        Ext.getDoc().un("mouseup", this.handleMouseUp, this);
-        this.el.removeClass(this.pressClass);
-        this.fireEvent("mouseup", this, e);
-    }
-});
-Ext.KeyNav = function(el, config){
-    this.el = Ext.get(el);
-    Ext.apply(this, config);
-    if(!this.disabled){
-        this.disabled = true;
-        this.enable();
-    }
-};
+        
+        
+        me.getProxy().getReader().buildExtractors(true);
 
-Ext.KeyNav.prototype = {
-    
-    disabled : false,
-    
-    defaultEventAction: "stopEvent",
-    
-    forceKeyDown : false,
+        
+        me.tree.setRootNode(root);
 
-    
-    relay : function(e){
-        var k = e.getKey();
-        var h = this.keyToHandler[k];
-        if(h && this[h]){
-            if(this.doRelay(e, this[h], h) !== true){
-                e[this.defaultEventAction]();
-            }
+        
+        if (!root.isLoaded() && (me.autoLoad === true || root.isExpanded())) {
+            me.load({
+                node: root
+            });
         }
-    },
 
-    
-    doRelay : function(e, h, hname){
-        return h.call(this.scope || this, e);
+        return root;
     },
 
     
-    enter : false,
-    left : false,
-    right : false,
-    up : false,
-    down : false,
-    tab : false,
-    esc : false,
-    pageUp : false,
-    pageDown : false,
-    del : false,
-    home : false,
-    end : false,
+    getRootNode: function() {
+        return this.tree.getRootNode();
+    },
 
     
-    keyToHandler : {
-        37 : "left",
-        39 : "right",
-        38 : "up",
-        40 : "down",
-        33 : "pageUp",
-        34 : "pageDown",
-        46 : "del",
-        36 : "home",
-        35 : "end",
-        13 : "enter",
-        27 : "esc",
-        9  : "tab"
+    getNodeById: function(id) {
+        return this.tree.getNodeById(id);
     },
-    
-    stopKeyUp: function(e) {
-        var k = e.getKey();
 
-        if (k >= 37 && k <= 40) {
-            
-            
-            e.stopEvent();
-        }
-    },
     
-    
-    destroy: function(){
-        this.disable();    
-    },
+    load: function(options) {
+        options = options || {};
+        options.params = options.params || {};
 
-       
-       enable: function() {
-        if (this.disabled) {
-            if (Ext.isSafari2) {
-                
-                this.el.on('keyup', this.stopKeyUp, this);
-            }
+        var me = this,
+            node = options.node || me.tree.getRootNode(),
+            root;
 
-            this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
-            this.disabled = false;
+        
+        
+        if (!node) {
+            node = me.setRootNode({
+                expanded: true
+            });
         }
-    },
 
-       
-       disable: function() {
-        if (!this.disabled) {
-            if (Ext.isSafari2) {
-                
-                this.el.un('keyup', this.stopKeyUp, this);
-            }
+        if (me.clearOnLoad) {
+            node.removeAll(true);
+        }
 
-            this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
-            this.disabled = true;
+        Ext.applyIf(options, {
+            node: node
+        });
+        options.params[me.nodeParam] = node ? node.getId() : 'root';
+
+        if (node) {
+            node.set('loading', true);
         }
+
+        return me.callParent([options]);
     },
+
+
     
-    
-    setDisabled : function(disabled){
-        this[disabled ? "disable" : "enable"]();
+    fillNode: function(node, records) {
+        var me = this,
+            ln = records ? records.length : 0,
+            i = 0, sortCollection;
+
+        if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
+            sortCollection = Ext.create('Ext.util.MixedCollection');
+            sortCollection.addAll(records);
+            sortCollection.sort(me.sorters.items);
+            records = sortCollection.items;
+        }
+
+        node.set('loaded', true);
+        for (; i < ln; i++) {
+            node.appendChild(records[i], undefined, true);
+        }
+
+        return records;
     },
+
     
-    
-    isKeydown: function(){
-        return this.forceKeyDown || Ext.EventManager.useKeydown;
-    }
-};
+    onProxyLoad: function(operation) {
+        var me = this,
+            successful = operation.wasSuccessful(),
+            records = operation.getRecords(),
+            node = operation.node;
 
-Ext.KeyMap = function(el, config, eventName){
-    this.el  = Ext.get(el);
-    this.eventName = eventName || "keydown";
-    this.bindings = [];
-    if(config){
-        this.addBinding(config);
-    }
-    this.enable();
-};
+        me.loading = false;
+        node.set('loading', false);
+        if (successful) {
+            records = me.fillNode(node, records);
+        }
+        
+        
+        
+        
+        me.fireEvent('read', me, operation.node, records, successful);
+        me.fireEvent('load', me, operation.node, records, successful);
+        
+        Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
+    },
 
-Ext.KeyMap.prototype = {
     
-    stopEvent : false,
+    onCreateRecords: function(records, operation, success) {
+        if (success) {
+            var i = 0,
+                length = records.length,
+                originalRecords = operation.records,
+                parentNode,
+                record,
+                original,
+                index;
 
-    
-       addBinding : function(config){
-        if(Ext.isArray(config)){
-            Ext.each(config, function(c){
-                this.addBinding(c);
-            }, this);
-            return;
-        }
-        var keyCode = config.key,
-            fn = config.fn || config.handler,
-            scope = config.scope;
-
-       if (config.stopEvent) {
-           this.stopEvent = config.stopEvent;    
-       }       
-
-        if(typeof keyCode == "string"){
-            var ks = [];
-            var keyString = keyCode.toUpperCase();
-            for(var j = 0, len = keyString.length; j < len; j++){
-                ks.push(keyString.charCodeAt(j));
-            }
-            keyCode = ks;
-        }
-        var keyArray = Ext.isArray(keyCode);
-        
-        var handler = function(e){
-            if(this.checkModifiers(config, e)){
-                var k = e.getKey();
-                if(keyArray){
-                    for(var i = 0, len = keyCode.length; i < len; i++){
-                        if(keyCode[i] == k){
-                          if(this.stopEvent){
-                              e.stopEvent();
-                          }
-                          fn.call(scope || window, k, e);
-                          return;
-                        }
-                    }
-                }else{
-                    if(k == keyCode){
-                        if(this.stopEvent){
-                           e.stopEvent();
-                        }
-                        fn.call(scope || window, k, e);
+            
+            for (; i < length; ++i) {
+                record = records[i];
+                original = originalRecords[i];
+                if (original) {
+                    parentNode = original.parentNode;
+                    if (parentNode) {
+                        
+                        original.isReplace = true;
+                        parentNode.replaceChild(record, original);
+                        delete original.isReplace;
                     }
+                    record.phantom = false;
                 }
             }
-        };
-        this.bindings.push(handler);
-       },
-    
+        }
+    },
+
     
-    checkModifiers: function(config, e){
-        var val, key, keys = ['shift', 'ctrl', 'alt'];
-        for (var i = 0, len = keys.length; i < len; ++i){
-            key = keys[i];
-            val = config[key];
-            if(!(val === undefined || (val === e[key + 'Key']))){
-                return false;
+    onUpdateRecords: function(records, operation, success){
+        if (success) {
+            var me = this,
+                i = 0,
+                length = records.length,
+                data = me.data,
+                original,
+                parentNode,
+                record;
+
+            for (; i < length; ++i) {
+                record = records[i];
+                original = me.tree.getNodeById(record.getId());
+                parentNode = original.parentNode;
+                if (parentNode) {
+                    
+                    original.isReplace = true;
+                    parentNode.replaceChild(record, original);
+                    original.isReplace = false;
+                }
             }
         }
-        return true;
     },
 
     
-    on : function(key, fn, scope){
-        var keyCode, shift, ctrl, alt;
-        if(typeof key == "object" && !Ext.isArray(key)){
-            keyCode = key.key;
-            shift = key.shift;
-            ctrl = key.ctrl;
-            alt = key.alt;
-        }else{
-            keyCode = key;
+    onDestroyRecords: function(records, operation, success){
+        if (success) {
+            this.removed = [];
         }
-        this.addBinding({
-            key: keyCode,
-            shift: shift,
-            ctrl: ctrl,
-            alt: alt,
-            fn: fn,
-            scope: scope
-        });
     },
 
     
-    handleKeyDown : function(e){
-           if(this.enabled){ 
-           var b = this.bindings;
-           for(var i = 0, len = b.length; i < len; i++){
-               b[i].call(this, e);
-           }
-           }
-       },
+    removeAll: function() {
+        this.getRootNode().destroy(true);
+        this.fireEvent('clear', this);
+    },
+
+    
+    doSort: function(sorterFn) {
+        var me = this;
+        if (me.remoteSort) {
+            
+            me.load();
+        } else {
+            me.tree.sort(sorterFn, true);
+            me.fireEvent('datachanged', me);
+        }
+        me.fireEvent('sort', me);
+    }
+});
 
-       
-       isEnabled : function(){
-           return this.enabled;
-       },
 
-       
-       enable: function(){
-               if(!this.enabled){
-                   this.el.on(this.eventName, this.handleKeyDown, this);
-                   this.enabled = true;
-               }
-       },
+Ext.define('Ext.data.UuidGenerator', function () {
+    var twoPow14 = Math.pow(2, 14),
+        twoPow16 = Math.pow(2, 16),
+        twoPow28 = Math.pow(2, 28),
+        twoPow32 = Math.pow(2, 32);
 
-       
-       disable: function(){
-               if(this.enabled){
-                   this.el.removeListener(this.eventName, this.handleKeyDown, this);
-                   this.enabled = false;
-               }
-       },
-    
-    
-    setDisabled : function(disabled){
-        this[disabled ? "disable" : "enable"]();
+    function toHex (value, length) {
+        var ret = value.toString(16);
+        if (ret.length > length) {
+            ret = ret.substring(ret.length - length); 
+        } else if (ret.length < length) {
+            ret = Ext.String.leftPad(ret, length, '0');
+        }
+        return ret;
     }
-};
-Ext.util.TextMetrics = function(){
-    var shared;
+
+    function rand (lo, hi) {
+        var v = Math.random() * (hi - lo + 1);
+        return Math.floor(v) + lo;
+    }
+
+    function split (bignum) {
+        if (typeof(bignum) == 'number') {
+            var hi = Math.floor(bignum / twoPow32);
+            return {
+                lo: Math.floor(bignum - hi * twoPow32),
+                hi: hi
+            };
+        }
+        return bignum;
+    }
+
     return {
+        extend: 'Ext.data.IdGenerator',
+
+        alias: 'idgen.uuid',
+
+        id: 'uuid', 
+
         
-        measure : function(el, text, fixedWidth){
-            if(!shared){
-                shared = Ext.util.TextMetrics.Instance(el, fixedWidth);
-            }
-            shared.bind(el);
-            shared.setFixedWidth(fixedWidth || 'auto');
-            return shared.getSize(text);
-        },
 
         
-        createInstance : function(el, fixedWidth){
-            return Ext.util.TextMetrics.Instance(el, fixedWidth);
-        }
-    };
-}();
 
-Ext.util.TextMetrics.Instance = function(bindTo, fixedWidth){
-    var ml = new Ext.Element(document.createElement('div'));
-    document.body.appendChild(ml.dom);
-    ml.position('absolute');
-    ml.setLeftTop(-1000, -1000);
-    ml.hide();
+        
+        version: 4,
 
-    if(fixedWidth){
-        ml.setWidth(fixedWidth);
-    }
+        constructor: function() {
+            var me = this;
 
-    var instance = {
-        
-        getSize : function(text){
-            ml.update(text);
-            var s = ml.getSize();
-            ml.update('');
-            return s;
+            me.callParent(arguments);
+
+            me.parts = [];
+            me.init();
         },
 
-        
-        bind : function(el){
-            ml.setStyle(
-                Ext.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
-            );
+        generate: function () {
+            var me = this,
+                parts = me.parts,
+                ts = me.timestamp;
+
+            
+            parts[0] = toHex(ts.lo, 8);
+            parts[1] = toHex(ts.hi & 0xFFFF, 4);
+            parts[2] = toHex(((ts.hi >>> 16) & 0xFFF) | (me.version << 12), 4);
+            parts[3] = toHex(0x80 | ((me.clockSeq >>> 8) & 0x3F), 2) +
+                       toHex(me.clockSeq & 0xFF, 2);
+            parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8);
+
+            if (me.version == 4) {
+                me.init(); 
+            } else {
+                
+                ++ts.lo;
+                if (ts.lo >= twoPow32) { 
+                    ts.lo = 0;
+                    ++ts.hi;
+                }
+            }
+
+            return parts.join('-').toLowerCase();
         },
 
-        
-        setFixedWidth : function(width){
-            ml.setWidth(width);
+        getRecId: function (rec) {
+            return rec.getId();
         },
 
         
-        getWidth : function(text){
-            ml.dom.style.width = 'auto';
-            return this.getSize(text).width;
+        init: function () {
+            var me = this,
+                salt, time;
+
+            if (me.version == 4) {
+                
+                
+                
+                
+                me.clockSeq = rand(0, twoPow14-1);
+
+                
+                salt = me.salt || (me.salt = {});
+                time = me.timestamp || (me.timestamp = {});
+
+                
+                salt.lo = rand(0, twoPow32-1);
+                salt.hi = rand(0, twoPow16-1);
+                time.lo = rand(0, twoPow32-1);
+                time.hi = rand(0, twoPow28-1);
+            } else {
+                
+                me.salt = split(me.salt);
+                me.timestamp = split(me.timestamp);
+
+                
+                
+                me.salt.hi |= 0x100;
+            }
         },
 
         
-        getHeight : function(text){
-            return this.getSize(text).height;
+        reconfigure: function (config) {
+            Ext.apply(this, config);
+            this.init();
         }
     };
+}());
 
-    instance.bind(bindTo);
 
-    return instance;
-};
+Ext.define('Ext.data.XmlStore', {
+    extend: 'Ext.data.Store',
+    alternateClassName: 'Ext.data.XmlStore',
+    alias: 'store.xml',
 
-Ext.Element.addMethods({
     
-    getTextWidth : function(text, min, max){
-        return (Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width).constrain(min || 0, max || 1000000);
+    constructor: function(config){
+        config = config || {};
+        config = config || {};
+
+        Ext.applyIf(config, {
+            proxy: {
+                type: 'ajax',
+                reader: 'xml',
+                writer: 'xml'
+            }
+        });
+
+        this.callParent([config]);
     }
 });
 
-Ext.util.Cookies = {
-    
-    set : function(name, value){
-        var argv = arguments;
-        var argc = arguments.length;
-        var expires = (argc > 2) ? argv[2] : null;
-        var path = (argc > 3) ? argv[3] : '/';
-        var domain = (argc > 4) ? argv[4] : null;
-        var secure = (argc > 5) ? argv[5] : false;
-        document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
-    },
 
-    
-    get : function(name){
-        var arg = name + "=";
-        var alen = arg.length;
-        var clen = document.cookie.length;
-        var i = 0;
-        var j = 0;
-        while(i < clen){
-            j = i + alen;
-            if(document.cookie.substring(i, j) == arg){
-                return Ext.util.Cookies.getCookieVal(j);
-            }
-            i = document.cookie.indexOf(" ", i) + 1;
-            if(i === 0){
-                break;
-            }
-        }
-        return null;
-    },
+Ext.define('Ext.data.proxy.Client', {
+    extend: 'Ext.data.proxy.Proxy',
+    alternateClassName: 'Ext.data.ClientProxy',
 
     
-    clear : function(name){
-        if(Ext.util.Cookies.get(name)){
-            document.cookie = name + "=" + "; expires=Thu, 01-Jan-70 00:00:01 GMT";
-        }
-    },
-    
-    getCookieVal : function(offset){
-        var endstr = document.cookie.indexOf(";", offset);
-        if(endstr == -1){
-            endstr = document.cookie.length;
-        }
-        return unescape(document.cookie.substring(offset, endstr));
+    clear: function() {
     }
-};
-Ext.handleError = function(e) {
-    throw e;
-};
+});
 
+Ext.define('Ext.data.proxy.JsonP', {
+    extend: 'Ext.data.proxy.Server',
+    alternateClassName: 'Ext.data.ScriptTagProxy',
+    alias: ['proxy.jsonp', 'proxy.scripttag'],
+    requires: ['Ext.data.JsonP'],
 
-Ext.Error = function(message) {
-    
-    this.message = (this.lang[message]) ? this.lang[message] : message;
-};
+    defaultWriterType: 'base',
 
-Ext.Error.prototype = new Error();
-Ext.apply(Ext.Error.prototype, {
     
-    lang: {},
+    callbackKey : 'callback',
 
-    name: 'Ext.Error',
     
-    getName : function() {
-        return this.name;
-    },
+    recordParam: 'records',
+
     
-    getMessage : function() {
-        return this.message;
+    autoAppendParams: true,
+
+    constructor: function(){
+        this.addEvents(
+            
+            'exception'
+        );
+        this.callParent(arguments);
     },
+
     
-    toJson : function() {
-        return Ext.encode(this);
-    }
-});
+    doRequest: function(operation, callback, scope) {
+        
+        var me      = this,
+            writer  = me.getWriter(),
+            request = me.buildRequest(operation),
+            params = request.params;
 
-Ext.ComponentMgr = function(){
-    var all = new Ext.util.MixedCollection();
-    var types = {};
-    var ptypes = {};
+        if (operation.allowWrite()) {
+            request = writer.write(request);
+        }
 
-    return {
         
-        register : function(c){
-            all.add(c);
-        },
+        Ext.apply(request, {
+            callbackKey: me.callbackKey,
+            timeout: me.timeout,
+            scope: me,
+            disableCaching: false, 
+            callback: me.createRequestCallback(request, operation, callback, scope)
+        });
 
         
-        unregister : function(c){
-            all.remove(c);
-        },
+        if (me.autoAppendParams) {
+            request.params = {};
+        }
 
+        request.jsonp = Ext.data.JsonP.request(request);
         
-        get : function(id){
-            return all.get(id);
-        },
+        request.params = params;
+        operation.setStarted();
+        me.lastRequest = request;
 
-        
-        onAvailable : function(id, fn, scope){
-            all.on("add", function(index, o){
-                if(o.id == id){
-                    fn.call(scope || o, o);
-                    all.un("add", fn, scope);
+        return request;
+    },
+
+    
+    createRequestCallback: function(request, operation, callback, scope) {
+        var me = this;
+
+        return function(success, response, errorType) {
+            delete me.lastRequest;
+            me.processResponse(success, operation, request, response, callback, scope);
+        };
+    },
+
+    
+    setException: function(operation, response) {
+        operation.setException(operation.request.jsonp.errorType);
+    },
+
+
+    
+    buildUrl: function(request) {
+        var me      = this,
+            url     = me.callParent(arguments),
+            params  = Ext.apply({}, request.params),
+            filters = params.filters,
+            records,
+            filter, i;
+
+        delete params.filters;
+
+        if (me.autoAppendParams) {
+            url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
+        }
+
+        if (filters && filters.length) {
+            for (i = 0; i < filters.length; i++) {
+                filter = filters[i];
+
+                if (filter.value) {
+                    url = Ext.urlAppend(url, filter.property + "=" + filter.value);
                 }
-            });
-        },
+            }
+        }
 
         
-        all : all,
-        
-        
-        types : types,
-        
-        
-        ptypes: ptypes,
-        
-        
-        isRegistered : function(xtype){
-            return types[xtype] !== undefined;    
-        },
-        
-        
-        isPluginRegistered : function(ptype){
-            return ptypes[ptype] !== undefined;    
-        },        
+        records = request.records;
 
-        
-        registerType : function(xtype, cls){
-            types[xtype] = cls;
-            cls.xtype = xtype;
-        },
+        if (Ext.isArray(records) && records.length > 0) {
+            url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.recordParam, me.encodeRecords(records)));
+        }
 
-        
-        create : function(config, defaultType){
-            return config.render ? config : new types[config.xtype || defaultType](config);
-        },
+        return url;
+    },
 
-        
-        registerPlugin : function(ptype, cls){
-            ptypes[ptype] = cls;
-            cls.ptype = ptype;
-        },
+    
+    destroy: function() {
+        this.abort();
+        this.callParent();
+    },
 
-        
-        createPlugin : function(config, defaultType){
-            var PluginCls = ptypes[config.ptype || defaultType];
-            if (PluginCls.init) {
-                return PluginCls;                
-            } else {
-                return new PluginCls(config);
-            }            
+    
+    abort: function() {
+        var lastRequest = this.lastRequest;
+        if (lastRequest) {
+            Ext.data.JsonP.abort(lastRequest.jsonp);
+        }
+    },
+
+    
+    encodeRecords: function(records) {
+        var encoded = "",
+            i = 0,
+            len = records.length;
+
+        for (; i < len; i++) {
+            encoded += Ext.Object.toQueryString(records[i].data);
         }
-    };
-}();
 
+        return encoded;
+    }
+});
 
-Ext.reg = Ext.ComponentMgr.registerType; 
 
-Ext.preg = Ext.ComponentMgr.registerPlugin;
+Ext.define('Ext.data.proxy.WebStorage', {
+    extend: 'Ext.data.proxy.Client',
+    alternateClassName: 'Ext.data.WebStorageProxy',
 
-Ext.create = Ext.ComponentMgr.create;
-Ext.Component = function(config){
-    config = config || {};
-    if(config.initialConfig){
-        if(config.isAction){           
-            this.baseAction = config;
-        }
-        config = config.initialConfig; 
-    }else if(config.tagName || config.dom || Ext.isString(config)){ 
-        config = {applyTo: config, id: config.id || config};
-    }
+    
+    id: undefined,
 
     
-    this.initialConfig = config;
+    constructor: function(config) {
+        this.callParent(arguments);
 
-    Ext.apply(this, config);
-    this.addEvents(
-        
-        'added',
-        
-        'disable',
-        
-        'enable',
-        
-        'beforeshow',
-        
-        'show',
-        
-        'beforehide',
-        
-        'hide',
-        
-        'removed',
-        
-        'beforerender',
-        
-        'render',
         
-        'afterrender',
-        
-        'beforedestroy',
-        
-        'destroy',
-        
-        'beforestaterestore',
-        
-        'staterestore',
-        
-        'beforestatesave',
+        this.cache = {};
+
+
         
-        'statesave'
-    );
-    this.getId();
-    Ext.ComponentMgr.register(this);
-    Ext.Component.superclass.constructor.call(this);
+        this.id = this.id || (this.store ? this.store.storeId : undefined);
 
-    if(this.baseAction){
-        this.baseAction.addComponent(this);
-    }
 
-    this.initComponent();
+        this.initialize();
+    },
+
+    
+    create: function(operation, callback, scope) {
+        var records = operation.records,
+            length  = records.length,
+            ids     = this.getIds(),
+            id, record, i;
+
+        operation.setStarted();
 
-    if(this.plugins){
-        if(Ext.isArray(this.plugins)){
-            for(var i = 0, len = this.plugins.length; i < len; i++){
-                this.plugins[i] = this.initPlugin(this.plugins[i]);
+        for (i = 0; i < length; i++) {
+            record = records[i];
+
+            if (record.phantom) {
+                record.phantom = false;
+                id = this.getNextId();
+            } else {
+                id = record.getId();
             }
-        }else{
-            this.plugins = this.initPlugin(this.plugins);
-        }
-    }
 
-    if(this.stateful !== false){
-        this.initState();
-    }
+            this.setRecord(record, id);
+            ids.push(id);
+        }
 
-    if(this.applyTo){
-        this.applyToMarkup(this.applyTo);
-        delete this.applyTo;
-    }else if(this.renderTo){
-        this.render(this.renderTo);
-        delete this.renderTo;
-    }
-};
+        this.setIds(ids);
 
+        operation.setCompleted();
+        operation.setSuccessful();
 
-Ext.Component.AUTO_ID = 1000;
+        if (typeof callback == 'function') {
+            callback.call(scope || this, operation);
+        }
+    },
 
-Ext.extend(Ext.Component, Ext.util.Observable, {
-    
-    
-    
-    
-    
-    
     
+    read: function(operation, callback, scope) {
+        
 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    disabled : false,
-    
-    hidden : false,
-    
-    
-    
-    
-    
-    
-    
-    autoEl : 'div',
+        var records = [],
+            ids     = this.getIds(),
+            length  = ids.length,
+            i, recordData, record;
 
-    
-    disabledClass : 'x-item-disabled',
-    
-    allowDomMove : true,
-    
-    autoShow : false,
-    
-    hideMode : 'display',
-    
-    hideParent : false,
-    
-    
-    
-    
-    
-    rendered : false,
+        
+        if (operation.id) {
+            record = this.getRecord(operation.id);
 
-    
-    
+            if (record) {
+                records.push(record);
+                operation.setSuccessful();
+            }
+        } else {
+            for (i = 0; i < length; i++) {
+                records.push(this.getRecord(ids[i]));
+            }
+            operation.setSuccessful();
+        }
 
-    
+        operation.setCompleted();
 
-    
-    tplWriteMode : 'overwrite',
+        operation.resultSet = Ext.create('Ext.data.ResultSet', {
+            records: records,
+            total  : records.length,
+            loaded : true
+        });
+
+        if (typeof callback == 'function') {
+            callback.call(scope || this, operation);
+        }
+    },
 
     
-    
-    
-    bubbleEvents: [],
+    update: function(operation, callback, scope) {
+        var records = operation.records,
+            length  = records.length,
+            ids     = this.getIds(),
+            record, id, i;
 
+        operation.setStarted();
 
-    
-    ctype : 'Ext.Component',
+        for (i = 0; i < length; i++) {
+            record = records[i];
+            this.setRecord(record);
 
-    
-    actionMode : 'el',
+            
+            
+            id = record.getId();
+            if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) {
+                ids.push(id);
+            }
+        }
+        this.setIds(ids);
 
-    
-    getActionEl : function(){
-        return this[this.actionMode];
-    },
+        operation.setCompleted();
+        operation.setSuccessful();
 
-    initPlugin : function(p){
-        if(p.ptype && !Ext.isFunction(p.init)){
-            p = Ext.ComponentMgr.createPlugin(p);
-        }else if(Ext.isString(p)){
-            p = Ext.ComponentMgr.createPlugin({
-                ptype: p
-            });
+        if (typeof callback == 'function') {
+            callback.call(scope || this, operation);
         }
-        p.init(this);
-        return p;
     },
 
     
-    initComponent : function(){
-        
-        if(this.listeners){
-            this.on(this.listeners);
-            delete this.listeners;
+    destroy: function(operation, callback, scope) {
+        var records = operation.records,
+            length  = records.length,
+            ids     = this.getIds(),
+
+            
+            newIds  = [].concat(ids),
+            i;
+
+        for (i = 0; i < length; i++) {
+            Ext.Array.remove(newIds, records[i].getId());
+            this.removeRecord(records[i], false);
+        }
+
+        this.setIds(newIds);
+
+        operation.setCompleted();
+        operation.setSuccessful();
+
+        if (typeof callback == 'function') {
+            callback.call(scope || this, operation);
         }
-        this.enableBubble(this.bubbleEvents);
     },
 
     
-    render : function(container, position){
-        if(!this.rendered && this.fireEvent('beforerender', this) !== false){
-            if(!container && this.el){
-                this.el = Ext.get(this.el);
-                container = this.el.dom.parentNode;
-                this.allowDomMove = false;
-            }
-            this.container = Ext.get(container);
-            if(this.ctCls){
-                this.container.addClass(this.ctCls);
-            }
-            this.rendered = true;
-            if(position !== undefined){
-                if(Ext.isNumber(position)){
-                    position = this.container.dom.childNodes[position];
-                }else{
-                    position = Ext.getDom(position);
-                }
-            }
-            this.onRender(this.container, position || null);
-            if(this.autoShow){
-                this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
-            }
-            if(this.cls){
-                this.el.addClass(this.cls);
-                delete this.cls;
-            }
-            if(this.style){
-                this.el.applyStyles(this.style);
-                delete this.style;
-            }
-            if(this.overCls){
-                this.el.addClassOnOver(this.overCls);
-            }
-            this.fireEvent('render', this);
+    getRecord: function(id) {
+        if (this.cache[id] === undefined) {
+            var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
+                data    = {},
+                Model   = this.model,
+                fields  = Model.prototype.fields.items,
+                length  = fields.length,
+                i, field, name, record;
 
+            for (i = 0; i < length; i++) {
+                field = fields[i];
+                name  = field.name;
 
-            
-            
-            var contentTarget = this.getContentTarget();
-            if (this.html){
-                contentTarget.update(Ext.DomHelper.markup(this.html));
-                delete this.html;
-            }
-            if (this.contentEl){
-                var ce = Ext.getDom(this.contentEl);
-                Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
-                contentTarget.appendChild(ce);
-            }
-            if (this.tpl) {
-                if (!this.tpl.compile) {
-                    this.tpl = new Ext.XTemplate(this.tpl);
-                }
-                if (this.data) {
-                    this.tpl[this.tplWriteMode](contentTarget, this.data);
-                    delete this.data;
+                if (typeof field.decode == 'function') {
+                    data[name] = field.decode(rawData[name]);
+                } else {
+                    data[name] = rawData[name];
                 }
             }
-            this.afterRender(this.container);
-
 
-            if(this.hidden){
-                
-                this.doHide();
-            }
-            if(this.disabled){
-                
-                this.disable(true);
-            }
+            record = new Model(data, id);
+            record.phantom = false;
 
-            if(this.stateful !== false){
-                this.initStateEvents();
-            }
-            this.fireEvent('afterrender', this);
+            this.cache[id] = record;
         }
-        return this;
-    },
 
+        return this.cache[id];
+    },
 
     
-    update: function(htmlOrData, loadScripts, cb) {
-        var contentTarget = this.getContentTarget();
-        if (this.tpl && typeof htmlOrData !== "string") {
-            this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
+    setRecord: function(record, id) {
+        if (id) {
+            record.setId(id);
         } else {
-            var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
-            contentTarget.update(html, loadScripts, cb);
+            id = record.getId();
         }
-    },
 
+        var me = this,
+            rawData = record.data,
+            data    = {},
+            model   = me.model,
+            fields  = model.prototype.fields.items,
+            length  = fields.length,
+            i = 0,
+            field, name, obj, key;
 
-    
-    onAdded : function(container, pos) {
-        this.ownerCt = container;
-        this.initRef();
-        this.fireEvent('added', this, container, pos);
-    },
+        for (; i < length; i++) {
+            field = fields[i];
+            name  = field.name;
 
-    
-    onRemoved : function() {
-        this.removeRef();
-        this.fireEvent('removed', this, this.ownerCt);
-        delete this.ownerCt;
+            if (typeof field.encode == 'function') {
+                data[name] = field.encode(rawData[name], record);
+            } else {
+                data[name] = rawData[name];
+            }
+        }
+
+        obj = me.getStorageObject();
+        key = me.getRecordKey(id);
+
+        
+        me.cache[id] = record;
+
+        
+        obj.removeItem(key);
+        obj.setItem(key, Ext.encode(data));
     },
 
     
-    initRef : function() {
-        
-        if(this.ref && !this.refOwner){
-            var levels = this.ref.split('/'),
-                last = levels.length,
-                i = 0,
-                t = this;
+    removeRecord: function(id, updateIds) {
+        var me = this,
+            ids;
 
-            while(t && i < last){
-                t = t.ownerCt;
-                ++i;
-            }
-            if(t){
-                t[this.refName = levels[--i]] = this;
-                
-                this.refOwner = t;
-            }
+        if (id.isModel) {
+            id = id.getId();
         }
-    },
 
-    removeRef : function() {
-        if (this.refOwner && this.refName) {
-            delete this.refOwner[this.refName];
-            delete this.refOwner;
+        if (updateIds !== false) {
+            ids = me.getIds();
+            Ext.Array.remove(ids, id);
+            me.setIds(ids);
         }
+
+        me.getStorageObject().removeItem(me.getRecordKey(id));
     },
 
     
-    initState : function(){
-        if(Ext.state.Manager){
-            var id = this.getStateId();
-            if(id){
-                var state = Ext.state.Manager.get(id);
-                if(state){
-                    if(this.fireEvent('beforestaterestore', this, state) !== false){
-                        this.applyState(Ext.apply({}, state));
-                        this.fireEvent('staterestore', this, state);
-                    }
-                }
-            }
+    getRecordKey: function(id) {
+        if (id.isModel) {
+            id = id.getId();
         }
+
+        return Ext.String.format("{0}-{1}", this.id, id);
     },
 
     
-    getStateId : function(){
-        return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
+    getRecordCounterKey: function() {
+        return Ext.String.format("{0}-counter", this.id);
     },
 
     
-    initStateEvents : function(){
-        if(this.stateEvents){
-            for(var i = 0, e; e = this.stateEvents[i]; i++){
-                this.on(e, this.saveState, this, {delay:100});
+    getIds: function() {
+        var ids    = (this.getStorageObject().getItem(this.id) || "").split(","),
+            length = ids.length,
+            i;
+
+        if (length == 1 && ids[0] === "") {
+            ids = [];
+        } else {
+            for (i = 0; i < length; i++) {
+                ids[i] = parseInt(ids[i], 10);
             }
         }
+
+        return ids;
     },
 
     
-    applyState : function(state){
-        if(state){
-            Ext.apply(this, state);
+    setIds: function(ids) {
+        var obj = this.getStorageObject(),
+            str = ids.join(",");
+
+        obj.removeItem(this.id);
+
+        if (!Ext.isEmpty(str)) {
+            obj.setItem(this.id, str);
         }
     },
 
     
-    getState : function(){
-        return null;
-    },
+    getNextId: function() {
+        var obj  = this.getStorageObject(),
+            key  = this.getRecordCounterKey(),
+            last = obj.getItem(key),
+            ids, id;
 
-    
-    saveState : function(){
-        if(Ext.state.Manager && this.stateful !== false){
-            var id = this.getStateId();
-            if(id){
-                var state = this.getState();
-                if(this.fireEvent('beforestatesave', this, state) !== false){
-                    Ext.state.Manager.set(id, state);
-                    this.fireEvent('statesave', this, state);
-                }
-            }
+        if (last === null) {
+            ids = this.getIds();
+            last = ids[ids.length - 1] || 0;
         }
+
+        id = parseInt(last, 10) + 1;
+        obj.setItem(key, id);
+
+        return id;
     },
 
     
-    applyToMarkup : function(el){
-        this.allowDomMove = false;
-        this.el = Ext.get(el);
-        this.render(this.el.dom.parentNode);
+    initialize: function() {
+        var storageObject = this.getStorageObject();
+        storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
     },
 
     
-    addClass : function(cls){
-        if(this.el){
-            this.el.addClass(cls);
-        }else{
-            this.cls = this.cls ? this.cls + ' ' + cls : cls;
+    clear: function() {
+        var obj = this.getStorageObject(),
+            ids = this.getIds(),
+            len = ids.length,
+            i;
+
+        
+        for (i = 0; i < len; i++) {
+            this.removeRecord(ids[i]);
         }
-        return this;
+
+        
+        obj.removeItem(this.getRecordCounterKey());
+        obj.removeItem(this.id);
     },
 
     
-    removeClass : function(cls){
-        if(this.el){
-            this.el.removeClass(cls);
-        }else if(this.cls){
-            this.cls = this.cls.split(' ').remove(cls).join(' ');
-        }
-        return this;
+    getStorageObject: function() {
+    }
+});
+
+Ext.define('Ext.data.proxy.LocalStorage', {
+    extend: 'Ext.data.proxy.WebStorage',
+    alias: 'proxy.localstorage',
+    alternateClassName: 'Ext.data.LocalStorageProxy',
+    
+    
+    getStorageObject: function() {
+        return window.localStorage;
+    }
+});
+
+Ext.define('Ext.data.proxy.Memory', {
+    extend: 'Ext.data.proxy.Client',
+    alias: 'proxy.memory',
+    alternateClassName: 'Ext.data.MemoryProxy',
+
+    
+
+    constructor: function(config) {
+        this.callParent([config]);
+
+        
+        this.setReader(this.reader);
+    },
+
+    
+    read: function(operation, callback, scope) {
+        var me     = this,
+            reader = me.getReader(),
+            result = reader.read(me.data);
+
+        Ext.apply(operation, {
+            resultSet: result
+        });
+
+        operation.setCompleted();
+        operation.setSuccessful();
+        Ext.callback(callback, scope || me, [operation]);
     },
 
+    clear: Ext.emptyFn
+});
+
+
+Ext.define('Ext.data.proxy.Rest', {
+    extend: 'Ext.data.proxy.Ajax',
+    alternateClassName: 'Ext.data.RestProxy',
+    alias : 'proxy.rest',
     
     
-    onRender : function(ct, position){
-        if(!this.el && this.autoEl){
-            if(Ext.isString(this.autoEl)){
-                this.el = document.createElement(this.autoEl);
-            }else{
-                var div = document.createElement('div');
-                Ext.DomHelper.overwrite(div, this.autoEl);
-                this.el = div.firstChild;
-            }
-            if (!this.el.id) {
-                this.el.id = this.getId();
+    appendId: true,
+    
+    
+    
+    
+    batchActions: false,
+    
+    
+    buildUrl: function(request) {
+        var me        = this,
+            operation = request.operation,
+            records   = operation.records || [],
+            record    = records[0],
+            format    = me.format,
+            url       = me.getUrl(request),
+            id        = record ? record.getId() : operation.id;
+        
+        if (me.appendId && id) {
+            if (!url.match(/\/$/)) {
+                url += '/';
             }
+            
+            url += id;
         }
-        if(this.el){
-            this.el = Ext.get(this.el);
-            if(this.allowDomMove !== false){
-                ct.dom.insertBefore(this.el.dom, position);
-                if (div) {
-                    Ext.removeNode(div);
-                    div = null;
-                }
+        
+        if (format) {
+            if (!url.match(/\.$/)) {
+                url += '.';
             }
+            
+            url += format;
         }
-    },
+        
+        request.url = url;
+        
+        return me.callParent(arguments);
+    }
+}, function() {
+    Ext.apply(this.prototype, {
+        
+        actionMethods: {
+            create : 'POST',
+            read   : 'GET',
+            update : 'PUT',
+            destroy: 'DELETE'
+        }
+    });
+});
+
+
+Ext.define('Ext.data.proxy.SessionStorage', {
+    extend: 'Ext.data.proxy.WebStorage',
+    alias: 'proxy.sessionstorage',
+    alternateClassName: 'Ext.data.SessionStorageProxy',
+    
+    
+    getStorageObject: function() {
+        return window.sessionStorage;
+    }
+});
+
+
+Ext.define('Ext.data.reader.Array', {
+    extend: 'Ext.data.reader.Json',
+    alternateClassName: 'Ext.data.ArrayReader',
+    alias : 'reader.array',
 
     
-    getAutoCreate : function(){
-        var cfg = Ext.isObject(this.autoCreate) ?
-                      this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
-        if(this.id && !cfg.id){
-            cfg.id = this.id;
+    buildExtractors: function() {
+        this.callParent(arguments);
+        
+        var fields = this.model.prototype.fields.items,
+            i = 0,
+            length = fields.length,
+            extractorFunctions = [],
+            map;
+        
+        for (; i < length; i++) {
+            map = fields[i].mapping;
+            extractorFunctions.push(function(index) {
+                return function(data) {
+                    return data[index];
+                };
+            }(map !== null ? map : i));
         }
-        return cfg;
-    },
+        
+        this.extractorFunctions = extractorFunctions;
+    }
+});
+
+
+Ext.define('Ext.data.reader.Xml', {
+    extend: 'Ext.data.reader.Reader',
+    alternateClassName: 'Ext.data.XmlReader',
+    alias : 'reader.xml',
 
     
-    afterRender : Ext.emptyFn,
 
     
-    destroy : function(){
-        if(!this.isDestroyed){
-            if(this.fireEvent('beforedestroy', this) !== false){
-                this.destroying = true;
-                this.beforeDestroy();
-                if(this.ownerCt && this.ownerCt.remove){
-                    this.ownerCt.remove(this, false);
-                }
-                if(this.rendered){
-                    this.el.remove();
-                    if(this.actionMode == 'container' || this.removeMode == 'container'){
-                        this.container.remove();
-                    }
-                }
-                
-                if(this.focusTask && this.focusTask.cancel){
-                    this.focusTask.cancel();
-                }
-                this.onDestroy();
-                Ext.ComponentMgr.unregister(this);
-                this.fireEvent('destroy', this);
-                this.purgeListeners();
-                this.destroying = false;
-                this.isDestroyed = true;
-            }
+    createAccessor: function(expr) {
+        var me = this;
+
+        if (Ext.isEmpty(expr)) {
+            return Ext.emptyFn;
+        }
+
+        if (Ext.isFunction(expr)) {
+            return expr;
         }
+
+        return function(root) {
+            return me.getNodeValue(Ext.DomQuery.selectNode(expr, root));
+        };
     },
 
-    deleteMembers : function(){
-        var args = arguments;
-        for(var i = 0, len = args.length; i < len; ++i){
-            delete this[args[i]];
+    getNodeValue: function(node) {
+        if (node && node.firstChild) {
+            return node.firstChild.nodeValue;
         }
+        return undefined;
     },
 
     
-    beforeDestroy : Ext.emptyFn,
+    getResponseData: function(response) {
+        var xml = response.responseXML;
 
-    
-    onDestroy  : Ext.emptyFn,
 
-    
-    getEl : function(){
-        return this.el;
+        return xml;
     },
 
     
-    getContentTarget : function(){
-        return this.el;
+    getData: function(data) {
+        return data.documentElement || data;
     },
 
     
-    getId : function(){
-        return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
-    },
+    getRoot: function(data) {
+        var nodeName = data.nodeName,
+            root     = this.root;
 
-    
-    getItemId : function(){
-        return this.itemId || this.getId();
+        if (!root || (nodeName && nodeName == root)) {
+            return data;
+        } else if (Ext.DomQuery.isXml(data)) {
+            
+            
+            
+            return Ext.DomQuery.selectNode(root, data);
+        }
     },
 
     
-    focus : function(selectText, delay){
-        if(delay){
-            this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
-            this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
-            return;
-        }
-        if(this.rendered && !this.isDestroyed){
-            this.el.focus();
-            if(selectText === true){
-                this.el.dom.select();
-            }
+    extractData: function(root) {
+        var recordName = this.record;
+
+
+        if (recordName != root.nodeName) {
+            root = Ext.DomQuery.select(recordName, root);
+        } else {
+            root = [root];
         }
-        return this;
+        return this.callParent([root]);
     },
 
     
-    blur : function(){
-        if(this.rendered){
-            this.el.blur();
-        }
-        return this;
+    getAssociatedDataRoot: function(data, associationName) {
+        return Ext.DomQuery.select(associationName, data)[0];
     },
 
     
-    disable : function( silent){
-        if(this.rendered){
-            this.onDisable();
-        }
-        this.disabled = true;
-        if(silent !== true){
-            this.fireEvent('disable', this);
+    readRecords: function(doc) {
+        
+        if (Ext.isArray(doc)) {
+            doc = doc[0];
         }
-        return this;
-    },
 
-    
-    onDisable : function(){
-        this.getActionEl().addClass(this.disabledClass);
-        this.el.dom.disabled = true;
-    },
+        
+        this.xmlData = doc;
+        return this.callParent([doc]);
+    }
+});
 
+Ext.define('Ext.data.writer.Xml', {
     
-    enable : function(){
-        if(this.rendered){
-            this.onEnable();
-        }
-        this.disabled = false;
-        this.fireEvent('enable', this);
-        return this;
-    },
+    
+    
+    extend: 'Ext.data.writer.Writer',
+    alternateClassName: 'Ext.data.XmlWriter',
+    
+    alias: 'writer.xml',
+    
+    
+    
+    
+    documentRoot: 'xmlData',
+    
+    
+    defaultDocumentRoot: 'xmlData',
 
     
-    onEnable : function(){
-        this.getActionEl().removeClass(this.disabledClass);
-        this.el.dom.disabled = false;
-    },
+    header: '',
 
     
-    setDisabled : function(disabled){
-        return this[disabled ? 'disable' : 'enable']();
-    },
+    record: 'record',
 
     
-    show : function(){
-        if(this.fireEvent('beforeshow', this) !== false){
-            this.hidden = false;
-            if(this.autoRender){
-                this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
-            }
-            if(this.rendered){
-                this.onShow();
+    writeRecords: function(request, data) {
+        var me = this,
+            xml = [],
+            i = 0,
+            len = data.length,
+            root = me.documentRoot,
+            record = me.record,
+            needsRoot = data.length !== 1,
+            item,
+            key;
+            
+        
+        xml.push(me.header || '');
+        
+        if (!root && needsRoot) {
+            root = me.defaultDocumentRoot;
+        }
+        
+        if (root) {
+            xml.push('<', root, '>');
+        }
+            
+        for (; i < len; ++i) {
+            item = data[i];
+            xml.push('<', record, '>');
+            for (key in item) {
+                if (item.hasOwnProperty(key)) {
+                    xml.push('<', key, '>', item[key], '</', key, '>');
+                }
             }
-            this.fireEvent('show', this);
+            xml.push('</', record, '>');
         }
-        return this;
-    },
+        
+        if (root) {
+            xml.push('</', root, '>');
+        }
+            
+        request.xmlData = xml.join('');
+        return request;
+    }
+});
+
+
+Ext.define('Ext.direct.Event', {
 
     
-    onShow : function(){
-        this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
-    },
+
+    alias: 'direct.event',
+
+    requires: ['Ext.direct.Manager'],
 
     
-    hide : function(){
-        if(this.fireEvent('beforehide', this) !== false){
-            this.doHide();
-            this.fireEvent('hide', this);
-        }
-        return this;
-    },
+
+    status: true,
 
     
-    doHide: function(){
-        this.hidden = true;
-        if(this.rendered){
-            this.onHide();
-        }
+    constructor: function(config) {
+        Ext.apply(this, config);
     },
 
     
-    onHide : function(){
-        this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
-    },
+    getData: function(){
+        return this.data;
+    }
+});
+
 
+Ext.define('Ext.direct.RemotingEvent', {
     
-    getVisibilityEl : function(){
-        return this.hideParent ? this.container : this.getActionEl();
-    },
+    
+   
+    extend: 'Ext.direct.Event',
+    
+    alias: 'direct.rpc',
+    
+    
+    
+    
+    getTransaction: function(){
+        return this.transaction || Ext.direct.Manager.getTransaction(this.tid);
+    }
+});
+
 
+Ext.define('Ext.direct.ExceptionEvent', {
     
-    setVisible : function(visible){
-        return this[visible ? 'show' : 'hide']();
-    },
+    
+   
+    extend: 'Ext.direct.RemotingEvent',
+    
+    alias: 'direct.exception',
+    
+    
+   
+   status: false
+});
+
+
+Ext.define('Ext.direct.Provider', {
 
     
-    isVisible : function(){
-        return this.rendered && this.getVisibilityEl().isVisible();
+
+   alias: 'direct.provider',
+
+    mixins: {
+        observable: 'Ext.util.Observable'
     },
 
     
-    cloneConfig : function(overrides){
-        overrides = overrides || {};
-        var id = overrides.id || Ext.id();
-        var cfg = Ext.applyIf(overrides, this.initialConfig);
-        cfg.id = id; 
-        return new this.constructor(cfg);
+
+   
+
+    constructor : function(config){
+        var me = this;
+
+        Ext.apply(me, config);
+        me.addEvents(
+            
+            'connect',
+            
+            'disconnect',
+            
+            'data',
+            
+            'exception'
+        );
+        me.mixins.observable.constructor.call(me, config);
     },
 
     
-    getXType : function(){
-        return this.constructor.xtype;
+    isConnected: function(){
+        return false;
     },
 
     
-    isXType : function(xtype, shallow){
-        
-        if (Ext.isFunction(xtype)){
-            xtype = xtype.xtype; 
-        }else if (Ext.isObject(xtype)){
-            xtype = xtype.constructor.xtype; 
-        }
+    connect: Ext.emptyFn,
 
-        return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
-    },
+    
+    disconnect: Ext.emptyFn
+});
+
+
+
+Ext.define('Ext.direct.JsonProvider', {
+
+    
+
+    extend: 'Ext.direct.Provider',
+
+    alias: 'direct.jsonprovider',
+
+    uses: ['Ext.direct.ExceptionEvent'],
 
     
-    getXTypes : function(){
-        var tc = this.constructor;
-        if(!tc.xtypes){
-            var c = [], sc = this;
-            while(sc && sc.constructor.xtype){
-                c.unshift(sc.constructor.xtype);
-                sc = sc.constructor.superclass;
+
+   
+   parseResponse: function(response){
+        if (!Ext.isEmpty(response.responseText)) {
+            if (Ext.isObject(response.responseText)) {
+                return response.responseText;
             }
-            tc.xtypeChain = c;
-            tc.xtypes = c.join('/');
+            return Ext.decode(response.responseText);
         }
-        return tc.xtypes;
+        return null;
     },
 
     
-    findParentBy : function(fn) {
-        for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
-        return p || null;
+    createEvents: function(response){
+        var data = null,
+            events = [],
+            event,
+            i = 0,
+            len;
+
+        try{
+            data = this.parseResponse(response);
+        } catch(e) {
+            event = Ext.create('Ext.direct.ExceptionEvent', {
+                data: e,
+                xhr: response,
+                code: Ext.direct.Manager.self.exceptions.PARSE,
+                message: 'Error parsing json response: \n\n ' + data
+            });
+            return [event];
+        }
+
+        if (Ext.isArray(data)) {
+            for (len = data.length; i < len; ++i) {
+                events.push(this.createEvent(data[i]));
+            }
+        } else {
+            events.push(this.createEvent(data));
+        }
+        return events;
     },
 
     
-    findParentByType : function(xtype) {
-        return Ext.isFunction(xtype) ?
-            this.findParentBy(function(p){
-                return p.constructor === xtype;
-            }) :
-            this.findParentBy(function(p){
-                return p.constructor.xtype === xtype;
-            });
+    createEvent: function(response){
+        return Ext.create('direct.' + response.type, response);
+    }
+});
+
+Ext.define('Ext.direct.PollingProvider', {
+    
+    
+    
+    extend: 'Ext.direct.JsonProvider',
+    
+    alias: 'direct.pollingprovider',
+    
+    uses: ['Ext.direct.ExceptionEvent'],
+    
+    requires: ['Ext.Ajax', 'Ext.util.DelayedTask'],
+    
+    
+    
+    
+    interval: 3000,
+
+    
+    
+    
+
+    
+    constructor : function(config){
+        this.callParent(arguments);
+        this.addEvents(
+            
+            'beforepoll',            
+            
+            'poll'
+        );
     },
 
     
-    getPositionEl : function(){
-        return this.positionEl || this.el;
+    isConnected: function(){
+        return !!this.pollTask;
     },
 
     
-    purgeListeners : function(){
-        Ext.Component.superclass.purgeListeners.call(this);
-        if(this.mons){
-            this.on('beforedestroy', this.clearMons, this, {single: true});
+    connect: function(){
+        var me = this, url = me.url;
+        
+        if (url && !me.pollTask) {
+            me.pollTask = Ext.TaskManager.start({
+                run: function(){
+                    if (me.fireEvent('beforepoll', me) !== false) {
+                        if (Ext.isFunction(url)) {
+                            url(me.baseParams);
+                        } else {
+                            Ext.Ajax.request({
+                                url: url,
+                                callback: me.onData,
+                                scope: me,
+                                params: me.baseParams
+                            });
+                        }
+                    }
+                },
+                interval: me.interval,
+                scope: me
+            });
+            me.fireEvent('connect', me);
+        } else if (!url) {
         }
     },
 
     
-    clearMons : function(){
-        Ext.each(this.mons, function(m){
-            m.item.un(m.ename, m.fn, m.scope);
-        }, this);
-        this.mons = [];
+    disconnect: function(){
+        var me = this;
+        
+        if (me.pollTask) {
+            Ext.TaskManager.stop(me.pollTask);
+            delete me.pollTask;
+            me.fireEvent('disconnect', me);
+        }
     },
 
     
-    createMons: function(){
-        if(!this.mons){
-            this.mons = [];
-            this.on('beforedestroy', this.clearMons, this, {single: true});
+    onData: function(opt, success, response){
+        var me = this, 
+            i = 0, 
+            len,
+            events;
+        
+        if (success) {
+            events = me.createEvents(response);
+            for (len = events.length; i < len; ++i) {
+                me.fireEvent('data', me, events[i]);
+            }
+        } else {
+            me.fireEvent('data', me, Ext.create('Ext.direct.ExceptionEvent', {
+                data: null,
+                code: Ext.direct.Manager.self.exceptions.TRANSPORT,
+                message: 'Unable to connect to the server.',
+                xhr: response
+            }));
+        }
+    }
+});
+
+Ext.define('Ext.direct.RemotingMethod', {
+
+    constructor: function(config){
+        var me = this,
+            params = Ext.isDefined(config.params) ? config.params : config.len,
+            name;
+
+        me.name = config.name;
+        me.formHandler = config.formHandler;
+        if (Ext.isNumber(params)) {
+            
+            me.len = params;
+            me.ordered = true;
+        } else {
+            
+            me.params = [];
+            Ext.each(params, function(param){
+                name = Ext.isObject(param) ? param.name : param;
+                me.params.push(name);
+            });
         }
     },
 
     
-    mon : function(item, ename, fn, scope, opt){
-        this.createMons();
-        if(Ext.isObject(ename)){
-            var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
+    getCallData: function(args){
+        var me = this,
+            data = null,
+            len  = me.len,
+            params = me.params,
+            callback,
+            scope,
+            name;
+
+        if (me.ordered) {
+            callback = args[len];
+            scope = args[len + 1];
+            if (len !== 0) {
+                data = args.slice(0, len);
+            }
+        } else {
+            data = Ext.apply({}, args[0]);
+            callback = args[1];
+            scope = args[2];
 
-            var o = ename;
-            for(var e in o){
-                if(propRe.test(e)){
-                    continue;
-                }
-                if(Ext.isFunction(o[e])){
-                    
-                    this.mons.push({
-                        item: item, ename: e, fn: o[e], scope: o.scope
-                    });
-                    item.on(e, o[e], o.scope, o);
-                }else{
-                    
-                    this.mons.push({
-                        item: item, ename: e, fn: o[e], scope: o.scope
-                    });
-                    item.on(e, o[e]);
+            
+            for (name in data) {
+                if (data.hasOwnProperty(name)) {
+                    if (!Ext.Array.contains(params, name)) {
+                        delete data[name];
+                    }
                 }
             }
-            return;
         }
 
-        this.mons.push({
-            item: item, ename: ename, fn: fn, scope: scope
-        });
-        item.on(ename, fn, scope, opt);
-    },
+        return {
+            data: data,
+            callback: callback,
+            scope: scope
+        };
+    }
+});
+
 
+Ext.define('Ext.direct.Transaction', {
     
-    mun : function(item, ename, fn, scope){
-        var found, mon;
-        this.createMons();
-        for(var i = 0, len = this.mons.length; i < len; ++i){
-            mon = this.mons[i];
-            if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
-                this.mons.splice(i, 1);
-                item.un(ename, fn, scope);
-                found = true;
-                break;
-            }
-        }
-        return found;
+    
+   
+    alias: 'direct.transaction',
+    alternateClassName: 'Ext.Direct.Transaction',
+   
+    statics: {
+        TRANSACTION_ID: 0
     },
+   
+    
 
     
-    nextSibling : function(){
-        if(this.ownerCt){
-            var index = this.ownerCt.items.indexOf(this);
-            if(index != -1 && index+1 < this.ownerCt.items.getCount()){
-                return this.ownerCt.items.itemAt(index+1);
-            }
-        }
-        return null;
+    constructor: function(config){
+        var me = this;
+        
+        Ext.apply(me, config);
+        me.id = ++me.self.TRANSACTION_ID;
+        me.retryCount = 0;
+    },
+   
+    send: function(){
+         this.provider.queueTransaction(this);
     },
 
-    
-    previousSibling : function(){
-        if(this.ownerCt){
-            var index = this.ownerCt.items.indexOf(this);
-            if(index > 0){
-                return this.ownerCt.items.itemAt(index-1);
-            }
-        }
-        return null;
+    retry: function(){
+        this.retryCount++;
+        this.send();
     },
 
-    
-    getBubbleTarget : function(){
-        return this.ownerCt;
+    getProvider: function(){
+        return this.provider;
     }
 });
 
-Ext.reg('component', Ext.Component);
-Ext.Action = Ext.extend(Object, {
-    
-    
+
+Ext.define('Ext.direct.RemotingProvider', {
     
     
+   
+    alias: 'direct.remotingprovider',
     
+    extend: 'Ext.direct.JsonProvider', 
     
+    requires: [
+        'Ext.util.MixedCollection', 
+        'Ext.util.DelayedTask', 
+        'Ext.direct.Transaction',
+        'Ext.direct.RemotingMethod'
+    ],
+   
     
-
-    constructor : function(config){
-        this.initialConfig = config;
-        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
-        this.items = [];
-    },
+   
+   
     
     
-    isAction : true,
-
     
-    setText : function(text){
-        this.initialConfig.text = text;
-        this.callEach('setText', [text]);
-    },
-
     
-    getText : function(){
-        return this.initialConfig.text;
-    },
-
     
-    setIconClass : function(cls){
-        this.initialConfig.iconCls = cls;
-        this.callEach('setIconClass', [cls]);
-    },
-
     
-    getIconClass : function(){
-        return this.initialConfig.iconCls;
-    },
-
     
-    setDisabled : function(v){
-        this.initialConfig.disabled = v;
-        this.callEach('setDisabled', [v]);
-    },
-
     
-    enable : function(){
-        this.setDisabled(false);
-    },
-
+    enableBuffer: 10,
     
-    disable : function(){
-        this.setDisabled(true);
-    },
-
     
-    isDisabled : function(){
-        return this.initialConfig.disabled;
-    },
-
+    maxRetries: 1,
     
-    setHidden : function(v){
-        this.initialConfig.hidden = v;
-        this.callEach('setVisible', [!v]);
-    },
-
     
-    show : function(){
-        this.setHidden(false);
-    },
-
+    timeout: undefined,
     
-    hide : function(){
-        this.setHidden(true);
+    constructor : function(config){
+        var me = this;
+        me.callParent(arguments);
+        me.addEvents(
+                        
+            'beforecall',            
+                        
+            'call'
+        );
+        me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;
+        me.transactions = Ext.create('Ext.util.MixedCollection');
+        me.callBuffer = [];
     },
-
     
-    isHidden : function(){
-        return this.initialConfig.hidden;
-    },
-
     
-    setHandler : function(fn, scope){
-        this.initialConfig.handler = fn;
-        this.initialConfig.scope = scope;
-        this.callEach('setHandler', [fn, scope]);
+    initAPI : function(){
+        var actions = this.actions,
+            namespace = this.namespace,
+            action,
+            cls,
+            methods,
+            i,
+            len,
+            method;
+            
+        for (action in actions) {
+            cls = namespace[action];
+            if (!cls) {
+                cls = namespace[action] = {};
+            }
+            methods = actions[action];
+            
+            for (i = 0, len = methods.length; i < len; ++i) {
+                method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
+                cls[method.name] = this.createHandler(action, method);
+            }
+        }
     },
-
     
-    each : function(fn, scope){
-        Ext.each(this.items, fn, scope);
-    },
-
     
-    callEach : function(fnName, args){
-        var cs = this.items;
-        for(var i = 0, len = cs.length; i < len; i++){
-            cs[i][fnName].apply(cs[i], args);
+    createHandler : function(action, method){
+        var me = this,
+            handler;
+        
+        if (!method.formHandler) {
+            handler = function(){
+                me.configureRequest(action, method, Array.prototype.slice.call(arguments, 0));
+            };
+        } else {
+            handler = function(form, callback, scope){
+                me.configureFormRequest(action, method, form, callback, scope);
+            };
         }
+        handler.directCfg = {
+            action: action,
+            method: method
+        };
+        return handler;
     },
-
     
-    addComponent : function(comp){
-        this.items.push(comp);
-        comp.on('destroy', this.removeComponent, this);
-    },
-
     
-    removeComponent : function(comp){
-        this.items.remove(comp);
+    isConnected: function(){
+        return !!this.connected;
     },
 
     
-    execute : function(){
-        this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
-    }
-});
-
-(function(){
-Ext.Layer = function(config, existingEl){
-    config = config || {};
-    var dh = Ext.DomHelper;
-    var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
-    if(existingEl){
-        this.dom = Ext.getDom(existingEl);
-    }
-    if(!this.dom){
-        var o = config.dh || {tag: 'div', cls: 'x-layer'};
-        this.dom = dh.append(pel, o);
-    }
-    if(config.cls){
-        this.addClass(config.cls);
-    }
-    this.constrain = config.constrain !== false;
-    this.setVisibilityMode(Ext.Element.VISIBILITY);
-    if(config.id){
-        this.id = this.dom.id = config.id;
-    }else{
-        this.id = Ext.id(this.dom);
-    }
-    this.zindex = config.zindex || this.getZIndex();
-    this.position('absolute', this.zindex);
-    if(config.shadow){
-        this.shadowOffset = config.shadowOffset || 4;
-        this.shadow = new Ext.Shadow({
-            offset : this.shadowOffset,
-            mode : config.shadow
-        });
-    }else{
-        this.shadowOffset = 0;
-    }
-    this.useShim = config.shim !== false && Ext.useShims;
-    this.useDisplay = config.useDisplay;
-    this.hide();
-};
-
-var supr = Ext.Element.prototype;
-
-
-var shims = [];
-
-Ext.extend(Ext.Layer, Ext.Element, {
-
-    getZIndex : function(){
-        return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
-    },
-
-    getShim : function(){
-        if(!this.useShim){
-            return null;
-        }
-        if(this.shim){
-            return this.shim;
-        }
-        var shim = shims.shift();
-        if(!shim){
-            shim = this.createShim();
-            shim.enableDisplayMode('block');
-            shim.dom.style.display = 'none';
-            shim.dom.style.visibility = 'visible';
-        }
-        var pn = this.dom.parentNode;
-        if(shim.dom.parentNode != pn){
-            pn.insertBefore(shim.dom, this.dom);
-        }
-        shim.setStyle('z-index', this.getZIndex()-2);
-        this.shim = shim;
-        return shim;
-    },
-
-    hideShim : function(){
-        if(this.shim){
-            this.shim.setDisplayed(false);
-            shims.push(this.shim);
-            delete this.shim;
+    connect: function(){
+        var me = this;
+        
+        if (me.url) {
+            me.initAPI();
+            me.connected = true;
+            me.fireEvent('connect', me);
+        } else if(!me.url) {
         }
     },
 
-    disableShadow : function(){
-        if(this.shadow){
-            this.shadowDisabled = true;
-            this.shadow.hide();
-            this.lastShadowOffset = this.shadowOffset;
-            this.shadowOffset = 0;
+    
+    disconnect: function(){
+        var me = this;
+        
+        if (me.connected) {
+            me.connected = false;
+            me.fireEvent('disconnect', me);
         }
     },
-
-    enableShadow : function(show){
-        if(this.shadow){
-            this.shadowDisabled = false;
-            this.shadowOffset = this.lastShadowOffset;
-            delete this.lastShadowOffset;
-            if(show){
-                this.sync(true);
+    
+    
+    runCallback: function(transaction, event){
+        var funcName = event.status ? 'success' : 'failure',
+            callback,
+            result;
+        
+        if (transaction && transaction.callback) {
+            callback = transaction.callback;
+            result = Ext.isDefined(event.result) ? event.result : event.data;
+        
+            if (Ext.isFunction(callback)) {
+                callback(result, event);
+            } else {
+                Ext.callback(callback[funcName], callback.scope, [result, event]);
+                Ext.callback(callback.callback, callback.scope, [result, event]);
             }
         }
     },
-
-    
     
     
-    sync : function(doShow){
-        var shadow = this.shadow;
-        if(!this.updating && this.isVisible() && (shadow || this.useShim)){
-            var shim = this.getShim(),
-                w = this.getWidth(),
-                h = this.getHeight(),
-                l = this.getLeft(true),
-                t = this.getTop(true);
-
-            if(shadow && !this.shadowDisabled){
-                if(doShow && !shadow.isVisible()){
-                    shadow.show(this);
-                }else{
-                    shadow.realign(l, t, w, h);
+    onData: function(options, success, response){
+        var me = this,
+            i = 0,
+            len,
+            events,
+            event,
+            transaction,
+            transactions;
+            
+        if (success) {
+            events = me.createEvents(response);
+            for (len = events.length; i < len; ++i) {
+                event = events[i];
+                transaction = me.getTransaction(event);
+                me.fireEvent('data', me, event);
+                if (transaction) {
+                    me.runCallback(transaction, event, true);
+                    Ext.direct.Manager.removeTransaction(transaction);
                 }
-                if(shim){
-                    if(doShow){
-                       shim.show();
+            }
+        } else {
+            transactions = [].concat(options.transaction);
+            for (len = transactions.length; i < len; ++i) {
+                transaction = me.getTransaction(transactions[i]);
+                if (transaction && transaction.retryCount < me.maxRetries) {
+                    transaction.retry();
+                } else {
+                    event = Ext.create('Ext.direct.ExceptionEvent', {
+                        data: null,
+                        transaction: transaction,
+                        code: Ext.direct.Manager.self.exceptions.TRANSPORT,
+                        message: 'Unable to connect to the server.',
+                        xhr: response
+                    });
+                    me.fireEvent('data', me, event);
+                    if (transaction) {
+                        me.runCallback(transaction, event, false);
+                        Ext.direct.Manager.removeTransaction(transaction);
                     }
-                    
-                    var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
-                        shadowSize = shadow.el.getSize();
-                    shimStyle.left = (shadowAdj[0])+'px';
-                    shimStyle.top = (shadowAdj[1])+'px';
-                    shimStyle.width = (shadowSize.width)+'px';
-                    shimStyle.height = (shadowSize.height)+'px';
-                }
-            }else if(shim){
-                if(doShow){
-                   shim.show();
                 }
-                shim.setSize(w, h);
-                shim.setLeftTop(l, t);
             }
         }
     },
-
     
-    destroy : function(){
-        this.hideShim();
-        if(this.shadow){
-            this.shadow.hide();
-        }
-        this.removeAllListeners();
-        Ext.removeNode(this.dom);
-        delete this.dom;
+    
+    getTransaction: function(options){
+        return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null;
     },
+    
+    
+    configureRequest: function(action, method, args){
+        var me = this,
+            callData = method.getCallData(args),
+            data = callData.data, 
+            callback = callData.callback, 
+            scope = callData.scope,
+            transaction;
+
+        transaction = Ext.create('Ext.direct.Transaction', {
+            provider: me,
+            args: args,
+            action: action,
+            method: method.name,
+            data: data,
+            callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback
+        });
 
-    remove : function(){
-        this.destroy();
+        if (me.fireEvent('beforecall', me, transaction, method) !== false) {
+            Ext.direct.Manager.addTransaction(transaction);
+            me.queueTransaction(transaction);
+            me.fireEvent('call', me, transaction, method);
+        }
     },
-
     
-    beginUpdate : function(){
-        this.updating = true;
+    
+    getCallData: function(transaction){
+        return {
+            action: transaction.action,
+            method: transaction.method,
+            data: transaction.data,
+            type: 'rpc',
+            tid: transaction.id
+        };
     },
+    
+    
+    sendRequest : function(data){
+        var me = this,
+            request = {
+                url: me.url,
+                callback: me.onData,
+                scope: me,
+                transaction: data,
+                timeout: me.timeout
+            }, callData,
+            enableUrlEncode = me.enableUrlEncode,
+            i = 0,
+            len,
+            params;
+            
 
+        if (Ext.isArray(data)) {
+            callData = [];
+            for (len = data.length; i < len; ++i) {
+                callData.push(me.getCallData(data[i]));
+            }
+        } else {
+            callData = me.getCallData(data);
+        }
+
+        if (enableUrlEncode) {
+            params = {};
+            params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData);
+            request.params = params;
+        } else {
+            request.jsonData = callData;
+        }
+        Ext.Ajax.request(request);
+    },
     
-    endUpdate : function(){
-        this.updating = false;
-        this.sync(true);
+    
+    queueTransaction: function(transaction){
+        var me = this,
+            enableBuffer = me.enableBuffer;
+        
+        if (transaction.form) {
+            me.sendFormRequest(transaction);
+            return;
+        }
+        
+        me.callBuffer.push(transaction);
+        if (enableBuffer) {
+            if (!me.callTask) {
+                me.callTask = Ext.create('Ext.util.DelayedTask', me.combineAndSend, me);
+            }
+            me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);
+        } else {
+            me.combineAndSend();
+        }
     },
-
     
-    hideUnders : function(negOffset){
-        if(this.shadow){
-            this.shadow.hide();
+    
+    combineAndSend : function(){
+        var buffer = this.callBuffer,
+            len = buffer.length;
+            
+        if (len > 0) {
+            this.sendRequest(len == 1 ? buffer[0] : buffer);
+            this.callBuffer = [];
         }
-        this.hideShim();
     },
-
     
-    constrainXY : function(){
-        if(this.constrain){
-            var vw = Ext.lib.Dom.getViewWidth(),
-                vh = Ext.lib.Dom.getViewHeight();
-            var s = Ext.getDoc().getScroll();
-
-            var xy = this.getXY();
-            var x = xy[0], y = xy[1];
-            var so = this.shadowOffset;
-            var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
+    
+    configureFormRequest : function(action, method, form, callback, scope){
+        var me = this,
+            transaction = Ext.create('Ext.direct.Transaction', {
+                provider: me,
+                action: action,
+                method: method.name,
+                args: [form, callback, scope],
+                callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback,
+                isForm: true
+            }),
+            isUpload,
+            params;
+
+        if (me.fireEvent('beforecall', me, transaction, method) !== false) {
+            Ext.direct.Manager.addTransaction(transaction);
+            isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data';
+            
+            params = {
+                extTID: transaction.id,
+                extAction: action,
+                extMethod: method.name,
+                extType: 'rpc',
+                extUpload: String(isUpload)
+            };
             
-            var moved = false;
             
-            if((x + w) > vw+s.left){
-                x = vw - w - so;
-                moved = true;
-            }
-            if((y + h) > vh+s.top){
-                y = vh - h - so;
-                moved = true;
-            }
             
-            if(x < s.left){
-                x = s.left;
-                moved = true;
-            }
-            if(y < s.top){
-                y = s.top;
-                moved = true;
-            }
-            if(moved){
-                if(this.avoidY){
-                    var ay = this.avoidY;
-                    if(y <= ay && (y+h) >= ay){
-                        y = ay-h-5;
-                    }
-                }
-                xy = [x, y];
-                this.storeXY(xy);
-                supr.setXY.call(this, xy);
-                this.sync();
-            }
+            Ext.apply(transaction, {
+                form: Ext.getDom(form),
+                isUpload: isUpload,
+                params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
+            });
+            me.fireEvent('call', me, transaction, method);
+            me.sendFormRequest(transaction);
         }
-        return this;
     },
     
-    getConstrainOffset : function(){
-        return this.shadowOffset;    
-    },
+    
+    sendFormRequest: function(transaction){
+        Ext.Ajax.request({
+            url: this.url,
+            params: transaction.params,
+            callback: this.onData,
+            scope: this,
+            form: transaction.form,
+            isUpload: transaction.isUpload,
+            transaction: transaction
+        });
+    }
+    
+});
 
-    isVisible : function(){
-        return this.visible;
-    },
+
+Ext.define('Ext.draw.Matrix', {
 
     
-    showAction : function(){
-        this.visible = true; 
-        if(this.useDisplay === true){
-            this.setDisplayed('');
-        }else if(this.lastXY){
-            supr.setXY.call(this, this.lastXY);
-        }else if(this.lastLT){
-            supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
-        }
-    },
+
+    requires: ['Ext.draw.Draw'],
 
     
-    hideAction : function(){
-        this.visible = false;
-        if(this.useDisplay === true){
-            this.setDisplayed(false);
-        }else{
-            this.setLeftTop(-10000,-10000);
+
+    constructor: function(a, b, c, d, e, f) {
+        if (a != null) {
+            this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
+        }
+        else {
+            this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
         }
     },
 
-    
-    setVisible : function(v, a, d, c, e){
-        if(v){
-            this.showAction();
-        }
-        if(a && v){
-            var cb = function(){
-                this.sync(true);
-                if(c){
-                    c();
+    add: function(a, b, c, d, e, f) {
+        var me = this,
+            out = [[], [], []],
+            matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
+            x,
+            y,
+            z,
+            res;
+
+        for (x = 0; x < 3; x++) {
+            for (y = 0; y < 3; y++) {
+                res = 0;
+                for (z = 0; z < 3; z++) {
+                    res += me.matrix[x][z] * matrix[z][y];
                 }
-            }.createDelegate(this);
-            supr.setVisible.call(this, true, true, d, cb, e);
-        }else{
-            if(!v){
-                this.hideUnders(true);
-            }
-            var cb = c;
-            if(a){
-                cb = function(){
-                    this.hideAction();
-                    if(c){
-                        c();
-                    }
-                }.createDelegate(this);
-            }
-            supr.setVisible.call(this, v, a, d, cb, e);
-            if(v){
-                this.sync(true);
-            }else if(!a){
-                this.hideAction();
+                out[x][y] = res;
             }
         }
-        return this;
+        me.matrix = out;
     },
 
-    storeXY : function(xy){
-        delete this.lastLT;
-        this.lastXY = xy;
+    prepend: function(a, b, c, d, e, f) {
+        var me = this,
+            out = [[], [], []],
+            matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
+            x,
+            y,
+            z,
+            res;
+
+        for (x = 0; x < 3; x++) {
+            for (y = 0; y < 3; y++) {
+                res = 0;
+                for (z = 0; z < 3; z++) {
+                    res += matrix[x][z] * me.matrix[z][y];
+                }
+                out[x][y] = res;
+            }
+        }
+        me.matrix = out;
     },
 
-    storeLeftTop : function(left, top){
-        delete this.lastXY;
-        this.lastLT = [left, top];
+    invert: function() {
+        var matrix = this.matrix,
+            a = matrix[0][0],
+            b = matrix[1][0],
+            c = matrix[0][1],
+            d = matrix[1][1],
+            e = matrix[0][2],
+            f = matrix[1][2],
+            x = a * d - b * c;
+        return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
     },
 
-    
-    beforeFx : function(){
-        this.beforeAction();
-        return Ext.Layer.superclass.beforeFx.apply(this, arguments);
+    clone: function() {
+        var matrix = this.matrix,
+            a = matrix[0][0],
+            b = matrix[1][0],
+            c = matrix[0][1],
+            d = matrix[1][1],
+            e = matrix[0][2],
+            f = matrix[1][2];
+        return new Ext.draw.Matrix(a, b, c, d, e, f);
     },
 
-    
-    afterFx : function(){
-        Ext.Layer.superclass.afterFx.apply(this, arguments);
-        this.sync(this.isVisible());
+    translate: function(x, y) {
+        this.prepend(1, 0, 0, 1, x, y);
     },
 
-    
-    beforeAction : function(){
-        if(!this.updating && this.shadow){
-            this.shadow.hide();
+    scale: function(x, y, cx, cy) {
+        var me = this;
+        if (y == null) {
+            y = x;
         }
+        me.add(1, 0, 0, 1, cx, cy);
+        me.add(x, 0, 0, y, 0, 0);
+        me.add(1, 0, 0, 1, -cx, -cy);
     },
 
-    
-    setLeft : function(left){
-        this.storeLeftTop(left, this.getTop(true));
-        supr.setLeft.apply(this, arguments);
-        this.sync();
-        return this;
+    rotate: function(a, x, y) {
+        a = Ext.draw.Draw.rad(a);
+        var me = this,
+            cos = +Math.cos(a).toFixed(9),
+            sin = +Math.sin(a).toFixed(9);
+        me.add(cos, sin, -sin, cos, x, y);
+        me.add(1, 0, 0, 1, -x, -y);
     },
 
-    setTop : function(top){
-        this.storeLeftTop(this.getLeft(true), top);
-        supr.setTop.apply(this, arguments);
-        this.sync();
-        return this;
+    x: function(x, y) {
+        var matrix = this.matrix;
+        return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
     },
 
-    setLeftTop : function(left, top){
-        this.storeLeftTop(left, top);
-        supr.setLeftTop.apply(this, arguments);
-        this.sync();
-        return this;
+    y: function(x, y) {
+        var matrix = this.matrix;
+        return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
     },
 
-    setXY : function(xy, a, d, c, e){
-        this.fixDisplay();
-        this.beforeAction();
-        this.storeXY(xy);
-        var cb = this.createCB(c);
-        supr.setXY.call(this, xy, a, d, cb, e);
-        if(!a){
-            cb();
-        }
-        return this;
+    get: function(i, j) {
+        return + this.matrix[i][j].toFixed(4);
     },
 
-    
-    createCB : function(c){
-        var el = this;
-        return function(){
-            el.constrainXY();
-            el.sync(true);
-            if(c){
-                c();
-            }
-        };
+    toString: function() {
+        var me = this;
+        return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
     },
 
-    
-    setX : function(x, a, d, c, e){
-        this.setXY([x, this.getY()], a, d, c, e);
-        return this;
+    toSvg: function() {
+        var me = this;
+        return "matrix(" + [me.get(0, 0), me.get(1, 0), me.get(0, 1), me.get(1, 1), me.get(0, 2), me.get(1, 2)].join() + ")";
     },
 
-    
-    setY : function(y, a, d, c, e){
-        this.setXY([this.getX(), y], a, d, c, e);
-        return this;
+    toFilter: function() {
+        var me = this;
+        return "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand',FilterType=bilinear,M11=" + me.get(0, 0) +
+            ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
+            ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
     },
 
-    
-    setSize : function(w, h, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        supr.setSize.call(this, w, h, a, d, cb, e);
-        if(!a){
-            cb();
-        }
-        return this;
+    offset: function() {
+        var matrix = this.matrix;
+        return [(matrix[0][2] || 0).toFixed(4), (matrix[1][2] || 0).toFixed(4)];
     },
 
     
-    setWidth : function(w, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        supr.setWidth.call(this, w, a, d, cb, e);
-        if(!a){
-            cb();
+    split: function () {
+        function norm(a) {
+            return a[0] * a[0] + a[1] * a[1];
         }
-        return this;
-    },
-
-    
-    setHeight : function(h, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        supr.setHeight.call(this, h, a, d, cb, e);
-        if(!a){
-            cb();
+        function normalize(a) {
+            var mag = Math.sqrt(norm(a));
+            a[0] /= mag;
+            a[1] /= mag;
         }
-        return this;
-    },
+        var matrix = this.matrix,
+            out = {
+                translateX: matrix[0][2],
+                translateY: matrix[1][2]
+            },
+            row;
 
-    
-    setBounds : function(x, y, w, h, a, d, c, e){
-        this.beforeAction();
-        var cb = this.createCB(c);
-        if(!a){
-            this.storeXY([x, y]);
-            supr.setXY.call(this, [x, y]);
-            supr.setSize.call(this, w, h, a, d, cb, e);
-            cb();
-        }else{
-            supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
-        }
-        return this;
-    },
+        
+        row = [[matrix[0][0], matrix[0][1]], [matrix[1][0], matrix[1][1]]];
+        out.scaleX = Math.sqrt(norm(row[0]));
+        normalize(row[0]);
 
-    
-    setZIndex : function(zindex){
-        this.zindex = zindex;
-        this.setStyle('z-index', zindex + 2);
-        if(this.shadow){
-            this.shadow.setZIndex(zindex + 1);
-        }
-        if(this.shim){
-            this.shim.setStyle('z-index', zindex);
-        }
-        return this;
+        out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
+        row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
+
+        out.scaleY = Math.sqrt(norm(row[1]));
+        normalize(row[1]);
+        out.shear /= out.scaleY;
+
+        
+        out.rotate = Math.asin(-row[0][1]);
+
+        out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
+
+        return out;
     }
 });
-})();
 
-Ext.Shadow = function(config){
-    Ext.apply(this, config);
-    if(typeof this.mode != "string"){
-        this.mode = this.defaultMode;
-    }
-    var o = this.offset, a = {h: 0};
-    var rad = Math.floor(this.offset/2);
-    switch(this.mode.toLowerCase()){ 
-        case "drop":
-            a.w = 0;
-            a.l = a.t = o;
-            a.t -= 1;
-            if(Ext.isIE){
-                a.l -= this.offset + rad;
-                a.t -= this.offset + rad;
-                a.w -= rad;
-                a.h -= rad;
-                a.t += 1;
-            }
-        break;
-        case "sides":
-            a.w = (o*2);
-            a.l = -o;
-            a.t = o-1;
-            if(Ext.isIE){
-                a.l -= (this.offset - rad);
-                a.t -= this.offset + rad;
-                a.l += 1;
-                a.w -= (this.offset - rad)*2;
-                a.w -= rad + 1;
-                a.h -= 1;
-            }
-        break;
-        case "frame":
-            a.w = a.h = (o*2);
-            a.l = a.t = -o;
-            a.t += 1;
-            a.h -= 2;
-            if(Ext.isIE){
-                a.l -= (this.offset - rad);
-                a.t -= (this.offset - rad);
-                a.l += 1;
-                a.w -= (this.offset + rad + 1);
-                a.h -= (this.offset + rad);
-                a.h += 1;
-            }
-        break;
-    };
 
-    this.adjusts = a;
-};
+Ext.define('Ext.draw.SpriteDD', {
+    extend: 'Ext.dd.DragSource',
 
-Ext.Shadow.prototype = {
-    
-    
-    offset: 4,
+    constructor : function(sprite, cfg){
+        var me = this,
+            el = sprite.el;
+        me.sprite = sprite;
+        me.el = el;
+        me.dragData = {el: el, sprite: sprite};
+        me.callParent([el, cfg]);
+        me.sprite.setStyle('cursor', 'move');
+    },
 
-    
-    defaultMode: "drop",
+    showFrame: Ext.emptyFn,
+    createFrame : Ext.emptyFn,
 
+    getDragEl : function(e){
+        return this.el;
+    },
     
-    show : function(target){
-        target = Ext.get(target);
-        if(!this.el){
-            this.el = Ext.Shadow.Pool.pull();
-            if(this.el.dom.nextSibling != target.dom){
-                this.el.insertBefore(target);
-            }
-        }
-        this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
-        if(Ext.isIE){
-            this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
+    getRegion: function() {
+        var me = this,
+            el = me.el,
+            pos, x1, x2, y1, y2, t, r, b, l, bbox, sprite;
+        
+        sprite = me.sprite;
+        bbox = sprite.getBBox();
+        
+        try {
+            pos = Ext.Element.getXY(el);
+        } catch (e) { }
+
+        if (!pos) {
+            return null;
         }
-        this.realign(
-            target.getLeft(true),
-            target.getTop(true),
-            target.getWidth(),
-            target.getHeight()
-        );
-        this.el.dom.style.display = "block";
-    },
 
-    
-    isVisible : function(){
-        return this.el ? true : false;  
+        x1 = pos[0];
+        x2 = x1 + bbox.width;
+        y1 = pos[1];
+        y2 = y1 + bbox.height;
+        
+        return Ext.create('Ext.util.Region', y1, x2, y2, x1);
     },
 
     
-    realign : function(l, t, w, h){
-        if(!this.el){
-            return;
-        }
-        var a = this.adjusts, d = this.el.dom, s = d.style;
-        var iea = 0;
-        s.left = (l+a.l)+"px";
-        s.top = (t+a.t)+"px";
-        var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
-        if(s.width != sws || s.height != shs){
-            s.width = sws;
-            s.height = shs;
-            if(!Ext.isIE){
-                var cn = d.childNodes;
-                var sww = Math.max(0, (sw-12))+"px";
-                cn[0].childNodes[1].style.width = sww;
-                cn[1].childNodes[1].style.width = sww;
-                cn[2].childNodes[1].style.width = sww;
-                cn[1].style.height = Math.max(0, (sh-12))+"px";
-            }
-        }
+     
+    startDrag: function(x, y) {
+        var me = this,
+            attr = me.sprite.attr;
+        me.prev = me.sprite.surface.transformToViewBox(x, y);
     },
 
-    
-    hide : function(){
-        if(this.el){
-            this.el.dom.style.display = "none";
-            Ext.Shadow.Pool.push(this.el);
-            delete this.el;
-        }
+    onDrag: function(e) {
+        var xy = e.getXY(),
+            me = this,
+            sprite = me.sprite,
+            attr = sprite.attr, dx, dy;
+        xy = me.sprite.surface.transformToViewBox(xy[0], xy[1]);
+        dx = xy[0] - me.prev[0];
+        dy = xy[1] - me.prev[1];
+        sprite.setAttributes({
+            translate: {
+                x: attr.translation.x + dx,
+                y: attr.translation.y + dy
+            }
+        }, true);
+        me.prev = xy;
     },
 
-    
-    setZIndex : function(z){
-        this.zIndex = z;
-        if(this.el){
-            this.el.setStyle("z-index", z);
-        }
+    setDragElPos: function () {
+        
+        return false;
     }
-};
+});
 
+Ext.define('Ext.draw.Sprite', {
 
-Ext.Shadow.Pool = function(){
-    var p = [];
-    var markup = Ext.isIE ?
-                 '<div class="x-ie-shadow"></div>' :
-                 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
-    return {
-        pull : function(){
-            var sh = p.shift();
-            if(!sh){
-                sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
-                sh.autoBoxAdjust = false;
-            }
-            return sh;
-        },
+    
 
-        push : function(sh){
-            p.push(sh);
-        }
-    };
-}();
-Ext.BoxComponent = Ext.extend(Ext.Component, {
+    mixins: {
+        observable: 'Ext.util.Observable',
+        animate: 'Ext.util.Animate'
+    },
+
+    requires: ['Ext.draw.SpriteDD'],
 
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
+
     
-    
-    
-    
-    
-    
-    
-    
-    
+
     
 
     
 
     
-    initComponent : function(){
-        Ext.BoxComponent.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'resize',
-            
-            'move'
+
+    dirty: false,
+    dirtyHidden: false,
+    dirtyTransform: false,
+    dirtyPath: true,
+    dirtyFont: true,
+    zIndexDirty: true,
+    isSprite: true,
+    zIndex: 0,
+    fontProperties: [
+        'font',
+        'font-size',
+        'font-weight',
+        'font-style',
+        'font-family',
+        'text-anchor',
+        'text'
+    ],
+    pathProperties: [
+        'x',
+        'y',
+        'd',
+        'path',
+        'height',
+        'width',
+        'radius',
+        'r',
+        'rx',
+        'ry',
+        'cx',
+        'cy'
+    ],
+    constructor: function(config) {
+        var me = this;
+        config = config || {};
+        me.id = Ext.id(null, 'ext-sprite-');
+        me.transformations = [];
+        Ext.copyTo(this, config, 'surface,group,type,draggable');
+        
+        me.bbox = {};
+        me.attr = {
+            zIndex: 0,
+            translation: {
+                x: null,
+                y: null
+            },
+            rotation: {
+                degrees: null,
+                x: null,
+                y: null
+            },
+            scaling: {
+                x: null,
+                y: null,
+                cx: null,
+                cy: null
+            }
+        };
+        
+        delete config.surface;
+        delete config.group;
+        delete config.type;
+        delete config.draggable;
+        me.setAttributes(config);
+        me.addEvents(
+            'beforedestroy',
+            'destroy',
+            'render',
+            'mousedown',
+            'mouseup',
+            'mouseover',
+            'mouseout',
+            'mousemove',
+            'click'
         );
+        me.mixins.observable.constructor.apply(this, arguments);
     },
 
     
-    boxReady : false,
-    
-    deferHeight: false,
+
+    initDraggable: function() {
+        var me = this;
+        me.draggable = true;
+        
+        if (!me.el) {
+            me.surface.createSpriteElement(me);
+        }
+        me.dd = Ext.create('Ext.draw.SpriteDD', me, Ext.isBoolean(me.draggable) ? null : me.draggable);
+        me.on('beforedestroy', me.dd.destroy, me.dd);
+    },
 
     
-    setSize : function(w, h){
+    setAttributes: function(attrs, redraw) {
+        var me = this,
+            fontProps = me.fontProperties,
+            fontPropsLength = fontProps.length,
+            pathProps = me.pathProperties,
+            pathPropsLength = pathProps.length,
+            hasSurface = !!me.surface,
+            custom = hasSurface && me.surface.customAttributes || {},
+            spriteAttrs = me.attr,
+            attr, i, translate, translation, rotate, rotation, scale, scaling;
+
+        attrs = Ext.apply({}, attrs);
+        for (attr in custom) {
+            if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") {
+                Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr])));
+            }
+        }
 
         
-        if(typeof w == 'object'){
-            h = w.height;
-            w = w.width;
+        if (!!attrs.hidden !== !!spriteAttrs.hidden) {
+            me.dirtyHidden = true;
         }
-        if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
-            w = this.boxMinWidth;
+
+        
+        for (i = 0; i < pathPropsLength; i++) {
+            attr = pathProps[i];
+            if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
+                me.dirtyPath = true;
+                break;
+            }
         }
-        if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
-            h = this.boxMinHeight;
+
+        
+        if ('zIndex' in attrs) {
+            me.zIndexDirty = true;
         }
-        if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
-            w = this.boxMaxWidth;
+
+        
+        for (i = 0; i < fontPropsLength; i++) {
+            attr = fontProps[i];
+            if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
+                me.dirtyFont = true;
+                break;
+            }
         }
-        if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
-            h = this.boxMaxHeight;
+
+        translate = attrs.translate;
+        translation = spriteAttrs.translation;
+        if (translate) {
+            if ((translate.x && translate.x !== translation.x) ||
+                (translate.y && translate.y !== translation.y)) {
+                Ext.apply(translation, translate);
+                me.dirtyTransform = true;
+            }
+            delete attrs.translate;
         }
-        
-        if(!this.boxReady){
-            this.width  = w;
-            this.height = h;
-            return this;
+
+        rotate = attrs.rotate;
+        rotation = spriteAttrs.rotation;
+        if (rotate) {
+            if ((rotate.x && rotate.x !== rotation.x) ||
+                (rotate.y && rotate.y !== rotation.y) ||
+                (rotate.degrees && rotate.degrees !== rotation.degrees)) {
+                Ext.apply(rotation, rotate);
+                me.dirtyTransform = true;
+            }
+            delete attrs.rotate;
         }
 
-        
-        if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
-            return this;
+        scale = attrs.scale;
+        scaling = spriteAttrs.scaling;
+        if (scale) {
+            if ((scale.x && scale.x !== scaling.x) ||
+                (scale.y && scale.y !== scaling.y) ||
+                (scale.cx && scale.cx !== scaling.cx) ||
+                (scale.cy && scale.cy !== scaling.cy)) {
+                Ext.apply(scaling, scale);
+                me.dirtyTransform = true;
+            }
+            delete attrs.scale;
         }
-        this.lastSize = {width: w, height: h};
-        var adj = this.adjustSize(w, h),
-            aw = adj.width,
-            ah = adj.height,
-            rz;
-        if(aw !== undefined || ah !== undefined){ 
-            rz = this.getResizeEl();
-            if(!this.deferHeight && aw !== undefined && ah !== undefined){
-                rz.setSize(aw, ah);
-            }else if(!this.deferHeight && ah !== undefined){
-                rz.setHeight(ah);
-            }else if(aw !== undefined){
-                rz.setWidth(aw);
-            }
-            this.onResize(aw, ah, w, h);
-            this.fireEvent('resize', this, aw, ah, w, h);
+
+        Ext.apply(spriteAttrs, attrs);
+        me.dirty = true;
+
+        if (redraw === true && hasSurface) {
+            me.redraw();
         }
         return this;
     },
 
     
-    setWidth : function(width){
-        return this.setSize(width);
+    getBBox: function() {
+        return this.surface.getBBox(this);
     },
 
-    
-    setHeight : function(height){
-        return this.setSize(undefined, height);
+    setText: function(text) {
+        return this.surface.setText(this, text);
     },
 
     
-    getSize : function(){
-        return this.getResizeEl().getSize();
+    hide: function(redraw) {
+        this.setAttributes({
+            hidden: true
+        }, redraw);
+        return this;
     },
 
     
-    getWidth : function(){
-        return this.getResizeEl().getWidth();
+    show: function(redraw) {
+        this.setAttributes({
+            hidden: false
+        }, redraw);
+        return this;
     },
 
     
-    getHeight : function(){
-        return this.getResizeEl().getHeight();
+    remove: function() {
+        if (this.surface) {
+            this.surface.remove(this);
+            return true;
+        }
+        return false;
     },
 
-    
-    getOuterSize : function(){
-        var el = this.getResizeEl();
-        return {width: el.getWidth() + el.getMargins('lr'),
-                height: el.getHeight() + el.getMargins('tb')};
+    onRemove: function() {
+        this.surface.onRemove(this);
     },
 
     
-    getPosition : function(local){
-        var el = this.getPositionEl();
-        if(local === true){
-            return [el.getLeft(true), el.getTop(true)];
+    destroy: function() {
+        var me = this;
+        if (me.fireEvent('beforedestroy', me) !== false) {
+            me.remove();
+            me.surface.onDestroy(me);
+            me.clearListeners();
+            me.fireEvent('destroy');
         }
-        return this.xy || el.getXY();
     },
 
     
-    getBox : function(local){
-        var pos = this.getPosition(local);
-        var s = this.getSize();
-        s.x = pos[0];
-        s.y = pos[1];
-        return s;
+    redraw: function() {
+        this.surface.renderItem(this);
+        return this;
     },
 
     
-    updateBox : function(box){
-        this.setSize(box.width, box.height);
-        this.setPagePosition(box.x, box.y);
+    setStyle: function() {
+        this.el.setStyle.apply(this.el, arguments);
         return this;
     },
 
     
-    getResizeEl : function(){
-        return this.resizeEl || this.el;
+    addCls: function(obj) {
+        this.surface.addCls(this, obj);
+        return this;
     },
 
     
-    setAutoScroll : function(scroll){
-        if(this.rendered){
-            this.getContentTarget().setOverflow(scroll ? 'auto' : '');
-        }
-        this.autoScroll = scroll;
+    removeCls: function(obj) {
+        this.surface.removeCls(this, obj);
         return this;
-    },
+    }
+});
 
-    
-    setPosition : function(x, y){
-        if(x && typeof x[1] == 'number'){
-            y = x[1];
-            x = x[0];
-        }
-        this.x = x;
-        this.y = y;
-        if(!this.boxReady){
-            return this;
-        }
-        var adj = this.adjustPosition(x, y);
-        var ax = adj.x, ay = adj.y;
 
-        var el = this.getPositionEl();
-        if(ax !== undefined || ay !== undefined){
-            if(ax !== undefined && ay !== undefined){
-                el.setLeftTop(ax, ay);
-            }else if(ax !== undefined){
-                el.setLeft(ax);
-            }else if(ay !== undefined){
-                el.setTop(ay);
-            }
-            this.onPosition(ax, ay);
-            this.fireEvent('move', this, ax, ay);
-        }
-        return this;
-    },
+Ext.define('Ext.draw.engine.Svg', {
 
     
-    setPagePosition : function(x, y){
-        if(x && typeof x[1] == 'number'){
-            y = x[1];
-            x = x[0];
-        }
-        this.pageX = x;
-        this.pageY = y;
-        if(!this.boxReady){
-            return;
-        }
-        if(x === undefined || y === undefined){ 
-            return;
-        }
-        var p = this.getPositionEl().translatePoints(x, y);
-        this.setPosition(p.left, p.top);
-        return this;
-    },
 
-    
-    afterRender : function(){
-        Ext.BoxComponent.superclass.afterRender.call(this);
-        if(this.resizeEl){
-            this.resizeEl = Ext.get(this.resizeEl);
-        }
-        if(this.positionEl){
-            this.positionEl = Ext.get(this.positionEl);
-        }
-        this.boxReady = true;
-        Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
-        this.setSize(this.width, this.height);
-        if(this.x || this.y){
-            this.setPosition(this.x, this.y);
-        }else if(this.pageX || this.pageY){
-            this.setPagePosition(this.pageX, this.pageY);
-        }
-    },
+    extend: 'Ext.draw.Surface',
 
-    
-    syncSize : function(){
-        delete this.lastSize;
-        this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
-        return this;
-    },
+    requires: ['Ext.draw.Draw', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
 
     
-    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
-    },
 
+    engine: 'Svg',
+
+    trimRe: /^\s+|\s+$/g,
+    spacesRe: /\s+/,
+    xlink: "http:/" + "/www.w3.org/1999/xlink",
+
+    translateAttrs: {
+        radius: "r",
+        radiusX: "rx",
+        radiusY: "ry",
+        path: "d",
+        lineWidth: "stroke-width",
+        fillOpacity: "fill-opacity",
+        strokeOpacity: "stroke-opacity",
+        strokeLinejoin: "stroke-linejoin"
+    },
     
-    onPosition : function(x, y){
+    parsers: {},
 
+    minDefaults: {
+        circle: {
+            cx: 0,
+            cy: 0,
+            r: 0,
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        ellipse: {
+            cx: 0,
+            cy: 0,
+            rx: 0,
+            ry: 0,
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        rect: {
+            x: 0,
+            y: 0,
+            width: 0,
+            height: 0,
+            rx: 0,
+            ry: 0,
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        text: {
+            x: 0,
+            y: 0,
+            "text-anchor": "start",
+            "font-family": null,
+            "font-size": null,
+            "font-weight": null,
+            "font-style": null,
+            fill: "#000",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        path: {
+            d: "M0,0",
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        image: {
+            x: 0,
+            y: 0,
+            width: 0,
+            height: 0,
+            preserveAspectRatio: "none",
+            opacity: null
+        }
     },
 
-    
-    adjustSize : function(w, h){
-        if(this.autoWidth){
-            w = 'auto';
+    createSvgElement: function(type, attrs) {
+        var el = this.domRef.createElementNS("http:/" + "/www.w3.org/2000/svg", type),
+            key;
+        if (attrs) {
+            for (key in attrs) {
+                el.setAttribute(key, String(attrs[key]));
+            }
         }
-        if(this.autoHeight){
-            h = 'auto';
+        return el;
+    },
+
+    createSpriteElement: function(sprite) {
+        
+        var el = this.createSvgElement(sprite.type);
+        el.id = sprite.id;
+        if (el.style) {
+            el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
         }
-        return {width : w, height: h};
+        sprite.el = Ext.get(el);
+        this.applyZIndex(sprite); 
+        sprite.matrix = Ext.create('Ext.draw.Matrix');
+        sprite.bbox = {
+            plain: 0,
+            transform: 0
+        };
+        sprite.fireEvent("render", sprite);
+        return el;
     },
 
+    getBBox: function (sprite, isWithoutTransform) {
+        var realPath = this["getPath" + sprite.type](sprite);
+        if (isWithoutTransform) {
+            sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
+            return sprite.bbox.plain;
+        }
+        sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
+        return sprite.bbox.transform;
+    },
     
-    adjustPosition : function(x, y){
-        return {x : x, y: y};
-    }
-});
-Ext.reg('box', Ext.BoxComponent);
-
-
-
-Ext.Spacer = Ext.extend(Ext.BoxComponent, {
-    autoEl:'div'
-});
-Ext.reg('spacer', Ext.Spacer);
-Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
+    getBBoxText: function (sprite) {
+        var bbox = {},
+            bb, height, width, i, ln, el;
 
-    
-    this.el = Ext.get(dragElement, true);
-    this.el.dom.unselectable = "on";
-    
-    this.resizingEl = Ext.get(resizingElement, true);
+        if (sprite && sprite.el) {
+            el = sprite.el.dom;
+            try {
+                bbox = el.getBBox();
+                return bbox;
+            } catch(e) {
+                
+            }
+            bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};
+            ln = el.getNumberOfChars();
+            for (i = 0; i < ln; i++) {
+                bb = el.getExtentOfChar(i);
+                bbox.y = Math.min(bb.y, bbox.y);
+                height = bb.y + bb.height - bbox.y;
+                bbox.height = Math.max(bbox.height, height);
+                width = bb.x + bb.width - bbox.x;
+                bbox.width = Math.max(bbox.width, width);
+            }
+            return bbox;
+        }
+    },
 
-    
-    this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
+    hide: function() {
+        Ext.get(this.el).hide();
+    },
 
-    
-    
-    this.minSize = 0;
+    show: function() {
+        Ext.get(this.el).show();
+    },
 
-    
-    this.maxSize = 2000;
+    hidePrim: function(sprite) {
+        this.addCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
+    },
 
-    
-    this.animate = false;
+    showPrim: function(sprite) {
+        this.removeCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
+    },
 
-    
-    this.useShim = false;
+    getDefs: function() {
+        return this._defs || (this._defs = this.createSvgElement("defs"));
+    },
 
-    
-    this.shim = null;
+    transform: function(sprite) {
+        var me = this,
+            matrix = Ext.create('Ext.draw.Matrix'),
+            transforms = sprite.transformations,
+            transformsLength = transforms.length,
+            i = 0,
+            transform, type;
+            
+        for (; i < transformsLength; i++) {
+            transform = transforms[i];
+            type = transform.type;
+            if (type == "translate") {
+                matrix.translate(transform.x, transform.y);
+            }
+            else if (type == "rotate") {
+                matrix.rotate(transform.degrees, transform.x, transform.y);
+            }
+            else if (type == "scale") {
+                matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
+            }
+        }
+        sprite.matrix = matrix;
+        sprite.el.set({transform: matrix.toSvg()});
+    },
 
-    if(!existingProxy){
+    setSize: function(w, h) {
+        var me = this,
+            el = me.el;
         
-        this.proxy = Ext.SplitBar.createProxy(this.orientation);
-    }else{
-        this.proxy = Ext.get(existingProxy).dom;
-    }
-    
-    this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
+        w = +w || me.width;
+        h = +h || me.height;
+        me.width = w;
+        me.height = h;
 
-    
-    this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
-
-    
-    this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
-
-    
-    this.dragSpecs = {};
+        el.setSize(w, h);
+        el.set({
+            width: w,
+            height: h
+        });
+        me.callParent([w, h]);
+    },
 
     
-    this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
-    this.adapter.init(this);
-
-    if(this.orientation == Ext.SplitBar.HORIZONTAL){
-        
-        this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
-        this.el.addClass("x-splitbar-h");
-    }else{
-        
-        this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
-        this.el.addClass("x-splitbar-v");
-    }
-
-    this.addEvents(
-        
-        "resize",
+    getRegion: function() {
         
-        "moved",
         
-        "beforeresize",
+        var svgXY = this.el.getXY(),
+            rectXY = this.bgRect.getXY(),
+            max = Math.max,
+            x = max(svgXY[0], rectXY[0]),
+            y = max(svgXY[1], rectXY[1]);
+        return {
+            left: x,
+            top: y,
+            right: x + this.width,
+            bottom: y + this.height
+        };
+    },
 
-        "beforeapply"
-    );
+    onRemove: function(sprite) {
+        if (sprite.el) {
+            sprite.el.remove();
+            delete sprite.el;
+        }
+        this.callParent(arguments);
+    },
+    
+    setViewBox: function(x, y, width, height) {
+        if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
+            this.callParent(arguments);
+            this.el.dom.setAttribute("viewBox", [x, y, width, height].join(" "));
+        }
+    },
 
-    Ext.SplitBar.superclass.constructor.call(this);
-};
+    render: function (container) {
+        var me = this;
+        if (!me.el) {
+            var width = me.width || 10,
+                height = me.height || 10,
+                el = me.createSvgElement('svg', {
+                    xmlns: "http:/" + "/www.w3.org/2000/svg",
+                    version: 1.1,
+                    width: width,
+                    height: height
+                }),
+                defs = me.getDefs(),
 
-Ext.extend(Ext.SplitBar, Ext.util.Observable, {
-    onStartProxyDrag : function(x, y){
-        this.fireEvent("beforeresize", this);
-        this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
-        this.overlay.unselectable();
-        this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
-        this.overlay.show();
-        Ext.get(this.proxy).setDisplayed("block");
-        var size = this.adapter.getElementSize(this);
-        this.activeMinSize = this.getMinimumSize();
-        this.activeMaxSize = this.getMaximumSize();
-        var c1 = size - this.activeMinSize;
-        var c2 = Math.max(this.activeMaxSize - size, 0);
-        if(this.orientation == Ext.SplitBar.HORIZONTAL){
-            this.dd.resetConstraints();
-            this.dd.setXConstraint(
-                this.placement == Ext.SplitBar.LEFT ? c1 : c2,
-                this.placement == Ext.SplitBar.LEFT ? c2 : c1,
-                this.tickSize
-            );
-            this.dd.setYConstraint(0, 0);
-        }else{
-            this.dd.resetConstraints();
-            this.dd.setXConstraint(0, 0);
-            this.dd.setYConstraint(
-                this.placement == Ext.SplitBar.TOP ? c1 : c2,
-                this.placement == Ext.SplitBar.TOP ? c2 : c1,
-                this.tickSize
-            );
-         }
-        this.dragSpecs.startSize = size;
-        this.dragSpecs.startPoint = [x, y];
-        Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
+                
+                
+                
+                
+                bgRect = me.createSvgElement("rect", {
+                    width: "100%",
+                    height: "100%",
+                    fill: "#000",
+                    stroke: "none",
+                    opacity: 0
+                }),
+                webkitRect;
+            
+                if (Ext.isSafari3) {
+                    
+                    webkitRect = me.createSvgElement("rect", {
+                        x: -10,
+                        y: -10,
+                        width: "110%",
+                        height: "110%",
+                        fill: "none",
+                        stroke: "#000"
+                    });
+                }
+            el.appendChild(defs);
+            if (Ext.isSafari3) {
+                el.appendChild(webkitRect);
+            }
+            el.appendChild(bgRect);
+            container.appendChild(el);
+            me.el = Ext.get(el);
+            me.bgRect = Ext.get(bgRect);
+            if (Ext.isSafari3) {
+                me.webkitRect = Ext.get(webkitRect);
+                me.webkitRect.hide();
+            }
+            me.el.on({
+                scope: me,
+                mouseup: me.onMouseUp,
+                mousedown: me.onMouseDown,
+                mouseover: me.onMouseOver,
+                mouseout: me.onMouseOut,
+                mousemove: me.onMouseMove,
+                mouseenter: me.onMouseEnter,
+                mouseleave: me.onMouseLeave,
+                click: me.onClick
+            });
+        }
+        me.renderAll();
     },
 
     
-    onEndProxyDrag : function(e){
-        Ext.get(this.proxy).setDisplayed(false);
-        var endPoint = Ext.lib.Event.getXY(e);
-        if(this.overlay){
-            Ext.destroy(this.overlay);
-            delete this.overlay;
-        }
-        var newSize;
-        if(this.orientation == Ext.SplitBar.HORIZONTAL){
-            newSize = this.dragSpecs.startSize +
-                (this.placement == Ext.SplitBar.LEFT ?
-                    endPoint[0] - this.dragSpecs.startPoint[0] :
-                    this.dragSpecs.startPoint[0] - endPoint[0]
-                );
-        }else{
-            newSize = this.dragSpecs.startSize +
-                (this.placement == Ext.SplitBar.TOP ?
-                    endPoint[1] - this.dragSpecs.startPoint[1] :
-                    this.dragSpecs.startPoint[1] - endPoint[1]
-                );
-        }
-        newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
-        if(newSize != this.dragSpecs.startSize){
-            if(this.fireEvent('beforeapply', this, newSize) !== false){
-                this.adapter.setElementSize(this, newSize);
-                this.fireEvent("moved", this, newSize);
-                this.fireEvent("resize", this, newSize);
-            }
+    onMouseEnter: function(e) {
+        if (this.el.parent().getRegion().contains(e.getPoint())) {
+            this.fireEvent('mouseenter', e);
         }
     },
 
     
-    getAdapter : function(){
-        return this.adapter;
+    onMouseLeave: function(e) {
+        if (!this.el.parent().getRegion().contains(e.getPoint())) {
+            this.fireEvent('mouseleave', e);
+        }
     },
-
     
-    setAdapter : function(adapter){
-        this.adapter = adapter;
-        this.adapter.init(this);
+    processEvent: function(name, e) {
+        var target = e.getTarget(),
+            surface = this.surface,
+            sprite;
+
+        this.fireEvent(name, e);
+        
+        if (target.nodeName == "tspan" && target.parentNode) {
+            target = target.parentNode;
+        }
+        sprite = this.items.get(target.id);
+        if (sprite) {
+            sprite.fireEvent(name, sprite, e);
+        }
     },
 
     
-    getMinimumSize : function(){
-        return this.minSize;
+    tuneText: function (sprite, attrs) {
+        var el = sprite.el.dom,
+            tspans = [],
+            height, tspan, text, i, ln, texts, factor;
+
+        if (attrs.hasOwnProperty("text")) {
+           tspans = this.setText(sprite, attrs.text);
+        }
+        
+        if (tspans.length) {
+            height = this.getBBoxText(sprite).height;
+            for (i = 0, ln = tspans.length; i < ln; i++) {
+                
+                
+                factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4;
+                tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor);
+            }
+            sprite.dirty = true;
+        }
     },
 
-    
-    setMinimumSize : function(minSize){
-        this.minSize = minSize;
+    setText: function(sprite, textString) {
+         var me = this,
+             el = sprite.el.dom,
+             x = el.getAttribute("x"),
+             tspans = [],
+             height, tspan, text, i, ln, texts;
+        
+        while (el.firstChild) {
+            el.removeChild(el.firstChild);
+        }
+        
+        texts = String(textString).split("\n");
+        for (i = 0, ln = texts.length; i < ln; i++) {
+            text = texts[i];
+            if (text) {
+                tspan = me.createSvgElement("tspan");
+                tspan.appendChild(document.createTextNode(Ext.htmlDecode(text)));
+                tspan.setAttribute("x", x);
+                el.appendChild(tspan);
+                tspans[i] = tspan;
+            }
+        }
+        return tspans;
     },
 
-    
-    getMaximumSize : function(){
-        return this.maxSize;
+    renderAll: function() {
+        this.items.each(this.renderItem, this);
     },
 
-    
-    setMaximumSize : function(maxSize){
-        this.maxSize = maxSize;
+    renderItem: function (sprite) {
+        if (!this.el) {
+            return;
+        }
+        if (!sprite.el) {
+            this.createSpriteElement(sprite);
+        }
+        if (sprite.zIndexDirty) {
+            this.applyZIndex(sprite);
+        }
+        if (sprite.dirty) {
+            this.applyAttrs(sprite);
+            this.applyTransformations(sprite);
+        }
     },
 
-    
-    setCurrentSize : function(size){
-        var oldAnimate = this.animate;
-        this.animate = false;
-        this.adapter.setElementSize(this, size);
-        this.animate = oldAnimate;
+    redraw: function(sprite) {
+        sprite.dirty = sprite.zIndexDirty = true;
+        this.renderItem(sprite);
     },
 
-    
-    destroy : function(removeEl){
-        Ext.destroy(this.shim, Ext.get(this.proxy));
-        this.dd.unreg();
-        if(removeEl){
-            this.el.remove();
+    applyAttrs: function (sprite) {
+        var me = this,
+            el = sprite.el,
+            group = sprite.group,
+            sattr = sprite.attr,
+            parsers = me.parsers,
+            
+            
+            
+            gradientsMap = me.gradientsMap || {},
+            safariFix = Ext.isSafari && !Ext.isStrict,
+            groups, i, ln, attrs, font, key, style, name, rect;
+
+        if (group) {
+            groups = [].concat(group);
+            ln = groups.length;
+            for (i = 0; i < ln; i++) {
+                group = groups[i];
+                me.getGroup(group).add(sprite);
+            }
+            delete sprite.group;
         }
-        this.purgeListeners();
-    }
-});
+        attrs = me.scrubAttrs(sprite) || {};
 
+        
+            sprite.bbox.plain = 0;
+            sprite.bbox.transform = 0;
+            if (sprite.type == "circle" || sprite.type == "ellipse") {
+                attrs.cx = attrs.cx || attrs.x;
+                attrs.cy = attrs.cy || attrs.y;
+            }
+            else if (sprite.type == "rect") {
+                attrs.rx = attrs.ry = attrs.r;
+            }
+            else if (sprite.type == "path" && attrs.d) {
+                attrs.d = Ext.draw.Draw.pathToString(Ext.draw.Draw.pathToAbsolute(attrs.d));
+            }
+            sprite.dirtyPath = false;
+        
+        
+        
+        
 
-Ext.SplitBar.createProxy = function(dir){
-    var proxy = new Ext.Element(document.createElement("div"));
-    document.body.appendChild(proxy.dom);
-    proxy.unselectable();
-    var cls = 'x-splitbar-proxy';
-    proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
-    return proxy.dom;
-};
+        if (attrs['clip-rect']) {
+            me.setClip(sprite, attrs);
+            delete attrs['clip-rect'];
+        }
+        if (sprite.type == 'text' && attrs.font && sprite.dirtyFont) {
+            el.set({ style: "font: " + attrs.font});
+            sprite.dirtyFont = false;
+        }
+        if (sprite.type == "image") {
+            el.dom.setAttributeNS(me.xlink, "href", attrs.src);
+        }
+        Ext.applyIf(attrs, me.minDefaults[sprite.type]);
 
+        if (sprite.dirtyHidden) {
+            (sattr.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
+            sprite.dirtyHidden = false;
+        }
+        for (key in attrs) {
+            if (attrs.hasOwnProperty(key) && attrs[key] != null) {
+                
+                
+                
+                
+                
+                if (safariFix && ('color|stroke|fill'.indexOf(key) > -1) && (attrs[key] in gradientsMap)) {
+                    attrs[key] = gradientsMap[attrs[key]];
+                }
+                if (key in parsers) {
+                    el.dom.setAttribute(key, parsers[key](attrs[key], sprite, me));
+                } else {
+                    el.dom.setAttribute(key, attrs[key]);
+                }
+            }
+        }
+        
+        if (sprite.type == 'text') {
+            me.tuneText(sprite, attrs);
+        }
 
-Ext.SplitBar.BasicLayoutAdapter = function(){
-};
+        
+        style = sattr.style;
+        if (style) {
+            el.setStyle(style);
+        }
 
-Ext.SplitBar.BasicLayoutAdapter.prototype = {
-    
-    init : function(s){
+        sprite.dirty = false;
 
+        if (Ext.isSafari3) {
+            
+            me.webkitRect.show();
+            setTimeout(function () {
+                me.webkitRect.hide();
+            });
+        }
     },
-    
-     getElementSize : function(s){
-        if(s.orientation == Ext.SplitBar.HORIZONTAL){
-            return s.resizingEl.getWidth();
-        }else{
-            return s.resizingEl.getHeight();
+
+    setClip: function(sprite, params) {
+        var me = this,
+            rect = params["clip-rect"],
+            clipEl, clipPath;
+        if (rect) {
+            if (sprite.clip) {
+                sprite.clip.parentNode.parentNode.removeChild(sprite.clip.parentNode);
+            }
+            clipEl = me.createSvgElement('clipPath');
+            clipPath = me.createSvgElement('rect');
+            clipEl.id = Ext.id(null, 'ext-clip-');
+            clipPath.setAttribute("x", rect.x);
+            clipPath.setAttribute("y", rect.y);
+            clipPath.setAttribute("width", rect.width);
+            clipPath.setAttribute("height", rect.height);
+            clipEl.appendChild(clipPath);
+            me.getDefs().appendChild(clipEl);
+            sprite.el.dom.setAttribute("clip-path", "url(#" + clipEl.id + ")");
+            sprite.clip = clipPath;
         }
+        
+        
+        
+        
+        
+        
     },
 
     
-    setElementSize : function(s, newSize, onComplete){
-        if(s.orientation == Ext.SplitBar.HORIZONTAL){
-            if(!s.animate){
-                s.resizingEl.setWidth(newSize);
-                if(onComplete){
-                    onComplete(s, newSize);
-                }
-            }else{
-                s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
+    applyZIndex: function(sprite) {
+        var me = this,
+            items = me.items,
+            idx = items.indexOf(sprite),
+            el = sprite.el,
+            prevEl;
+        if (me.el.dom.childNodes[idx + 2] !== el.dom) { 
+            if (idx > 0) {
+                
+                do {
+                    prevEl = items.getAt(--idx).el;
+                } while (!prevEl && idx > 0);
             }
-        }else{
+            el.insertAfter(prevEl || me.bgRect);
+        }
+        sprite.zIndexDirty = false;
+    },
+
+    createItem: function (config) {
+        var sprite = Ext.create('Ext.draw.Sprite', config);
+        sprite.surface = this;
+        return sprite;
+    },
 
-            if(!s.animate){
-                s.resizingEl.setHeight(newSize);
-                if(onComplete){
-                    onComplete(s, newSize);
+    addGradient: function(gradient) {
+        gradient = Ext.draw.Draw.parseGradient(gradient);
+        var me = this,
+            ln = gradient.stops.length,
+            vector = gradient.vector,
+            
+            
+            
+            usePlain = Ext.isSafari && !Ext.isStrict,
+            gradientEl, stop, stopEl, i, gradientsMap;
+            
+        gradientsMap = me.gradientsMap || {};
+        
+        if (!usePlain) {
+            if (gradient.type == "linear") {
+                gradientEl = me.createSvgElement("linearGradient");
+                gradientEl.setAttribute("x1", vector[0]);
+                gradientEl.setAttribute("y1", vector[1]);
+                gradientEl.setAttribute("x2", vector[2]);
+                gradientEl.setAttribute("y2", vector[3]);
+            }
+            else {
+                gradientEl = me.createSvgElement("radialGradient");
+                gradientEl.setAttribute("cx", gradient.centerX);
+                gradientEl.setAttribute("cy", gradient.centerY);
+                gradientEl.setAttribute("r", gradient.radius);
+                if (Ext.isNumber(gradient.focalX) && Ext.isNumber(gradient.focalY)) {
+                    gradientEl.setAttribute("fx", gradient.focalX);
+                    gradientEl.setAttribute("fy", gradient.focalY);
                 }
-            }else{
-                s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
             }
+            gradientEl.id = gradient.id;
+            me.getDefs().appendChild(gradientEl);
+            for (i = 0; i < ln; i++) {
+                stop = gradient.stops[i];
+                stopEl = me.createSvgElement("stop");
+                stopEl.setAttribute("offset", stop.offset + "%");
+                stopEl.setAttribute("stop-color", stop.color);
+                stopEl.setAttribute("stop-opacity",stop.opacity);
+                gradientEl.appendChild(stopEl);
+            }
+        } else {
+            gradientsMap['url(#' + gradient.id + ')'] = gradient.stops[0].color;
         }
-    }
-};
-
-
-Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
-    this.basic = new Ext.SplitBar.BasicLayoutAdapter();
-    this.container = Ext.get(container);
-};
+        me.gradientsMap = gradientsMap;
+    },
 
-Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
-    init : function(s){
-        this.basic.init(s);
+    
+    hasCls: function(sprite, className) {
+        return className && (' ' + (sprite.el.dom.getAttribute('class') || '') + ' ').indexOf(' ' + className + ' ') != -1;
     },
 
-    getElementSize : function(s){
-        return this.basic.getElementSize(s);
+    addCls: function(sprite, className) {
+        var el = sprite.el,
+            i,
+            len,
+            v,
+            cls = [],
+            curCls =  el.getAttribute('class') || '';
+        
+        if (!Ext.isArray(className)) {
+            if (typeof className == 'string' && !this.hasCls(sprite, className)) {
+                el.set({ 'class': curCls + ' ' + className });
+            }
+        }
+        else {
+            for (i = 0, len = className.length; i < len; i++) {
+                v = className[i];
+                if (typeof v == 'string' && (' ' + curCls + ' ').indexOf(' ' + v + ' ') == -1) {
+                    cls.push(v);
+                }
+            }
+            if (cls.length) {
+                el.set({ 'class': ' ' + cls.join(' ') });
+            }
+        }
     },
 
-    setElementSize : function(s, newSize, onComplete){
-        this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
+    removeCls: function(sprite, className) {
+        var me = this,
+            el = sprite.el,
+            curCls =  el.getAttribute('class') || '',
+            i, idx, len, cls, elClasses;
+        if (!Ext.isArray(className)){
+            className = [className];
+        }
+        if (curCls) {
+            elClasses = curCls.replace(me.trimRe, ' ').split(me.spacesRe);
+            for (i = 0, len = className.length; i < len; i++) {
+                cls = className[i];
+                if (typeof cls == 'string') {
+                    cls = cls.replace(me.trimRe, '');
+                    idx = Ext.Array.indexOf(elClasses, cls);
+                    if (idx != -1) {
+                        Ext.Array.erase(elClasses, idx, 1);
+                    }
+                }
+            }
+            el.set({ 'class': elClasses.join(' ') });
+        }
     },
 
-    moveSplitter : function(s){
-        var yes = Ext.SplitBar;
-        switch(s.placement){
-            case yes.LEFT:
-                s.el.setX(s.resizingEl.getRight());
-                break;
-            case yes.RIGHT:
-                s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
-                break;
-            case yes.TOP:
-                s.el.setY(s.resizingEl.getBottom());
-                break;
-            case yes.BOTTOM:
-                s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
-                break;
+    destroy: function() {
+        var me = this;
+        
+        me.callParent();
+        if (me.el) {
+            me.el.remove();
         }
+        delete me.el;
     }
-};
-
-
-Ext.SplitBar.VERTICAL = 1;
-
+});
 
-Ext.SplitBar.HORIZONTAL = 2;
 
+Ext.define('Ext.draw.engine.Vml', {
 
-Ext.SplitBar.LEFT = 1;
+    
 
+    extend: 'Ext.draw.Surface',
 
-Ext.SplitBar.RIGHT = 2;
+    requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
 
+    
 
-Ext.SplitBar.TOP = 3;
+    engine: 'Vml',
 
+    map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
+    bitesRe: /([clmz]),?([^clmz]*)/gi,
+    valRe: /-?[^,\s-]+/g,
+    fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i,
+    pathlike: /^(path|rect)$/,
+    NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops
+    partialPathRe: /[clmz]/g,
+    fontFamilyRe: /^['"]+|['"]+$/g,
+    baseVmlCls: Ext.baseCSSPrefix + 'vml-base',
+    vmlGroupCls: Ext.baseCSSPrefix + 'vml-group',
+    spriteCls: Ext.baseCSSPrefix + 'vml-sprite',
+    measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span',
+    zoom: 21600,
+    coordsize: 1000,
+    coordorigin: '0 0',
 
-Ext.SplitBar.BOTTOM = 4;
+    // VML uses CSS z-index and therefore doesn't need sprites to be kept in zIndex order
+    orderSpritesByZIndex: false,
 
-Ext.Container = Ext.extend(Ext.BoxComponent, {
-    
     
     
-    
-    bufferResize: 50,
+    path2vml: function (path) {
+        var me = this,
+            nonVML =  me.NonVmlPathRe,
+            map = me.map,
+            val = me.valRe,
+            zoom = me.zoom,
+            bites = me.bitesRe,
+            command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw),
+            res, pa, p, r, i, ii, j, jj;
+        if (String(path).match(nonVML)) {
+            command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw);
+        } else if (!String(path).match(me.partialPathRe)) {
+            res = String(path).replace(bites, function (all, command, args) {
+                var vals = [],
+                    isMove = command.toLowerCase() == "m",
+                    res = map[command];
+                args.replace(val, function (value) {
+                    if (isMove && vals[length] == 2) {
+                        res += vals + map[command == "m" ? "l" : "L"];
+                        vals = [];
+                    }
+                    vals.push(Math.round(value * zoom));
+                });
+                return res + vals;
+            });
+            return res;
+        }
+        pa = command(path);
+        res = [];
+        for (i = 0, ii = pa.length; i < ii; i++) {
+            p = pa[i];
+            r = pa[i][0].toLowerCase();
+            if (r == "z") {
+                r = "x";
+            }
+            for (j = 1, jj = p.length; j < jj; j++) {
+                r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : "");
+            }
+            res.push(r);
+        }
+        return res.join(" ");
+    },
 
     
-    
-    
-
+    translateAttrs: {
+        radius: "r",
+        radiusX: "rx",
+        radiusY: "ry",
+        lineWidth: "stroke-width",
+        fillOpacity: "fill-opacity",
+        strokeOpacity: "stroke-opacity",
+        strokeLinejoin: "stroke-linejoin"
+    },
 
     
-    autoDestroy : true,
+    minDefaults: {
+        circle: {
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        ellipse: {
+            cx: 0,
+            cy: 0,
+            rx: 0,
+            ry: 0,
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        rect: {
+            x: 0,
+            y: 0,
+            width: 0,
+            height: 0,
+            rx: 0,
+            ry: 0,
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        text: {
+            x: 0,
+            y: 0,
+            "text-anchor": "start",
+            font: '10px "Arial"',
+            fill: "#000",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        path: {
+            d: "M0,0",
+            fill: "none",
+            stroke: null,
+            "stroke-width": null,
+            opacity: null,
+            "fill-opacity": null,
+            "stroke-opacity": null
+        },
+        image: {
+            x: 0,
+            y: 0,
+            width: 0,
+            height: 0,
+            preserveAspectRatio: "none",
+            opacity: null
+        }
+    },
 
     
-    forceLayout: false,
+    onMouseEnter: function(e) {
+        this.fireEvent("mouseenter", e);
+    },
 
     
-    
-    defaultType : 'panel',
+    onMouseLeave: function(e) {
+        this.fireEvent("mouseleave", e);
+    },
 
     
-    resizeEvent: 'resize',
+    processEvent: function(name, e) {
+        var target = e.getTarget(),
+            surface = this.surface,
+            sprite;
+        this.fireEvent(name, e);
+        sprite = this.items.get(target.id);
+        if (sprite) {
+            sprite.fireEvent(name, sprite, e);
+        }
+    },
 
     
-    bubbleEvents: ['add', 'remove'],
+    createSpriteElement: function(sprite) {
+        var me = this,
+            attr = sprite.attr,
+            type = sprite.type,
+            zoom = me.zoom,
+            vml = sprite.vml || (sprite.vml = {}),
+            round = Math.round,
+            el = me.createNode('shape'),
+            path, skew, textPath;
+
+        el.coordsize = zoom + ' ' + zoom;
+        el.coordorigin = attr.coordorigin || "0 0";
+        Ext.get(el).addCls(me.spriteCls);
+        if (type == "text") {
+            vml.path = path = me.createNode("path");
+            path.textpathok = true;
+            vml.textpath = textPath = me.createNode("textpath");
+            textPath.on = true;
+            el.appendChild(textPath);
+            el.appendChild(path);
+        }
+        el.id = sprite.id;
+        sprite.el = Ext.get(el);
+        me.el.appendChild(el);
+        if (type !== 'image') {
+            skew = me.createNode("skew");
+            skew.on = true;
+            el.appendChild(skew);
+            sprite.skew = skew;
+        }
+        sprite.matrix = Ext.create('Ext.draw.Matrix');
+        sprite.bbox = {
+            plain: null,
+            transform: null
+        };
+        sprite.fireEvent("render", sprite);
+        return sprite.el;
+    },
 
     
-    initComponent : function(){
-        Ext.Container.superclass.initComponent.call(this);
-
-        this.addEvents(
-            
-            'afterlayout',
-            
-            'beforeadd',
-            
-            'beforeremove',
-            
-            'add',
-            
-            'remove'
-        );
-
-        
-        var items = this.items;
-        if(items){
-            delete this.items;
-            this.add(items);
+    getBBox: function (sprite, isWithoutTransform) {
+        var realPath = this["getPath" + sprite.type](sprite);
+        if (isWithoutTransform) {
+            sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
+            return sprite.bbox.plain;
         }
+        sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
+        return sprite.bbox.transform;
     },
 
-    
-    initItems : function(){
-        if(!this.items){
-            this.items = new Ext.util.MixedCollection(false, this.getComponentId);
-            this.getLayout(); 
-        }
+    getBBoxText: function (sprite) {
+        var vml = sprite.vml;
+        return {
+            x: vml.X + (vml.bbx || 0) - vml.W / 2,
+            y: vml.Y - vml.H / 2,
+            width: vml.W,
+            height: vml.H
+        };
     },
 
-    
-    setLayout : function(layout){
-        if(this.layout && this.layout != layout){
-            this.layout.setContainer(null);
+    applyAttrs: function (sprite) {
+        var me = this,
+            vml = sprite.vml,
+            group = sprite.group,
+            spriteAttr = sprite.attr,
+            el = sprite.el,
+            dom = el.dom,
+            style, name, groups, i, ln, scrubbedAttrs, font, key, bbox;
+
+        if (group) {
+            groups = [].concat(group);
+            ln = groups.length;
+            for (i = 0; i < ln; i++) {
+                group = groups[i];
+                me.getGroup(group).add(sprite);
+            }
+            delete sprite.group;
+        }
+        scrubbedAttrs = me.scrubAttrs(sprite) || {};
+
+        if (sprite.zIndexDirty) {
+            me.setZIndex(sprite);
         }
-        this.layout = layout;
-        this.initItems();
-        layout.setContainer(this);
-    },
 
-    afterRender: function(){
         
+        Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]);
+
+        if (dom.href) {
+            dom.href = scrubbedAttrs.href;
+        }
+        if (dom.title) {
+            dom.title = scrubbedAttrs.title;
+        }
+        if (dom.target) {
+            dom.target = scrubbedAttrs.target;
+        }
+        if (dom.cursor) {
+            dom.cursor = scrubbedAttrs.cursor;
+        }
+
         
-        Ext.Container.superclass.afterRender.call(this);
-        if(!this.layout){
-            this.layout = 'auto';
+        if (sprite.dirtyHidden) {
+            (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
+            sprite.dirtyHidden = false;
         }
-        if(Ext.isObject(this.layout) && !this.layout.layout){
-            this.layoutConfig = this.layout;
-            this.layout = this.layoutConfig.type;
+
+        
+        if (sprite.dirtyPath) {
+            if (sprite.type == "circle" || sprite.type == "ellipse") {
+                var cx = scrubbedAttrs.x,
+                    cy = scrubbedAttrs.y,
+                    rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0,
+                    ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0;
+                dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}",
+                            Math.round((cx - rx) * me.zoom),
+                            Math.round((cy - ry) * me.zoom),
+                            Math.round((cx + rx) * me.zoom),
+                            Math.round((cy + ry) * me.zoom),
+                            Math.round(cx * me.zoom));
+                sprite.dirtyPath = false;
+            }
+            else if (sprite.type !== "text") {
+                sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path;
+                dom.path = me.path2vml(scrubbedAttrs.path);
+                sprite.dirtyPath = false;
+            }
         }
-        if(Ext.isString(this.layout)){
-            this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
+
+        
+        if ("clip-rect" in scrubbedAttrs) {
+            me.setClip(sprite, scrubbedAttrs);
         }
-        this.setLayout(this.layout);
 
         
-        if(this.activeItem !== undefined){
-            var item = this.activeItem;
-            delete this.activeItem;
-            this.layout.setActiveItem(item);
+        if (sprite.type == "text") {
+            me.setTextAttributes(sprite, scrubbedAttrs);
         }
 
         
-        if(!this.ownerCt){
-            this.doLayout(false, true);
+        if (sprite.type == 'image' || scrubbedAttrs.opacity  || scrubbedAttrs['fill-opacity'] || scrubbedAttrs.fill) {
+            me.setFill(sprite, scrubbedAttrs);
         }
 
         
+        if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
+            me.setStroke(sprite, scrubbedAttrs);
+        }
+        
         
-        if(this.monitorResize === true){
-            Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
+        style = spriteAttr.style;
+        if (style) {
+            el.setStyle(style);
         }
+
+        sprite.dirty = false;
     },
 
-    
-    getLayoutTarget : function(){
-        return this.el;
+    setZIndex: function(sprite) {
+        if (sprite.el) {
+            if (sprite.attr.zIndex != undefined) {
+                sprite.el.setStyle('zIndex', sprite.attr.zIndex);
+            }
+            sprite.zIndexDirty = false;
+        }
     },
 
     
-    getComponentId : function(comp){
-        return comp.getItemId();
+    setPaths: function(sprite, params) {
+        var spriteAttr = sprite.attr;
+        
+        sprite.bbox.plain = null;
+        sprite.bbox.transform = null;
+        if (sprite.type == 'circle') {
+            spriteAttr.rx = spriteAttr.ry = params.r;
+            return Ext.draw.Draw.ellipsePath(sprite);
+        }
+        else if (sprite.type == 'ellipse') {
+            spriteAttr.rx = params.rx;
+            spriteAttr.ry = params.ry;
+            return Ext.draw.Draw.ellipsePath(sprite);
+        }
+        else if (sprite.type == 'rect' || sprite.type == 'image') {
+            spriteAttr.rx = spriteAttr.ry = params.r;
+            return Ext.draw.Draw.rectPath(sprite);
+        }
+        else if (sprite.type == 'path' && spriteAttr.path) {
+            return Ext.draw.Draw.pathToAbsolute(spriteAttr.path);
+        }
+        return false;
     },
 
-    
-    add : function(comp){
-        this.initItems();
-        var args = arguments.length > 1;
-        if(args || Ext.isArray(comp)){
-            var result = [];
-            Ext.each(args ? arguments : comp, function(c){
-                result.push(this.add(c));
-            }, this);
-            return result;
+    setFill: function(sprite, params) {
+        var me = this,
+            el = sprite.el,
+            dom = el.dom,
+            fillEl = dom.getElementsByTagName('fill')[0],
+            opacity, gradient, fillUrl, rotation, angle;
+
+        if (fillEl) {
+            dom.removeChild(fillEl);
+        } else {
+            fillEl = me.createNode('fill');
+        }
+        if (Ext.isArray(params.fill)) {
+            params.fill = params.fill[0];
+        }
+        if (sprite.type == 'image') {
+            fillEl.on = true;
+            fillEl.src = params.src;
+            fillEl.type = "tile";
+            fillEl.rotate = true;
+        } else if (params.fill == "none") {
+            fillEl.on = false;
+        } else {
+            if (typeof params.opacity == "number") {
+                fillEl.opacity = params.opacity;
+            }
+            if (typeof params["fill-opacity"] == "number") {
+                fillEl.opacity = params["fill-opacity"];
+            }
+            fillEl.on = true;
+            if (typeof params.fill == "string") {
+                fillUrl = params.fill.match(me.fillUrlRe);
+                if (fillUrl) {
+                    fillUrl = fillUrl[1];
+                    
+                    if (fillUrl.charAt(0) == "#") {
+                        gradient = me.gradientsColl.getByKey(fillUrl.substring(1));
+                    }
+                    if (gradient) {
+                        
+                        rotation = params.rotation;
+                        angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360;
+                        
+                        if (angle === 0) {
+                            angle = 180;
+                        }
+                        fillEl.angle = angle;
+                        fillEl.type = "gradient";
+                        fillEl.method = "sigma";
+                        fillEl.colors = gradient.colors;
+                    }
+                    
+                    else {
+                        fillEl.src = fillUrl;
+                        fillEl.type = "tile";
+                        fillEl.rotate = true;
+                    }
+                }
+                else {
+                    fillEl.color = Ext.draw.Color.toHex(params.fill) || params.fill;
+                    fillEl.src = "";
+                    fillEl.type = "solid";
+                }
+            }
         }
-        var c = this.lookupComponent(this.applyDefaults(comp));
-        var index = this.items.length;
-        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
-            this.items.add(c);
+        dom.appendChild(fillEl);
+    },
+
+    setStroke: function(sprite, params) {
+        var me = this,
+            el = sprite.el.dom,
+            strokeEl = sprite.strokeEl,
+            newStroke = false,
+            width, opacity;
+
+        if (!strokeEl) {
+            strokeEl = sprite.strokeEl = me.createNode("stroke");
+            newStroke = true;
+        }
+        if (Ext.isArray(params.stroke)) {
+            params.stroke = params.stroke[0];
+        }
+        if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) {
+            strokeEl.on = false;
+        }
+        else {
+            strokeEl.on = true;
+            if (params.stroke && !params.stroke.match(me.fillUrlRe)) {
+                
+                strokeEl.color = Ext.draw.Color.toHex(params.stroke);
+            }
+            strokeEl.joinstyle = params["stroke-linejoin"];
+            strokeEl.endcap = params["stroke-linecap"] || "round";
+            strokeEl.miterlimit = params["stroke-miterlimit"] || 8;
+            width = parseFloat(params["stroke-width"] || 1) * 0.75;
+            opacity = params["stroke-opacity"] || 1;
             
-            c.onAdded(this, index);
-            this.onAdd(c);
-            this.fireEvent('add', this, c, index);
+            if (Ext.isNumber(width) && width < 1) {
+                strokeEl.weight = 1;
+                strokeEl.opacity = opacity * width;
+            }
+            else {
+                strokeEl.weight = width;
+                strokeEl.opacity = opacity;
+            }
+        }
+        if (newStroke) {
+            el.appendChild(strokeEl);
         }
-        return c;
     },
 
-    onAdd : function(c){
-        
+    setClip: function(sprite, params) {
+        var me = this,
+            el = sprite.el,
+            clipEl = sprite.clipEl,
+            rect = String(params["clip-rect"]).split(me.separatorRe);
+        if (!clipEl) {
+            clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div"));
+            clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite');
+        }
+        if (rect.length == 4) {
+            rect[2] = +rect[2] + (+rect[0]);
+            rect[3] = +rect[3] + (+rect[1]);
+            clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3]));
+            clipEl.setSize(me.el.width, me.el.height);
+        }
+        else {
+            clipEl.setStyle("clip", "");
+        }
     },
 
-    
-    onAdded : function(container, pos) {
-        
-        this.ownerCt = container;
-        this.initRef();
+    setTextAttributes: function(sprite, params) {
+        var me = this,
+            vml = sprite.vml,
+            textStyle = vml.textpath.style,
+            spanCacheStyle = me.span.style,
+            zoom = me.zoom,
+            round = Math.round,
+            fontObj = {
+                fontSize: "font-size",
+                fontWeight: "font-weight",
+                fontStyle: "font-style"
+            },
+            fontProp,
+            paramProp;
+        if (sprite.dirtyFont) {
+            if (params.font) {
+                textStyle.font = spanCacheStyle.font = params.font;
+            }
+            if (params["font-family"]) {
+                textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"';
+                spanCacheStyle.fontFamily = params["font-family"];
+            }
+
+            for (fontProp in fontObj) {
+                paramProp = params[fontObj[fontProp]];
+                if (paramProp) {
+                    textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp;
+                }
+            }
+
+            me.setText(sprite, params.text);
+            
+            if (vml.textpath.string) {
+                me.span.innerHTML = String(vml.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>");
+            }
+            vml.W = me.span.offsetWidth;
+            vml.H = me.span.offsetHeight + 2; 
+
+            
+            if (params["text-anchor"] == "middle") {
+                textStyle["v-text-align"] = "center";
+            }
+            else if (params["text-anchor"] == "end") {
+                textStyle["v-text-align"] = "right";
+                vml.bbx = -Math.round(vml.W / 2);
+            }
+            else {
+                textStyle["v-text-align"] = "left";
+                vml.bbx = Math.round(vml.W / 2);
+            }
+        }
+        vml.X = params.x;
+        vml.Y = params.y;
+        vml.path.v = Ext.String.format("m{0},{1}l{2},{1}", Math.round(vml.X * zoom), Math.round(vml.Y * zoom), Math.round(vml.X * zoom) + 1);
         
-        this.cascade(function(c){
-            c.initRef();
-        });
-        this.fireEvent('added', this, container, pos);
+        sprite.bbox.plain = null;
+        sprite.bbox.transform = null;
+        sprite.dirtyFont = false;
     },
-
     
-    insert : function(index, comp){
-        this.initItems();
-        var a = arguments, len = a.length;
-        if(len > 2){
-            var result = [];
-            for(var i = len-1; i >= 1; --i) {
-                result.push(this.insert(index, a[i]));
+    setText: function(sprite, text) {
+        sprite.vml.textpath.string = Ext.htmlDecode(text);
+    },
+
+    hide: function() {
+        this.el.hide();
+    },
+
+    show: function() {
+        this.el.show();
+    },
+
+    hidePrim: function(sprite) {
+        sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility');
+    },
+
+    showPrim: function(sprite) {
+        sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility');
+    },
+
+    setSize: function(width, height) {
+        var me = this;
+        width = width || me.width;
+        height = height || me.height;
+        me.width = width;
+        me.height = height;
+
+        if (me.el) {
+            
+            if (width != undefined) {
+                me.el.setWidth(width);
             }
-            return result;
-        }
-        var c = this.lookupComponent(this.applyDefaults(comp));
-        index = Math.min(index, this.items.length);
-        if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
-            if(c.ownerCt == this){
-                this.items.remove(c);
+            if (height != undefined) {
+                me.el.setHeight(height);
             }
-            this.items.insert(index, c);
-            c.onAdded(this, index);
-            this.onAdd(c);
-            this.fireEvent('add', this, c, index);
+
+            
+            me.applyViewBox();
+
+            me.callParent(arguments);
         }
-        return c;
+    },
+
+    setViewBox: function(x, y, width, height) {
+        this.callParent(arguments);
+        this.viewBox = {
+            x: x,
+            y: y,
+            width: width,
+            height: height
+        };
+        this.applyViewBox();
     },
 
     
-    applyDefaults : function(c){
-        var d = this.defaults;
-        if(d){
-            if(Ext.isFunction(d)){
-                d = d.call(this, c);
+    applyViewBox: function() {
+        var me = this,
+            viewBox = me.viewBox,
+            width = me.width,
+            height = me.height,
+            viewBoxX, viewBoxY, viewBoxWidth, viewBoxHeight,
+            relativeHeight, relativeWidth, size;
+
+        if (viewBox && (width || height)) {
+            viewBoxX = viewBox.x;
+            viewBoxY = viewBox.y;
+            viewBoxWidth = viewBox.width;
+            viewBoxHeight = viewBox.height;
+            relativeHeight = height / viewBoxHeight;
+            relativeWidth = width / viewBoxWidth;
+
+            if (viewBoxWidth * relativeHeight < width) {
+                viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
             }
-            if(Ext.isString(c)){
-                c = Ext.ComponentMgr.get(c);
-                Ext.apply(c, d);
-            }else if(!c.events){
-                Ext.applyIf(c, d);
-            }else{
-                Ext.apply(c, d);
+            if (viewBoxHeight * relativeWidth < height) {
+                viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
             }
+
+            size = 1 / Math.max(viewBoxWidth / width, viewBoxHeight / height);
+
+            me.viewBoxShift = {
+                dx: -viewBoxX,
+                dy: -viewBoxY,
+                scale: size
+            };
+            me.items.each(function(item) {
+                me.transform(item);
+            });
         }
-        return c;
     },
 
-    
-    onBeforeAdd : function(item){
-        if(item.ownerCt){
-            item.ownerCt.remove(item, false);
+    onAdd: function(item) {
+        this.callParent(arguments);
+        if (this.el) {
+            this.renderItem(item);
         }
-        if(this.hideBorders === true){
-            item.border = (item.border === true);
+    },
+
+    onRemove: function(sprite) {
+        if (sprite.el) {
+            sprite.el.remove();
+            delete sprite.el;
         }
+        this.callParent(arguments);
     },
 
     
-    remove : function(comp, autoDestroy){
-        this.initItems();
-        var c = this.getComponent(comp);
-        if(c && this.fireEvent('beforeremove', this, c) !== false){
-            this.doRemove(c, autoDestroy);
-            this.fireEvent('remove', this, c);
+    createNode : (function () {
+        try {
+            var doc = Ext.getDoc().dom;
+            if (!doc.namespaces.rvml) {
+                doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
+            }
+            return function (tagName) {
+                return doc.createElement("<rvml:" + tagName + ' class="rvml">');
+            };
+        } catch (e) {
+            return function (tagName) {
+                return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
+            };
         }
-        return c;
+    })(),
+
+    render: function (container) {
+        var me = this,
+            doc = Ext.getDoc().dom;
+
+        if (!me.el) {
+            var el = doc.createElement("div");
+            me.el = Ext.get(el);
+            me.el.addCls(me.baseVmlCls);
+
+            
+            me.span = doc.createElement("span");
+            Ext.get(me.span).addCls(me.measureSpanCls);
+            el.appendChild(me.span);
+            me.el.setSize(me.width || 10, me.height || 10);
+            container.appendChild(el);
+            me.el.on({
+                scope: me,
+                mouseup: me.onMouseUp,
+                mousedown: me.onMouseDown,
+                mouseover: me.onMouseOver,
+                mouseout: me.onMouseOut,
+                mousemove: me.onMouseMove,
+                mouseenter: me.onMouseEnter,
+                mouseleave: me.onMouseLeave,
+                click: me.onClick
+            });
+        }
+        me.renderAll();
     },
 
-    onRemove: function(c){
-        
+    renderAll: function() {
+        this.items.each(this.renderItem, this);
     },
 
-    
-    doRemove: function(c, autoDestroy){
-        var l = this.layout,
-            hasLayout = l && this.rendered;
+    redraw: function(sprite) {
+        sprite.dirty = true;
+        this.renderItem(sprite);
+    },
 
-        if(hasLayout){
-            l.onRemove(c);
-        }
-        this.items.remove(c);
-        c.onRemoved();
-        this.onRemove(c);
-        if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
-            c.destroy();
+    renderItem: function (sprite) {
+        
+        if (!this.el) {
+            return;
         }
-        if(hasLayout){
-            l.afterRemove(c);
+
+        
+        if (!sprite.el) {
+            this.createSpriteElement(sprite);
         }
-    },
 
-    
-    removeAll: function(autoDestroy){
-        this.initItems();
-        var item, rem = [], items = [];
-        this.items.each(function(i){
-            rem.push(i);
-        });
-        for (var i = 0, len = rem.length; i < len; ++i){
-            item = rem[i];
-            this.remove(item, autoDestroy);
-            if(item.ownerCt !== this){
-                items.push(item);
+        if (sprite.dirty) {
+            this.applyAttrs(sprite);
+            if (sprite.dirtyTransform) {
+                this.applyTransformations(sprite);
             }
         }
-        return items;
     },
 
-    
-    getComponent : function(comp){
-        if(Ext.isObject(comp)){
-            comp = comp.getItemId();
-        }
-        return this.items.get(comp);
+    rotationCompensation: function (deg, dx, dy) {
+        var matrix = Ext.create('Ext.draw.Matrix');
+        matrix.rotate(-deg, 0.5, 0.5);
+        return {
+            x: matrix.x(dx, dy),
+            y: matrix.y(dx, dy)
+        };
     },
 
-    
-    lookupComponent : function(comp){
-        if(Ext.isString(comp)){
-            return Ext.ComponentMgr.get(comp);
-        }else if(!comp.events){
-            return this.createComponent(comp);
+    extractTransform: function (sprite) {
+        var me = this,
+            matrix = Ext.create('Ext.draw.Matrix'), scale,
+            transformstions, tranformationsLength,
+            transform, i = 0,
+            shift = me.viewBoxShift;
+
+        for(transformstions = sprite.transformations, tranformationsLength = transformstions.length;
+            i < tranformationsLength; i ++) {
+            transform = transformstions[i];
+            switch (transform.type) {
+                case 'translate' :
+                    matrix.translate(transform.x, transform.y);
+                    break;
+                case 'rotate':
+                    matrix.rotate(transform.degrees, transform.x, transform.y);
+                    break;
+                case 'scale':
+                    matrix.scale(transform.x || transform.scale, transform.y || transform.scale, transform.centerX, transform.centerY);
+                    break;
+            }
         }
-        return comp;
-    },
 
-    
-    createComponent : function(config, defaultType){
-        if (config.render) {
-            return config;
+        if (shift) {
+            matrix.add(1, 0, 0, 1, shift.dx, shift.dy);
+            matrix.prepend(shift.scale, 0, 0, shift.scale, 0, 0);
         }
         
-        
-        var c = Ext.create(Ext.apply({
-            ownerCt: this
-        }, config), defaultType || this.defaultType);
-        delete c.initialConfig.ownerCt;
-        delete c.ownerCt;
-        return c;
+        return sprite.matrix = matrix;
     },
 
-    
-    canLayout : function() {
-        var el = this.getVisibilityEl();
-        return el && el.dom && !el.isStyle("display", "none");
+    setSimpleCoords: function(sprite, sx, sy, dx, dy, rotate) {
+        var me = this,
+            matrix = sprite.matrix,
+            dom = sprite.el.dom,
+            style = dom.style,
+            yFlipper = 1,
+            flip = "",
+            fill = dom.getElementsByTagName('fill')[0],
+            kx = me.zoom / sx,
+            ky = me.zoom / sy,
+            rotationCompensation;
+        if (!sx || !sy) {
+            return;
+        }
+        dom.coordsize = Math.abs(kx) + ' ' + Math.abs(ky);
+        style.rotation = rotate * (sx * sy < 0 ? -1 : 1);
+        if (rotate) {
+            rotationCompensation = me.rotationCompensation(rotate, dx, dy);
+            dx = rotationCompensation.x;
+            dy = rotationCompensation.y;
+        }
+        if (sx < 0) {
+            flip += "x"
+        }
+        if (sy < 0) {
+            flip += " y";
+            yFlipper = -1;
+        }
+        style.flip = flip;
+        dom.coordorigin = (dx * -kx) + ' ' + (dy * -ky);
+        if (fill) {
+            dom.removeChild(fill);
+            rotationCompensation = me.rotationCompensation(rotate, matrix.x(sprite.x, sprite.y), matrix.y(sprite.x, sprite.y));
+            fill.position = rotationCompensation.x * yFlipper + ' ' + rotationCompensation.y * yFlipper;
+            fill.size = sprite.width * Math.abs(sx) + ' ' + sprite.height * Math.abs(sy);
+            dom.appendChild(fill);
+        }
     },
 
-    
+    transform : function (sprite) {
+        var me = this,
+            el = sprite.el,
+            skew = sprite.skew,
+            dom = el.dom,
+            domStyle = dom.style,
+            matrix = me.extractTransform(sprite).clone(),
+            split, zoom = me.zoom,
+            fill = dom.getElementsByTagName('fill')[0],
+            isPatt = !String(sprite.fill).indexOf("url("),
+            offset, c;
 
-    doLayout : function(shallow, force){
-        var rendered = this.rendered,
-            forceLayout = force || this.forceLayout;
 
-        if(this.collapsed || !this.canLayout()){
-            this.deferLayout = this.deferLayout || !shallow;
-            if(!forceLayout){
-                return;
+        
+
+        if (sprite.type != "image" && skew && !isPatt) {
+            
+            skew.matrix = matrix.toString();
+            
+            
+            
+            offset = matrix.offset();
+            if (offset[0] > 32767) {
+                offset[0] = 32767;
+            } else if (offset[0] < -32768) {
+                offset[0] = -32768
+            }
+            if (offset[1] > 32767) {
+                offset[1] = 32767;
+            } else if (offset[1] < -32768) {
+                offset[1] = -32768
             }
-            shallow = shallow && !this.deferLayout;
+            skew.offset = offset;
         } else {
-            delete this.deferLayout;
-        }
-        if(rendered && this.layout){
-            this.layout.layout();
-        }
-        if(shallow !== true && this.items){
-            var cs = this.items.items;
-            for(var i = 0, len = cs.length; i < len; i++){
-                var c = cs[i];
-                if(c.doLayout){
-                    c.doLayout(false, forceLayout);
+            if (skew) {
+                skew.matrix = "1 0 0 1";
+                skew.offset = "0 0";
+            }
+            split = matrix.split();
+            if (split.isSimple) {
+                domStyle.filter = '';
+                me.setSimpleCoords(sprite, split.scaleX, split.scaleY, split.translateX, split.translateY, split.rotate / Math.PI * 180);
+            } else {
+                domStyle.filter = matrix.toFilter();
+                var bb = me.getBBox(sprite),
+                    dx = bb.x - sprite.x,
+                    dy = bb.y - sprite.y;
+                dom.coordorigin = (dx * -zoom) + ' ' + (dy * -zoom);
+                if (fill) {
+                    dom.removeChild(fill);
+                    fill.position = dx + ' ' + dy;
+                    fill.size = sprite.width * sprite.scale.x + ' ' + sprite.height * 1.1;
+                    dom.appendChild(fill);
                 }
             }
         }
-        if(rendered){
-            this.onLayout(shallow, forceLayout);
-        }
-        
-        this.hasLayout = true;
-        delete this.forceLayout;
     },
 
-    onLayout : Ext.emptyFn,
+    createItem: function (config) {
+        return Ext.create('Ext.draw.Sprite', config);
+    },
 
-    
-    shouldBufferLayout: function(){
-        
-        var hl = this.hasLayout;
-        if(this.ownerCt){
-            
-            return hl ? !this.hasLayoutPending() : false;
+    getRegion: function() {
+        return this.el.getRegion();
+    },
+
+    addCls: function(sprite, className) {
+        if (sprite && sprite.el) {
+            sprite.el.addCls(className);
+        }
+    },
+
+    removeCls: function(sprite, className) {
+        if (sprite && sprite.el) {
+            sprite.el.removeCls(className);
         }
-        
-        return hl;
     },
 
     
-    hasLayoutPending: function(){
+    addGradient: function(gradient) {
+        var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')),
+            colors = [],
+            stops = Ext.create('Ext.util.MixedCollection');
+
         
-        var pending = false;
-        this.ownerCt.bubble(function(c){
-            if(c.layoutPending){
-                pending = true;
-                return false;
-            }
+        stops.addAll(gradient.stops);
+        stops.sortByKey("ASC", function(a, b) {
+            a = parseInt(a, 10);
+            b = parseInt(b, 10);
+            return a > b ? 1 : (a < b ? -1 : 0);
+        });
+        stops.eachKey(function(k, v) {
+            colors.push(k + "% " + v.color);
+        });
+
+        gradients.add(gradient.id, {
+            colors: colors.join(","),
+            angle: gradient.angle
         });
-        return pending;
     },
 
-    onShow : function(){
-        
-        Ext.Container.superclass.onShow.call(this);
+    destroy: function() {
+        var me = this;
         
-        if(Ext.isDefined(this.deferLayout)){
-            delete this.deferLayout;
-            this.doLayout(true);
+        me.callParent(arguments);
+        if (me.el) {
+            me.el.remove();
         }
-    },
+        delete me.el;
+    }
+});
 
-    
-    getLayout : function(){
-        if(!this.layout){
-            var layout = new Ext.layout.AutoLayout(this.layoutConfig);
-            this.setLayout(layout);
-        }
-        return this.layout;
-    },
+
+Ext.define('Ext.fx.target.ElementCSS', {
 
     
-    beforeDestroy : function(){
-        var c;
-        if(this.items){
-            while(c = this.items.first()){
-                this.doRemove(c, true);
-            }
-        }
-        if(this.monitorResize){
-            Ext.EventManager.removeResizeListener(this.doLayout, this);
-        }
-        Ext.destroy(this.layout);
-        Ext.Container.superclass.beforeDestroy.call(this);
-    },
+
+    extend: 'Ext.fx.target.Element',
 
     
-    bubble : function(fn, scope, args){
-        var p = this;
-        while(p){
-            if(fn.apply(scope || p, args || [p]) === false){
-                break;
+
+    setAttr: function(targetData, isFirstFrame) {
+        var cssArr = {
+                attrs: [],
+                duration: [],
+                easing: []
+            },
+            ln = targetData.length,
+            attributes,
+            attrs,
+            attr,
+            easing,
+            duration,
+            o,
+            i,
+            j,
+            ln2;
+        for (i = 0; i < ln; i++) {
+            attrs = targetData[i];
+            duration = attrs.duration;
+            easing = attrs.easing;
+            attrs = attrs.attrs;
+            for (attr in attrs) {
+                if (Ext.Array.indexOf(cssArr.attrs, attr) == -1) {
+                    cssArr.attrs.push(attr.replace(/[A-Z]/g, function(v) {
+                        return '-' + v.toLowerCase();
+                    }));
+                    cssArr.duration.push(duration + 'ms');
+                    cssArr.easing.push(easing);
+                }
             }
-            p = p.ownerCt;
         }
-        return this;
-    },
+        attributes = cssArr.attrs.join(',');
+        duration = cssArr.duration.join(',');
+        easing = cssArr.easing.join(', ');
+        for (i = 0; i < ln; i++) {
+            attrs = targetData[i].attrs;
+            for (attr in attrs) {
+                ln2 = attrs[attr].length;
+                for (j = 0; j < ln2; j++) {
+                    o = attrs[attr][j];
+                    o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', isFirstFrame ? '' : attributes);
+                    o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', isFirstFrame ? '' : duration);
+                    o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', isFirstFrame ? '' : easing);
+                    o[0].setStyle(attr, o[1]);
 
-    
-    cascade : function(fn, scope, args){
-        if(fn.apply(scope || this, args || [this]) !== false){
-            if(this.items){
-                var cs = this.items.items;
-                for(var i = 0, len = cs.length; i < len; i++){
-                    if(cs[i].cascade){
-                        cs[i].cascade(fn, scope, args);
-                    }else{
-                        fn.apply(scope || cs[i], args || [cs[i]]);
+                    
+                    if (isFirstFrame) {
+                        o = o[0].dom.offsetWidth;
+                    }
+                    else {
+                        
+                        o[0].on(Ext.supports.CSS3TransitionEnd, function() {
+                            this.setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', null);
+                            this.setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', null);
+                            this.setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', null);
+                        }, o[0], { single: true });
                     }
                 }
             }
         }
-        return this;
-    },
+    }
+});
 
-    
-    findById : function(id){
-        var m, ct = this;
-        this.cascade(function(c){
-            if(ct != c && c.id === id){
-                m = c;
-                return false;
-            }
-        });
-        return m || null;
-    },
+Ext.define('Ext.fx.target.CompositeElementCSS', {
 
     
-    findByType : function(xtype, shallow){
-        return this.findBy(function(c){
-            return c.isXType(xtype, shallow);
-        });
-    },
 
-    
-    find : function(prop, value){
-        return this.findBy(function(c){
-            return c[prop] === value;
-        });
-    },
+    extend: 'Ext.fx.target.CompositeElement',
 
-    
-    findBy : function(fn, scope){
-        var m = [], ct = this;
-        this.cascade(function(c){
-            if(ct != c && fn.call(scope || c, c, ct) === true){
-                m.push(c);
-            }
-        });
-        return m;
-    },
+    requires: ['Ext.fx.target.ElementCSS'],
 
     
-    get : function(key){
-        return this.items.get(key);
+    setAttr: function() {
+        return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments);
     }
 });
 
-Ext.Container.LAYOUTS = {};
-Ext.reg('container', Ext.Container);
+Ext.define('Ext.layout.container.AbstractFit', {
 
-Ext.layout.ContainerLayout = Ext.extend(Object, {
-    
     
 
-    
+    extend: 'Ext.layout.container.Container',
 
     
-    monitorResize:false,
-    
-    activeItem : null,
 
-    constructor : function(config){
-        this.id = Ext.id(null, 'ext-layout-');
-        Ext.apply(this, config);
-    },
+    itemCls: Ext.baseCSSPrefix + 'fit-item',
+    targetCls: Ext.baseCSSPrefix + 'layout-fit',
+    type: 'fit'
+});
 
-    type: 'container',
+Ext.define('Ext.layout.container.Fit', {
 
     
-    IEMeasureHack : function(target, viewFlag) {
-        var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
-        for (i = 0 ; i < tLen ; i++) {
-            c = tChildren[i];
-            e = Ext.get(c);
-            if (e) {
-                d[i] = e.getStyle('display');
-                e.setStyle({display: 'none'});
-            }
-        }
-        ret = target ? target.getViewSize(viewFlag) : {};
-        for (i = 0 ; i < tLen ; i++) {
-            c = tChildren[i];
-            e = Ext.get(c);
-            if (e) {
-                e.setStyle({display: d[i]});
-            }
-        }
-        return ret;
-    },
 
-    
-    getLayoutTargetSize : Ext.EmptyFn,
+    extend: 'Ext.layout.container.AbstractFit',
+    alias: 'layout.fit',
+    alternateClassName: 'Ext.layout.FitLayout',
+    requires: ['Ext.layout.container.Box'],
 
     
-    layout : function(){
-        var ct = this.container, target = ct.getLayoutTarget();
-        if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
-            target.addClass(this.targetCls);
-        }
-        this.onLayout(ct, target);
-        ct.fireEvent('afterlayout', ct, this);
-    },
 
     
-    onLayout : function(ct, target){
-        this.renderAll(ct, target);
+    defaultMargins: {
+        top: 0,
+        right: 0,
+        bottom: 0,
+        left: 0
     },
 
     
-    isValidParent : function(c, target){
-        return target && c.getPositionEl().dom.parentNode == (target.dom || target);
-    },
+    onLayout : function() {
+        var me = this,
+            size,
+            item,
+            margins;
+        me.callParent();
 
-    
-    renderAll : function(ct, target){
-        var items = ct.items.items, i, c, len = items.length;
-        for(i = 0; i < len; i++) {
-            c = items[i];
-            if(c && (!c.rendered || !this.isValidParent(c, target))){
-                this.renderItem(c, i, target);
+        if (me.owner.items.length) {
+            item = me.owner.items.get(0);
+            margins = item.margins || me.defaultMargins;
+            size = me.getLayoutTargetSize();
+            size.width  -= margins.width;
+            size.height -= margins.height;
+            me.setItemBox(item, size);
+
+            
+            
+            if (margins.left || margins.top) {
+                item.setPosition(margins.left, margins.top);
             }
         }
     },
 
-    
-    renderItem : function(c, position, target){
-        if (c) {
-            if (!c.rendered) {
-                c.render(target, position);
-                this.configureItem(c, position);
-            } else if (!this.isValidParent(c, target)) {
-                if (Ext.isNumber(position)) {
-                    position = target.dom.childNodes[position];
-                }
-                
-                target.dom.insertBefore(c.getPositionEl().dom, position || null);
-                c.container = target;
-                this.configureItem(c, position);
+    getTargetBox : function() {
+        return this.getLayoutTargetSize();
+    },
+
+    setItemBox : function(item, box) {
+        var me = this;
+        if (item && box.height > 0) {
+            if (!me.owner.isFixedWidth()) {
+               box.width = undefined;
             }
+            if (!me.owner.isFixedHeight()) {
+               box.height = undefined;
+            }
+            me.setItemSize(item, box.width, box.height);
         }
     },
 
+    configureItem: function(item) {
+
+        
+        
+        item.layoutManagedHeight = 0;
+        item.layoutManagedWidth = 0;
+
+        this.callParent(arguments);
+    }
+}, function() {
     
     
-    getRenderedItems: function(ct){
-        var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
-        for (i = 0; i < len; i++) {
-            if((c = cti[i]).rendered && this.isValidParent(c, t)){
-                items.push(c);
-            }
-        };
-        return items;
-    },
+    this.prototype.renderItem = Ext.layout.container.Box.prototype.renderItem;
+});
+
+Ext.define('Ext.layout.container.AbstractCard', {
 
     
-    configureItem: function(c, position){
-        if (this.extraCls) {
-            var t = c.getPositionEl ? c.getPositionEl() : c;
-            t.addClass(this.extraCls);
-        }
-        
-        
-        if (c.doLayout && this.forceLayout) {
-            c.doLayout();
-        }
-        if (this.renderHidden && c != this.activeItem) {
-            c.hide();
-        }
-    },
 
-    onRemove: function(c){
-        if(this.activeItem == c){
-            delete this.activeItem;
+    extend: 'Ext.layout.container.Fit',
+
+    
+
+    type: 'card',
+
+    sizeAllCards: false,
+
+    hideInactive: true,
+
+    
+    deferredRender : false,
+
+    beforeLayout: function() {
+        var me = this;
+        me.getActiveItem();
+        if (me.activeItem && me.deferredRender) {
+            me.renderItems([me.activeItem], me.getRenderTarget());
+            return true;
         }
-        if(c.rendered && this.extraCls){
-            var t = c.getPositionEl ? c.getPositionEl() : c;
-            t.removeClass(this.extraCls);
+        else {
+            return this.callParent(arguments);
         }
     },
 
-    afterRemove: function(c){
-        if(c.removeRestore){
-            c.removeMode = 'container';
-            delete c.removeRestore;
+    renderChildren: function () {
+        if (!this.deferredRender) {
+            this.getActiveItem();
+            this.callParent();
         }
     },
 
-    
-    onResize: function(){
-        var ct = this.container,
-            b;
-        if(ct.collapsed){
-            return;
+    onLayout: function() {
+        var me = this,
+            activeItem = me.activeItem,
+            items = me.getVisibleItems(),
+            ln = items.length,
+            targetBox = me.getTargetBox(),
+            i, item;
+
+        for (i = 0; i < ln; i++) {
+            item = items[i];
+            me.setItemBox(item, targetBox);
         }
-        if(b = ct.bufferResize && ct.shouldBufferLayout()){
-            if(!this.resizeTask){
-                this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
-                this.resizeBuffer = Ext.isNumber(b) ? b : 50;
+
+        if (!me.firstActivated && activeItem) {
+            if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
+                activeItem.fireEvent('activate', activeItem);
             }
-            ct.layoutPending = true;
-            this.resizeTask.delay(this.resizeBuffer);
-        }else{
-            this.runLayout();
+            me.firstActivated = true;
         }
     },
 
-    runLayout: function(){
-        var ct = this.container;
-        this.layout();
-        ct.onLayout();
-        delete ct.layoutPending;
-    },
-
-    
-    setContainer : function(ct){
+    isValidParent : function(item, target, position) {
         
-        if(this.monitorResize && ct != this.container){
-            var old = this.container;
-            if(old){
-                old.un(old.resizeEvent, this.onResize, this);
-            }
-            if(ct){
-                ct.on(ct.resizeEvent, this.onResize, this);
-            }
-        }
-        this.container = ct;
+        
+        var itemEl = item.el ? item.el.dom : Ext.getDom(item);
+        return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
     },
 
     
-    parseMargins : function(v){
-        if (Ext.isNumber(v)) {
-            v = v.toString();
+    getActiveItem: function() {
+        var me = this;
+        if (!me.activeItem && me.owner) {
+            me.activeItem = me.parseActiveItem(me.owner.activeItem);
         }
-        var ms  = v.split(' '),
-            len = ms.length;
-            
-        if (len == 1) {
-            ms[1] = ms[2] = ms[3] = ms[0];
-        } else if(len == 2) {
-            ms[2] = ms[0];
-            ms[3] = ms[1];
-        } else if(len == 3) {
-            ms[3] = ms[1];
+
+        if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
+            return me.activeItem;
         }
-        
-        return {
-            top   :parseInt(ms[0], 10) || 0,
-            right :parseInt(ms[1], 10) || 0,
-            bottom:parseInt(ms[2], 10) || 0,
-            left  :parseInt(ms[3], 10) || 0
-        };
-    },
 
-    
-    fieldTpl: (function() {
-        var t = new Ext.Template(
-            '<div class="x-form-item {itemCls}" tabIndex="-1">',
-                '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
-                '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
-                '</div><div class="{clearCls}"></div>',
-            '</div>'
-        );
-        t.disableFormats = true;
-        return t.compile();
-    })(),
+        return null;
+    },
 
     
-    destroy : function(){
-        
-        if(this.resizeTask && this.resizeTask.cancel){
-            this.resizeTask.cancel();
+    parseActiveItem: function(item) {
+        if (item && item.isComponent) {
+            return item;
         }
-        if(!Ext.isEmpty(this.targetCls)){
-            var target = this.container.getLayoutTarget();
-            if(target){
-                target.removeClass(this.targetCls);
-            }
+        else if (typeof item == 'number' || item === undefined) {
+            return this.getLayoutItems()[item || 0];
         }
-    }
-});
-Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
-    type: 'auto',
-
-    monitorResize: true,
-
-    onLayout : function(ct, target){
-        Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
-        var cs = this.getRenderedItems(ct), len = cs.length, i, c;
-        for(i = 0; i < len; i++){
-            c = cs[i];
-            if (c.doLayout){
-                
-                c.doLayout(true);
-            }
+        else {
+            return this.owner.getComponent(item);
         }
-    }
-});
-
-Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
+    },
 
-Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
     
-    monitorResize:true,
-
-    type: 'fit',
-
-    getLayoutTargetSize : function() {
-        var target = this.container.getLayoutTarget();
-        if (!target) {
-            return {};
+    configureItem: function(item, position) {
+        this.callParent([item, position]);
+        if (this.hideInactive && this.activeItem !== item) {
+            item.hide();
+        }
+        else {
+            item.show();
         }
-        
-        return target.getStyleSize();
     },
 
-    
-    onLayout : function(ct, target){
-        Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
-        if(!ct.collapsed){
-            this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
+    onRemove: function(component) {
+        if (component === this.activeItem) {
+            this.activeItem = null;
+            if (this.owner.items.getCount() === 0) {
+                this.firstActivated = false;
+            }
         }
     },
 
     
-    setItemSize : function(item, size){
-        if(item && size.height > 0){ 
-            item.setSize(size);
+    getAnimation: function(newCard, owner) {
+        var newAnim = (newCard || {}).cardSwitchAnimation;
+        if (newAnim === false) {
+            return false;
         }
-    }
-});
-Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;
-Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
-    
-    deferredRender : false,
+        return newAnim || owner.cardSwitchAnimation;
+    },
 
     
-    layoutOnCardChange : false,
+    getNext: function() {
+        
+        
+        var wrap = arguments[0];
+        var items = this.getLayoutItems(),
+            index = Ext.Array.indexOf(items, this.activeItem);
+        return items[index + 1] || (wrap ? items[0] : false);
+    },
 
     
-    
-    renderHidden : true,
-
-    type: 'card',
+    next: function() {
+        
+        
+        var anim = arguments[0], wrap = arguments[1];
+        return this.setActiveItem(this.getNext(wrap), anim);
+    },
 
     
-    setActiveItem : function(item){
-        var ai = this.activeItem,
-            ct = this.container;
-        item = ct.getComponent(item);
-
+    getPrev: function() {
         
-        if(item && ai != item){
-
-            
-            if(ai){
-                ai.hide();
-                if (ai.hidden !== true) {
-                    return false;
-                }
-                ai.fireEvent('deactivate', ai);
-            }
-
-            var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
-
-            
-            this.activeItem = item;
-
-            
-            
-            delete item.deferLayout;
-
-            
-            item.show();
-
-            this.layout();
-
-            if(layout){
-                item.doLayout();
-            }
-            item.fireEvent('activate', item);
-        }
+        
+        var wrap = arguments[0];
+        var items = this.getLayoutItems(),
+            index = Ext.Array.indexOf(items, this.activeItem);
+        return items[index - 1] || (wrap ? items[items.length - 1] : false);
     },
 
     
-    renderAll : function(ct, target){
-        if(this.deferredRender){
-            this.renderItem(this.activeItem, undefined, target);
-        }else{
-            Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
-        }
+    prev: function() {
+        
+        
+        var anim = arguments[0], wrap = arguments[1];
+        return this.setActiveItem(this.getPrev(wrap), anim);
     }
 });
-Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
 
-Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
+
+Ext.define('Ext.selection.Model', {
+    extend: 'Ext.util.Observable',
+    alternateClassName: 'Ext.AbstractSelectionModel',
+    requires: ['Ext.data.StoreManager'],
     
 
     
-    monitorResize : true,
 
-    type : 'anchor',
+    
+    allowDeselect: false,
 
     
-    defaultAnchor : '100%',
+    selected: null,
 
-    parseAnchorRE : /^(r|right|b|bottom)$/i,
+    
+    pruneRemoved: true,
 
-    getLayoutTargetSize : function() {
-        var target = this.container.getLayoutTarget();
-        if (!target) {
-            return {};
-        }
-        
-        return target.getStyleSize();
-    },
+    constructor: function(cfg) {
+        var me = this;
 
-    
-    onLayout : function(ct, target){
-        Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
-        var size = this.getLayoutTargetSize();
+        cfg = cfg || {};
+        Ext.apply(me, cfg);
 
-        var w = size.width, h = size.height;
+        me.addEvents(
+            
+            'selectionchange'
+        );
 
-        if(w < 20 && h < 20){
-            return;
-        }
+        me.modes = {
+            SINGLE: true,
+            SIMPLE: true,
+            MULTI: true
+        };
 
         
-        var aw, ah;
-        if(ct.anchorSize){
-            if(typeof ct.anchorSize == 'number'){
-                aw = ct.anchorSize;
-            }else{
-                aw = ct.anchorSize.width;
-                ah = ct.anchorSize.height;
-            }
-        }else{
-            aw = ct.initialConfig.width;
-            ah = ct.initialConfig.height;
-        }
+        me.setSelectionMode(cfg.mode || me.mode);
 
-        var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
-        for(i = 0; i < len; i++){
-            c = cs[i];
-            el = c.getPositionEl();
+        
+        me.selected = Ext.create('Ext.util.MixedCollection');
 
-            
-            if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
-                c.anchor = this.defaultAnchor;
-            }
+        me.callParent(arguments);
+    },
 
-            if(c.anchor){
-                a = c.anchorSpec;
-                if(!a){ 
-                    vs = c.anchor.split(' ');
-                    c.anchorSpec = a = {
-                        right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
-                        bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
-                    };
-                }
-                cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
-                ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
+    
+    bind : function(store, initial){
+        var me = this;
 
-                if(cw || ch){
-                    boxes.push({
-                        comp: c,
-                        width: cw || undefined,
-                        height: ch || undefined
-                    });
-                }
+        if(!initial && me.store){
+            if(store !== me.store && me.store.autoDestroy){
+                me.store.destroyStore();
+            }else{
+                me.store.un("add", me.onStoreAdd, me);
+                me.store.un("clear", me.onStoreClear, me);
+                me.store.un("remove", me.onStoreRemove, me);
+                me.store.un("update", me.onStoreUpdate, me);
             }
         }
-        for (i = 0, len = boxes.length; i < len; i++) {
-            c = boxes[i];
-            c.comp.setSize(c.width, c.height);
+        if(store){
+            store = Ext.data.StoreManager.lookup(store);
+            store.on({
+                add: me.onStoreAdd,
+                clear: me.onStoreClear,
+                remove: me.onStoreRemove,
+                update: me.onStoreUpdate,
+                scope: me
+            });
+        }
+        me.store = store;
+        if(store && !initial) {
+            me.refresh();
         }
     },
 
     
-    parseAnchor : function(a, start, cstart){
-        if(a && a != 'none'){
-            var last;
-            
-            if(this.parseAnchorRE.test(a)){
-                var diff = cstart - start;
-                return function(v){
-                    if(v !== last){
-                        last = v;
-                        return v - diff;
-                    }
-                }
-            
-            }else if(a.indexOf('%') != -1){
-                var ratio = parseFloat(a.replace('%', ''))*.01;
-                return function(v){
-                    if(v !== last){
-                        last = v;
-                        return Math.floor(v*ratio);
-                    }
-                }
-            
-            }else{
-                a = parseInt(a, 10);
-                if(!isNaN(a)){
-                    return function(v){
-                        if(v !== last){
-                            last = v;
-                            return v + a;
-                        }
-                    }
-                }
-            }
+    selectAll: function(suppressEvent) {
+        var me = this,
+            selections = me.store.getRange(),
+            i = 0,
+            len = selections.length,
+            start = me.getSelection().length;
+
+        me.bulkChange = true;
+        for (; i < len; i++) {
+            me.doSelect(selections[i], true, suppressEvent);
         }
-        return false;
+        delete me.bulkChange;
+        
+        me.maybeFireSelectionChange(me.getSelection().length !== start);
     },
 
     
-    adjustWidthAnchor : function(value, comp){
-        return value;
-    },
+    deselectAll: function(suppressEvent) {
+        var me = this,
+            selections = me.getSelection(),
+            i = 0,
+            len = selections.length,
+            start = me.getSelection().length;
 
-    
-    adjustHeightAnchor : function(value, comp){
-        return value;
-    }
+        me.bulkChange = true;
+        for (; i < len; i++) {
+            me.doDeselect(selections[i], suppressEvent);
+        }
+        delete me.bulkChange;
+        
+        me.maybeFireSelectionChange(me.getSelection().length !== start);
+    },
 
     
-});
-Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
-
-Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
     
-    monitorResize:true,
-
-    type: 'column',
-
-    extraCls: 'x-column',
-
-    scrollOffset : 0,
-
     
+    selectWithEvent: function(record, e, keepExisting) {
+        var me = this;
 
-    targetCls: 'x-column-layout-ct',
-
-    isValidParent : function(c, target){
-        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
-    },
-
-    getLayoutTargetSize : function() {
-        var target = this.container.getLayoutTarget(), ret;
-        if (target) {
-            ret = target.getViewSize();
-
-            
-            
-            
-            if (Ext.isIE && Ext.isStrict && ret.width == 0){
-                ret =  target.getStyleSize();
-            }
-
-            ret.width -= target.getPadding('lr');
-            ret.height -= target.getPadding('tb');
-        }
-        return ret;
-    },
-
-    renderAll : function(ct, target) {
-        if(!this.innerCt){
-            
-            
-            this.innerCt = target.createChild({cls:'x-column-inner'});
-            this.innerCt.createChild({cls:'x-clear'});
+        switch (me.selectionMode) {
+            case 'MULTI':
+                if (e.ctrlKey && me.isSelected(record)) {
+                    me.doDeselect(record, false);
+                } else if (e.shiftKey && me.lastFocused) {
+                    me.selectRange(me.lastFocused, record, e.ctrlKey);
+                } else if (e.ctrlKey) {
+                    me.doSelect(record, true, false);
+                } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
+                    me.doSelect(record, keepExisting, false);
+                } else {
+                    me.doSelect(record, false);
+                }
+                break;
+            case 'SIMPLE':
+                if (me.isSelected(record)) {
+                    me.doDeselect(record);
+                } else {
+                    me.doSelect(record, true);
+                }
+                break;
+            case 'SINGLE':
+                
+                if (me.allowDeselect && me.isSelected(record)) {
+                    me.doDeselect(record);
+                
+                } else {
+                    me.doSelect(record, false);
+                }
+                break;
         }
-        Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
     },
 
     
-    onLayout : function(ct, target){
-        var cs = ct.items.items,
-            len = cs.length,
-            c,
+    selectRange : function(startRow, endRow, keepExisting, dir){
+        var me = this,
+            store = me.store,
+            selectedCount = 0,
             i,
-            m,
-            margins = [];
-
-        this.renderAll(ct, target);
+            tmp,
+            dontDeselect,
+            records = [];
 
-        var size = this.getLayoutTargetSize();
-
-        if(size.width < 1 && size.height < 1){ 
+        if (me.isLocked()){
             return;
         }
 
-        var w = size.width - this.scrollOffset,
-            h = size.height,
-            pw = w;
+        if (!keepExisting) {
+            me.deselectAll(true);
+        }
 
-        this.innerCt.setWidth(w);
+        if (!Ext.isNumber(startRow)) {
+            startRow = store.indexOf(startRow);
+        }
+        if (!Ext.isNumber(endRow)) {
+            endRow = store.indexOf(endRow);
+        }
 
         
-        
+        if (startRow > endRow){
+            tmp = endRow;
+            endRow = startRow;
+            startRow = tmp;
+        }
 
-        for(i = 0; i < len; i++){
-            c = cs[i];
-            m = c.getPositionEl().getMargins('lr');
-            margins[i] = m;
-            if(!c.columnWidth){
-                pw -= (c.getWidth() + m);
+        for (i = startRow; i <= endRow; i++) {
+            if (me.isSelected(store.getAt(i))) {
+                selectedCount++;
             }
         }
 
-        pw = pw < 0 ? 0 : pw;
-
-        for(i = 0; i < len; i++){
-            c = cs[i];
-            m = margins[i];
-            if(c.columnWidth){
-                c.setSize(Math.floor(c.columnWidth * pw) - m);
-            }
+        if (!dir) {
+            dontDeselect = -1;
+        } else {
+            dontDeselect = (dir == 'up') ? startRow : endRow;
         }
 
-        
-        
-        if (Ext.isIE) {
-            if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
-                var ts = this.getLayoutTargetSize();
-                if (ts.width != size.width){
-                    this.adjustmentPass = true;
-                    this.onLayout(ct, target);
+        for (i = startRow; i <= endRow; i++){
+            if (selectedCount == (endRow - startRow + 1)) {
+                if (i != dontDeselect) {
+                    me.doDeselect(i, true);
                 }
+            } else {
+                records.push(store.getAt(i));
             }
         }
-        delete this.adjustmentPass;
-    }
+        me.doMultiSelect(records, true);
+    },
 
     
-});
-
-Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
+    select: function(records, keepExisting, suppressEvent) {
+        
+        if (Ext.isDefined(records)) {
+            this.doSelect(records, keepExisting, suppressEvent);
+        }
+    },
 
-Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
     
-    monitorResize:true,
-    
-    rendered : false,
-
-    type: 'border',
-
-    targetCls: 'x-border-layout-ct',
-
-    getLayoutTargetSize : function() {
-        var target = this.container.getLayoutTarget();
-        return target ? target.getViewSize() : {};
+    deselect: function(records, suppressEvent) {
+        this.doDeselect(records, suppressEvent);
     },
 
-    
-    onLayout : function(ct, target){
-        var collapsed, i, c, pos, items = ct.items.items, len = items.length;
-        if(!this.rendered){
-            collapsed = [];
-            for(i = 0; i < len; i++) {
-                c = items[i];
-                pos = c.region;
-                if(c.collapsed){
-                    collapsed.push(c);
-                }
-                c.collapsed = false;
-                if(!c.rendered){
-                    c.render(target, i);
-                    c.getPositionEl().addClass('x-border-panel');
-                }
-                this[pos] = pos != 'center' && c.split ?
-                    new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
-                    new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
-                this[pos].render(target, c);
-            }
-            this.rendered = true;
-        }
+    doSelect: function(records, keepExisting, suppressEvent) {
+        var me = this,
+            record;
 
-        var size = this.getLayoutTargetSize();
-        if(size.width < 20 || size.height < 20){ 
-            if(collapsed){
-                this.restoreCollapsed = collapsed;
-            }
+        if (me.locked) {
             return;
-        }else if(this.restoreCollapsed){
-            collapsed = this.restoreCollapsed;
-            delete this.restoreCollapsed;
-        }
-
-        var w = size.width, h = size.height,
-            centerW = w, centerH = h, centerY = 0, centerX = 0,
-            n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
-            b, m, totalWidth, totalHeight;
-        if(!c && Ext.layout.BorderLayout.WARN !== false){
-            throw 'No center region defined in BorderLayout ' + ct.id;
-        }
-
-        if(n && n.isVisible()){
-            b = n.getSize();
-            m = n.getMargins();
-            b.width = w - (m.left+m.right);
-            b.x = m.left;
-            b.y = m.top;
-            centerY = b.height + b.y + m.bottom;
-            centerH -= centerY;
-            n.applyLayout(b);
-        }
-        if(s && s.isVisible()){
-            b = s.getSize();
-            m = s.getMargins();
-            b.width = w - (m.left+m.right);
-            b.x = m.left;
-            totalHeight = (b.height + m.top + m.bottom);
-            b.y = h - totalHeight + m.top;
-            centerH -= totalHeight;
-            s.applyLayout(b);
-        }
-        if(west && west.isVisible()){
-            b = west.getSize();
-            m = west.getMargins();
-            b.height = centerH - (m.top+m.bottom);
-            b.x = m.left;
-            b.y = centerY + m.top;
-            totalWidth = (b.width + m.left + m.right);
-            centerX += totalWidth;
-            centerW -= totalWidth;
-            west.applyLayout(b);
-        }
-        if(e && e.isVisible()){
-            b = e.getSize();
-            m = e.getMargins();
-            b.height = centerH - (m.top+m.bottom);
-            totalWidth = (b.width + m.left + m.right);
-            b.x = w - totalWidth + m.left;
-            b.y = centerY + m.top;
-            centerW -= totalWidth;
-            e.applyLayout(b);
-        }
-        if(c){
-            m = c.getMargins();
-            var centerBox = {
-                x: centerX + m.left,
-                y: centerY + m.top,
-                width: centerW - (m.left+m.right),
-                height: centerH - (m.top+m.bottom)
-            };
-            c.applyLayout(centerBox);
         }
-        if(collapsed){
-            for(i = 0, len = collapsed.length; i < len; i++){
-                collapsed[i].collapse(false);
-            }
-        }
-        if(Ext.isIE && Ext.isStrict){ 
-            target.repaint();
+        if (typeof records === "number") {
+            records = [me.store.getAt(records)];
         }
-        
-        if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
-            var ts = this.getLayoutTargetSize();
-            if (ts.width != size.width || ts.height != size.height){
-                this.adjustmentPass = true;
-                this.onLayout(ct, target);
-            }
+        if (me.selectionMode == "SINGLE" && records) {
+            record = records.length ? records[0] : records;
+            me.doSingleSelect(record, suppressEvent);
+        } else {
+            me.doMultiSelect(records, keepExisting, suppressEvent);
         }
-        delete this.adjustmentPass;
     },
 
-    destroy: function() {
-        var r = ['north', 'south', 'east', 'west'], i, region;
-        for (i = 0; i < r.length; i++) {
-            region = this[r[i]];
-            if(region){
-                if(region.destroy){
-                    region.destroy();
-                }else if (region.split){
-                    region.split.destroy(true);
-                }
-            }
-        }
-        Ext.layout.BorderLayout.superclass.destroy.call(this);
-    }
+    doMultiSelect: function(records, keepExisting, suppressEvent) {
+        var me = this,
+            selected = me.selected,
+            change = false,
+            i = 0,
+            len, record;
 
-    
-});
+        if (me.locked) {
+            return;
+        }
 
 
-Ext.layout.BorderLayout.Region = function(layout, config, pos){
-    Ext.apply(this, config);
-    this.layout = layout;
-    this.position = pos;
-    this.state = {};
-    if(typeof this.margins == 'string'){
-        this.margins = this.layout.parseMargins(this.margins);
-    }
-    this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
-    if(this.collapsible){
-        if(typeof this.cmargins == 'string'){
-            this.cmargins = this.layout.parseMargins(this.cmargins);
-        }
-        if(this.collapseMode == 'mini' && !this.cmargins){
-            this.cmargins = {left:0,top:0,right:0,bottom:0};
-        }else{
-            this.cmargins = Ext.applyIf(this.cmargins || {},
-                pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
+        records = !Ext.isArray(records) ? [records] : records;
+        len = records.length;
+        if (!keepExisting && selected.getCount() > 0) {
+            if (me.doDeselect(me.getSelection(), suppressEvent) === false) {
+                return;
+            }
+            
         }
-    }
-};
 
-Ext.layout.BorderLayout.Region.prototype = {
-    
-    
-    
-    
-    
-    
-    collapsible : false,
-    
-    split:false,
-    
-    floatable: true,
-    
-    minWidth:50,
-    
-    minHeight:50,
+        function commit () {
+            selected.add(record);
+            change = true;
+        }
 
-    
-    defaultMargins : {left:0,top:0,right:0,bottom:0},
-    
-    defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
-    
-    defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
-    floatingZIndex: 100,
+        for (; i < len; i++) {
+            record = records[i];
+            if (keepExisting && me.isSelected(record)) {
+                continue;
+            }
+            me.lastSelected = record;
 
-    
-    isCollapsed : false,
+            me.onSelectChange(record, true, suppressEvent, commit);
+        }
+        me.setLastFocused(record, suppressEvent);
+        
+        me.maybeFireSelectionChange(change && !suppressEvent);
+    },
 
     
-    
-    
+    doDeselect: function(records, suppressEvent) {
+        var me = this,
+            selected = me.selected,
+            i = 0,
+            len, record,
+            attempted = 0,
+            accepted = 0;
 
-    
-    render : function(ct, p){
-        this.panel = p;
-        p.el.enableDisplayMode();
-        this.targetEl = ct;
-        this.el = p.el;
+        if (me.locked) {
+            return false;
+        }
 
-        var gs = p.getState, ps = this.position;
-        p.getState = function(){
-            return Ext.apply(gs.call(p) || {}, this.state);
-        }.createDelegate(this);
+        if (typeof records === "number") {
+            records = [me.store.getAt(records)];
+        } else if (!Ext.isArray(records)) {
+            records = [records];
+        }
 
-        if(ps != 'center'){
-            p.allowQueuedExpand = false;
-            p.on({
-                beforecollapse: this.beforeCollapse,
-                collapse: this.onCollapse,
-                beforeexpand: this.beforeExpand,
-                expand: this.onExpand,
-                hide: this.onHide,
-                show: this.onShow,
-                scope: this
-            });
-            if(this.collapsible || this.floatable){
-                p.collapseEl = 'el';
-                p.slideAnchor = this.getSlideAnchor();
-            }
-            if(p.tools && p.tools.toggle){
-                p.tools.toggle.addClass('x-tool-collapse-'+ps);
-                p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
-            }
+        function commit () {
+            ++accepted;
+            selected.remove(record);
         }
-    },
 
-    
-    getCollapsedEl : function(){
-        if(!this.collapsedEl){
-            if(!this.toolTemplate){
-                var tt = new Ext.Template(
-                     '<div class="x-tool x-tool-{id}">&#160;</div>'
-                );
-                tt.disableFormats = true;
-                tt.compile();
-                Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
-            }
-            this.collapsedEl = this.targetEl.createChild({
-                cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
-                id: this.panel.id + '-xcollapsed'
-            });
-            this.collapsedEl.enableDisplayMode('block');
+        len = records.length;
 
-            if(this.collapseMode == 'mini'){
-                this.collapsedEl.addClass('x-layout-cmini-'+this.position);
-                this.miniCollapsedEl = this.collapsedEl.createChild({
-                    cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
-                });
-                this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
-                this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
-                this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
-            }else {
-                if(this.collapsible !== false && !this.hideCollapseTool) {
-                    var t = this.expandToolEl = this.toolTemplate.append(
-                            this.collapsedEl.dom,
-                            {id:'expand-'+this.position}, true);
-                    t.addClassOnOver('x-tool-expand-'+this.position+'-over');
-                    t.on('click', this.onExpandClick, this, {stopEvent:true});
-                }
-                if(this.floatable !== false || this.titleCollapse){
-                   this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
-                   this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
+        for (; i < len; i++) {
+            record = records[i];
+            if (me.isSelected(record)) {
+                if (me.lastSelected == record) {
+                    me.lastSelected = selected.last();
                 }
+                ++attempted;
+                me.onSelectChange(record, false, suppressEvent, commit);
             }
         }
-        return this.collapsedEl;
-    },
-
-    
-    onExpandClick : function(e){
-        if(this.isSlid){
-            this.panel.expand(false);
-        }else{
-            this.panel.expand();
-        }
-    },
 
-    
-    onCollapseClick : function(e){
-        this.panel.collapse();
-    },
-
-    
-    beforeCollapse : function(p, animate){
-        this.lastAnim = animate;
-        if(this.splitEl){
-            this.splitEl.hide();
-        }
-        this.getCollapsedEl().show();
-        var el = this.panel.getEl();
-        this.originalZIndex = el.getStyle('z-index');
-        el.setStyle('z-index', 100);
-        this.isCollapsed = true;
-        this.layout.layout();
+        
+        me.maybeFireSelectionChange(accepted > 0 && !suppressEvent);
+        return accepted === attempted;
     },
 
-    
-    onCollapse : function(animate){
-        this.panel.el.setStyle('z-index', 1);
-        if(this.lastAnim === false || this.panel.animCollapse === false){
-            this.getCollapsedEl().dom.style.visibility = 'visible';
-        }else{
-            this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
-        }
-        this.state.collapsed = true;
-        this.panel.saveState();
-    },
+    doSingleSelect: function(record, suppressEvent) {
+        var me = this,
+            changed = false,
+            selected = me.selected;
 
-    
-    beforeExpand : function(animate){
-        if(this.isSlid){
-            this.afterSlideIn();
+        if (me.locked) {
+            return;
         }
-        var c = this.getCollapsedEl();
-        this.el.show();
-        if(this.position == 'east' || this.position == 'west'){
-            this.panel.setSize(undefined, c.getHeight());
-        }else{
-            this.panel.setSize(c.getWidth(), undefined);
+        
+        
+        if (me.isSelected(record)) {
+            return;
         }
-        c.hide();
-        c.dom.style.visibility = 'hidden';
-        this.panel.el.setStyle('z-index', this.floatingZIndex);
-    },
 
-    
-    onExpand : function(){
-        this.isCollapsed = false;
-        if(this.splitEl){
-            this.splitEl.show();
-        }
-        this.layout.layout();
-        this.panel.el.setStyle('z-index', this.originalZIndex);
-        this.state.collapsed = false;
-        this.panel.saveState();
-    },
+        function commit () {
+            me.bulkChange = true;
+            if (selected.getCount() > 0 && me.doDeselect(me.lastSelected, suppressEvent) === false) {
+                delete me.bulkChange;
+                return false;
+            }
+            delete me.bulkChange;
 
-    
-    collapseClick : function(e){
-        if(this.isSlid){
-           e.stopPropagation();
-           this.slideIn();
-        }else{
-           e.stopPropagation();
-           this.slideOut();
+            selected.add(record);
+            me.lastSelected = record;
+            changed = true;
         }
-    },
 
-    
-    onHide : function(){
-        if(this.isCollapsed){
-            this.getCollapsedEl().hide();
-        }else if(this.splitEl){
-            this.splitEl.hide();
-        }
-    },
+        me.onSelectChange(record, true, suppressEvent, commit);
 
-    
-    onShow : function(){
-        if(this.isCollapsed){
-            this.getCollapsedEl().show();
-        }else if(this.splitEl){
-            this.splitEl.show();
+        if (changed) {
+            if (!suppressEvent) {
+                me.setLastFocused(record);
+            }
+            me.maybeFireSelectionChange(!suppressEvent);
         }
     },
 
     
-    isVisible : function(){
-        return !this.panel.hidden;
+    setLastFocused: function(record, supressFocus) {
+        var me = this,
+            recordBeforeLast = me.lastFocused;
+        me.lastFocused = record;
+        me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
     },
 
     
-    getMargins : function(){
-        return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
+    isFocused: function(record) {
+        return record === this.getLastFocused();
     },
 
-    
-    getSize : function(){
-        return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
-    },
 
     
-    setPanel : function(panel){
-        this.panel = panel;
+    
+    maybeFireSelectionChange: function(fireEvent) {
+        var me = this;
+        if (fireEvent && !me.bulkChange) {
+            me.fireEvent('selectionchange', me, me.getSelection());
+        }
     },
 
     
-    getMinWidth: function(){
-        return this.minWidth;
+    getLastSelected: function() {
+        return this.lastSelected;
     },
 
-    
-    getMinHeight: function(){
-        return this.minHeight;
+    getLastFocused: function() {
+        return this.lastFocused;
     },
 
     
-    applyLayoutCollapsed : function(box){
-        var ce = this.getCollapsedEl();
-        ce.setLeftTop(box.x, box.y);
-        ce.setSize(box.width, box.height);
+    getSelection: function() {
+        return this.selected.getRange();
     },
 
     
-    applyLayout : function(box){
-        if(this.isCollapsed){
-            this.applyLayoutCollapsed(box);
-        }else{
-            this.panel.setPosition(box.x, box.y);
-            this.panel.setSize(box.width, box.height);
-        }
+    getSelectionMode: function() {
+        return this.selectionMode;
     },
 
     
-    beforeSlide: function(){
-        this.panel.beforeEffect();
+    setSelectionMode: function(selMode) {
+        selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
+        
+        
+        this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
     },
 
     
-    afterSlide : function(){
-        this.panel.afterEffect();
+    isLocked: function() {
+        return this.locked;
     },
 
     
-    initAutoHide : function(){
-        if(this.autoHide !== false){
-            if(!this.autoHideHd){
-                this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
-                this.autoHideHd = {
-                    "mouseout": function(e){
-                        if(!e.within(this.el, true)){
-                            this.autoHideSlideTask.delay(500);
-                        }
-                    },
-                    "mouseover" : function(e){
-                        this.autoHideSlideTask.cancel();
-                    },
-                    scope : this
-                };
-            }
-            this.el.on(this.autoHideHd);
-            this.collapsedEl.on(this.autoHideHd);
-        }
+    setLocked: function(locked) {
+        this.locked = !!locked;
     },
 
     
-    clearAutoHide : function(){
-        if(this.autoHide !== false){
-            this.el.un("mouseout", this.autoHideHd.mouseout);
-            this.el.un("mouseover", this.autoHideHd.mouseover);
-            this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
-            this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
-        }
+    isSelected: function(record) {
+        record = Ext.isNumber(record) ? this.store.getAt(record) : record;
+        return this.selected.indexOf(record) !== -1;
     },
 
     
-    clearMonitor : function(){
-        Ext.getDoc().un("click", this.slideInIf, this);
+    hasSelection: function() {
+        return this.selected.getCount() > 0;
     },
 
-    
-    slideOut : function(){
-        if(this.isSlid || this.el.hasActiveFx()){
-            return;
-        }
-        this.isSlid = true;
-        var ts = this.panel.tools, dh, pc;
-        if(ts && ts.toggle){
-            ts.toggle.hide();
+    refresh: function() {
+        var me = this,
+            toBeSelected = [],
+            oldSelections = me.getSelection(),
+            len = oldSelections.length,
+            selection,
+            change,
+            i = 0,
+            lastFocused = this.getLastFocused();
+
+        
+        
+        
+        for (; i < len; i++) {
+            selection = oldSelections[i];
+            if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
+                toBeSelected.push(selection);
+            }
         }
-        this.el.show();
 
         
-        pc = this.panel.collapsed;
-        this.panel.collapsed = false;
+        
+        if (me.selected.getCount() != toBeSelected.length) {
+            change = true;
+        }
 
-        if(this.position == 'east' || this.position == 'west'){
-            
-            dh = this.panel.deferHeight;
-            this.panel.deferHeight = false;
+        me.clearSelections();
 
-            this.panel.setSize(undefined, this.collapsedEl.getHeight());
+        if (me.store.indexOf(lastFocused) !== -1) {
+            
+            this.setLastFocused(lastFocused, true);
+        }
 
+        if (toBeSelected.length) {
             
-            this.panel.deferHeight = dh;
-        }else{
-            this.panel.setSize(this.collapsedEl.getWidth(), undefined);
+            me.doSelect(toBeSelected, false, true);
         }
 
-        
-        this.panel.collapsed = pc;
+        me.maybeFireSelectionChange(change);
+    },
 
-        this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
-        this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
-        this.el.setStyle("z-index", this.floatingZIndex+2);
-        this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
-        if(this.animFloat !== false){
-            this.beforeSlide();
-            this.el.slideIn(this.getSlideAnchor(), {
-                callback: function(){
-                    this.afterSlide();
-                    this.initAutoHide();
-                    Ext.getDoc().on("click", this.slideInIf, this);
-                },
-                scope: this,
-                block: true
-            });
-        }else{
-            this.initAutoHide();
-             Ext.getDoc().on("click", this.slideInIf, this);
-        }
+    
+    clearSelections: function() {
+        
+        this.selected.clear();
+        this.lastSelected = null;
+        this.setLastFocused(null);
     },
 
     
-    afterSlideIn : function(){
-        this.clearAutoHide();
-        this.isSlid = false;
-        this.clearMonitor();
-        this.el.setStyle("z-index", "");
-        this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
-        this.el.dom.style.left = this.restoreLT[0];
-        this.el.dom.style.top = this.restoreLT[1];
+    onStoreAdd: function() {
 
-        var ts = this.panel.tools;
-        if(ts && ts.toggle){
-            ts.toggle.show();
-        }
     },
 
     
-    slideIn : function(cb){
-        if(!this.isSlid || this.el.hasActiveFx()){
-            Ext.callback(cb);
-            return;
-        }
-        this.isSlid = false;
-        if(this.animFloat !== false){
-            this.beforeSlide();
-            this.el.slideOut(this.getSlideAnchor(), {
-                callback: function(){
-                    this.el.hide();
-                    this.afterSlide();
-                    this.afterSlideIn();
-                    Ext.callback(cb);
-                },
-                scope: this,
-                block: true
-            });
-        }else{
-            this.el.hide();
-            this.afterSlideIn();
+    
+    onStoreClear: function() {
+        if (this.selected.getCount > 0) {
+            this.clearSelections();
+            this.maybeFireSelectionChange(true);
         }
     },
 
     
-    slideInIf : function(e){
-        if(!e.within(this.el)){
-            this.slideIn();
+    
+    
+    onStoreRemove: function(store, record) {
+        var me = this,
+            selected = me.selected;
+
+        if (me.locked || !me.pruneRemoved) {
+            return;
         }
-    },
 
-    
-    anchors : {
-        "west" : "left",
-        "east" : "right",
-        "north" : "top",
-        "south" : "bottom"
+        if (selected.remove(record)) {
+            if (me.lastSelected == record) {
+                me.lastSelected = null;
+            }
+            if (me.getLastFocused() == record) {
+                me.setLastFocused(null);
+            }
+            me.maybeFireSelectionChange(true);
+        }
     },
 
     
-    sanchors : {
-        "west" : "l",
-        "east" : "r",
-        "north" : "t",
-        "south" : "b"
+    getCount: function() {
+        return this.selected.getCount();
     },
 
     
-    canchors : {
-        "west" : "tl-tr",
-        "east" : "tr-tl",
-        "north" : "tl-bl",
-        "south" : "bl-tl"
+    destroy: function() {
+
     },
 
     
-    getAnchor : function(){
-        return this.anchors[this.position];
+    onStoreUpdate: function() {
+
     },
 
     
-    getCollapseAnchor : function(){
-        return this.canchors[this.position];
+    onSelectChange: function(record, isSelected, suppressEvent) {
+
     },
 
     
-    getSlideAnchor : function(){
-        return this.sanchors[this.position];
+    onLastFocusChanged: function(oldFocused, newFocused) {
+
     },
 
     
-    getAlignAdj : function(){
-        var cm = this.cmargins;
-        switch(this.position){
-            case "west":
-                return [0, 0];
-            break;
-            case "east":
-                return [0, 0];
-            break;
-            case "north":
-                return [0, 0];
-            break;
-            case "south":
-                return [0, 0];
-            break;
-        }
+    onEditorKey: function(field, e) {
+
     },
 
     
-    getExpandAdj : function(){
-        var c = this.collapsedEl, cm = this.cmargins;
-        switch(this.position){
-            case "west":
-                return [-(cm.right+c.getWidth()+cm.left), 0];
-            break;
-            case "east":
-                return [cm.right+c.getWidth()+cm.left, 0];
-            break;
-            case "north":
-                return [0, -(cm.top+cm.bottom+c.getHeight())];
-            break;
-            case "south":
-                return [0, cm.top+cm.bottom+c.getHeight()];
-            break;
-        }
-    },
+    bindComponent: function(cmp) {
 
-    destroy : function(){
-        if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
-            this.autoHideSlideTask.cancel();
-        }
-        Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
     }
-};
+});
 
+Ext.define('Ext.selection.DataViewModel', {
+    extend: 'Ext.selection.Model',
 
-Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
-    Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
-    
-    this.applyLayout = this.applyFns[pos];
-};
+    requires: ['Ext.util.KeyNav'],
 
-Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
-    
-    
-    splitTip : "Drag to resize.",
-    
-    collapsibleSplitTip : "Drag to resize. Double click to hide.",
-    
-    useSplitTips : false,
+    deselectOnContainerClick: true,
 
     
-    splitSettings : {
-        north : {
-            orientation: Ext.SplitBar.VERTICAL,
-            placement: Ext.SplitBar.TOP,
-            maxFn : 'getVMaxSize',
-            minProp: 'minHeight',
-            maxProp: 'maxHeight'
-        },
-        south : {
-            orientation: Ext.SplitBar.VERTICAL,
-            placement: Ext.SplitBar.BOTTOM,
-            maxFn : 'getVMaxSize',
-            minProp: 'minHeight',
-            maxProp: 'maxHeight'
-        },
-        east : {
-            orientation: Ext.SplitBar.HORIZONTAL,
-            placement: Ext.SplitBar.RIGHT,
-            maxFn : 'getHMaxSize',
-            minProp: 'minWidth',
-            maxProp: 'maxWidth'
-        },
-        west : {
-            orientation: Ext.SplitBar.HORIZONTAL,
-            placement: Ext.SplitBar.LEFT,
-            maxFn : 'getHMaxSize',
-            minProp: 'minWidth',
-            maxProp: 'maxWidth'
-        }
-    },
+    enableKeyNav: true,
 
-    
-    applyFns : {
-        west : function(box){
-            if(this.isCollapsed){
-                return this.applyLayoutCollapsed(box);
-            }
-            var sd = this.splitEl.dom, s = sd.style;
-            this.panel.setPosition(box.x, box.y);
-            var sw = sd.offsetWidth;
-            s.left = (box.x+box.width-sw)+'px';
-            s.top = (box.y)+'px';
-            s.height = Math.max(0, box.height)+'px';
-            this.panel.setSize(box.width-sw, box.height);
-        },
-        east : function(box){
-            if(this.isCollapsed){
-                return this.applyLayoutCollapsed(box);
-            }
-            var sd = this.splitEl.dom, s = sd.style;
-            var sw = sd.offsetWidth;
-            this.panel.setPosition(box.x+sw, box.y);
-            s.left = (box.x)+'px';
-            s.top = (box.y)+'px';
-            s.height = Math.max(0, box.height)+'px';
-            this.panel.setSize(box.width-sw, box.height);
-        },
-        north : function(box){
-            if(this.isCollapsed){
-                return this.applyLayoutCollapsed(box);
-            }
-            var sd = this.splitEl.dom, s = sd.style;
-            var sh = sd.offsetHeight;
-            this.panel.setPosition(box.x, box.y);
-            s.left = (box.x)+'px';
-            s.top = (box.y+box.height-sh)+'px';
-            s.width = Math.max(0, box.width)+'px';
-            this.panel.setSize(box.width, box.height-sh);
-        },
-        south : function(box){
-            if(this.isCollapsed){
-                return this.applyLayoutCollapsed(box);
-            }
-            var sd = this.splitEl.dom, s = sd.style;
-            var sh = sd.offsetHeight;
-            this.panel.setPosition(box.x, box.y+sh);
-            s.left = (box.x)+'px';
-            s.top = (box.y)+'px';
-            s.width = Math.max(0, box.width)+'px';
-            this.panel.setSize(box.width, box.height-sh);
-        }
-    },
+    constructor: function(cfg){
+        this.addEvents(
+            
+            'beforedeselect',
 
-    
-    render : function(ct, p){
-        Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
+            
+            'beforeselect',
 
-        var ps = this.position;
+            
+            'deselect',
 
-        this.splitEl = ct.createChild({
-            cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
-            id: this.panel.id + '-xsplit'
-        });
+            
+            'select'
+        );
+        this.callParent(arguments);
+    },
 
-        if(this.collapseMode == 'mini'){
-            this.miniSplitEl = this.splitEl.createChild({
-                cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
-            });
-            this.miniSplitEl.addClassOnOver('x-layout-mini-over');
-            this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
-        }
+    bindComponent: function(view) {
+        var me = this,
+            eventListeners = {
+                refresh: me.refresh,
+                scope: me
+            };
 
-        var s = this.splitSettings[ps];
+        me.view = view;
+        me.bind(view.getStore());
 
-        this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
-        this.split.tickSize = this.tickSize;
-        this.split.placement = s.placement;
-        this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
-        this.split.minSize = this.minSize || this[s.minProp];
-        this.split.on("beforeapply", this.onSplitMove, this);
-        this.split.useShim = this.useShim === true;
-        this.maxSize = this.maxSize || this[s.maxProp];
+        view.on(view.triggerEvent, me.onItemClick, me);
+        view.on(view.triggerCtEvent, me.onContainerClick, me);
 
-        if(p.hidden){
-            this.splitEl.hide();
-        }
+        view.on(eventListeners);
 
-        if(this.useSplitTips){
-            this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
-        }
-        if(this.collapsible){
-            this.splitEl.on("dblclick", this.onCollapseClick,  this);
+        if (me.enableKeyNav) {
+            me.initKeyNav(view);
         }
     },
 
-    
-    getSize : function(){
-        if(this.isCollapsed){
-            return this.collapsedEl.getSize();
-        }
-        var s = this.panel.getSize();
-        if(this.position == 'north' || this.position == 'south'){
-            s.height += this.splitEl.dom.offsetHeight;
-        }else{
-            s.width += this.splitEl.dom.offsetWidth;
-        }
-        return s;
+    onItemClick: function(view, record, item, index, e) {
+        this.selectWithEvent(record, e);
     },
 
-    
-    getHMaxSize : function(){
-         var cmax = this.maxSize || 10000;
-         var center = this.layout.center;
-         return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
+    onContainerClick: function() {
+        if (this.deselectOnContainerClick) {
+            this.deselectAll();
+        }
     },
 
-    
-    getVMaxSize : function(){
-        var cmax = this.maxSize || 10000;
-        var center = this.layout.center;
-        return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
+    initKeyNav: function(view) {
+        var me = this;
+
+        if (!view.rendered) {
+            view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
+            return;
+        }
+
+        view.el.set({
+            tabIndex: -1
+        });
+        me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
+            down: Ext.pass(me.onNavKey, [1], me),
+            right: Ext.pass(me.onNavKey, [1], me),
+            left: Ext.pass(me.onNavKey, [-1], me),
+            up: Ext.pass(me.onNavKey, [-1], me),
+            scope: me
+        });
     },
 
-    
-    onSplitMove : function(split, newSize){
-        var s = this.panel.getSize();
-        this.lastSplitSize = newSize;
-        if(this.position == 'north' || this.position == 'south'){
-            this.panel.setSize(s.width, newSize);
-            this.state.height = newSize;
-        }else{
-            this.panel.setSize(newSize, s.height);
-            this.state.width = newSize;
+    onNavKey: function(step) {
+        step = step || 1;
+        var me = this,
+            view = me.view,
+            selected = me.getSelection()[0],
+            numRecords = me.view.store.getCount(),
+            idx;
+
+        if (selected) {
+            idx = view.indexOf(view.getNode(selected)) + step;
+        } else {
+            idx = 0;
         }
-        this.layout.layout();
-        this.panel.saveState();
-        return false;
+
+        if (idx < 0) {
+            idx = numRecords - 1;
+        } else if (idx >= numRecords) {
+            idx = 0;
+        }
+
+        me.select(idx);
     },
 
     
-    getSplitBar : function(){
-        return this.split;
-    },
+    onSelectChange: function(record, isSelected, suppressEvent, commitFn) {
+        var me = this,
+            view = me.view,
+            eventName = isSelected ? 'select' : 'deselect';
+
+        if ((suppressEvent || me.fireEvent('before' + eventName, me, record)) !== false &&
+                commitFn() !== false) {
+
+            if (isSelected) {
+                view.onItemSelect(record);
+            } else {
+                view.onItemDeselect(record);
+            }
 
+            if (!suppressEvent) {
+                me.fireEvent(eventName, me, record);
+            }
+        }
+    },
     
-    destroy : function() {
-        Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
-        Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
+    destroy: function(){
+        Ext.destroy(this.keyNav);
+        this.callParent();
     }
 });
 
-Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
 
-Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
+Ext.define('Ext.state.CookieProvider', {
+    extend: 'Ext.state.Provider',
 
     
-    labelSeparator : ':',
 
     
 
     
-    trackLabels: false,
-
-    type: 'form',
-
-    onRemove: function(c){
-        Ext.layout.FormLayout.superclass.onRemove.call(this, c);
-        if(this.trackLabels){
-            c.un('show', this.onFieldShow, this);
-            c.un('hide', this.onFieldHide, this);
-        }
-        
-        var el = c.getPositionEl(),
-            ct = c.getItemCt && c.getItemCt();
-        if (c.rendered && ct) {
-            if (el && el.dom) {
-                el.insertAfter(ct);
-            }
-            Ext.destroy(ct);
-            Ext.destroyMembers(c, 'label', 'itemCt');
-            if (c.customItemCt) {
-                Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
-            }
-        }
-    },
 
     
-    setContainer : function(ct){
-        Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
-        if(ct.labelAlign){
-            ct.addClass('x-form-label-'+ct.labelAlign);
-        }
-
-        if(ct.hideLabels){
-            Ext.apply(this, {
-                labelStyle: 'display:none',
-                elementStyle: 'padding-left:0;',
-                labelAdjust: 0
-            });
-        }else{
-            this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
-            ct.labelWidth = ct.labelWidth || 100;
-            if(Ext.isNumber(ct.labelWidth)){
-                var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
-                Ext.apply(this, {
-                    labelAdjust: ct.labelWidth + pad,
-                    labelStyle: 'width:' + ct.labelWidth + 'px;',
-                    elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
-                });
-            }
-            if(ct.labelAlign == 'top'){
-                Ext.apply(this, {
-                    labelStyle: 'width:auto;',
-                    labelAdjust: 0,
-                    elementStyle: 'padding-left:0;'
-                });
-            }
-        }
-    },
 
     
-    isHide: function(c){
-        return c.hideLabel || this.container.hideLabels;
+    constructor : function(config){
+        var me = this;
+        me.path = "/";
+        me.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
+        me.domain = null;
+        me.secure = false;
+        me.callParent(arguments);
+        me.state = me.readCookies();
     },
 
-    onFieldShow: function(c){
-        c.getItemCt().removeClass('x-hide-' + c.hideMode);
+    
+    set : function(name, value){
+        var me = this;
 
-        
-        if (c.isComposite) {
-            c.doLayout();
+        if(typeof value == "undefined" || value === null){
+            me.clear(name);
+            return;
         }
-    },
-
-    onFieldHide: function(c){
-        c.getItemCt().addClass('x-hide-' + c.hideMode);
+        me.setCookie(name, value);
+        me.callParent(arguments);
     },
 
     
-    getLabelStyle: function(s){
-        var ls = '', items = [this.labelStyle, s];
-        for (var i = 0, len = items.length; i < len; ++i){
-            if (items[i]){
-                ls += items[i];
-                if (ls.substr(-1, 1) != ';'){
-                    ls += ';';
-                }
-            }
-        }
-        return ls;
+    clear : function(name){
+        this.clearCookie(name);
+        this.callParent(arguments);
     },
 
     
+    readCookies : function(){
+        var cookies = {},
+            c = document.cookie + ";",
+            re = /\s?(.*?)=(.*?);/g,
+            prefix = this.prefix,
+            len = prefix.length,
+            matches,
+            name,
+            value;
 
-    
-    renderItem : function(c, position, target){
-        if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
-            var args = this.getTemplateArgs(c);
-            if(Ext.isNumber(position)){
-                position = target.dom.childNodes[position] || null;
-            }
-            if(position){
-                c.itemCt = this.fieldTpl.insertBefore(position, args, true);
-            }else{
-                c.itemCt = this.fieldTpl.append(target, args, true);
-            }
-            if(!c.getItemCt){
-                
-                
-                Ext.apply(c, {
-                    getItemCt: function(){
-                        return c.itemCt;
-                    },
-                    customItemCt: true
-                });
-            }
-            c.label = c.getItemCt().child('label.x-form-item-label');
-            if(!c.rendered){
-                c.render('x-form-el-' + c.id);
-            }else if(!this.isValidParent(c, target)){
-                Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
-            }
-            if(this.trackLabels){
-                if(c.hidden){
-                    this.onFieldHide(c);
-                }
-                c.on({
-                    scope: this,
-                    show: this.onFieldShow,
-                    hide: this.onFieldHide
-                });
+        while((matches = re.exec(c)) != null){
+            name = matches[1];
+            value = matches[2];
+            if (name && name.substring(0, len) == prefix){
+                cookies[name.substr(len)] = this.decodeValue(value);
             }
-            this.configureItem(c);
-        }else {
-            Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
         }
+        return cookies;
     },
 
     
-    getTemplateArgs: function(field) {
-        var noLabelSep = !field.fieldLabel || field.hideLabel;
+    setCookie : function(name, value){
+        var me = this;
 
-        return {
-            id            : field.id,
-            label         : field.fieldLabel,
-            itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
-            clearCls      : field.clearCls || 'x-form-clear-left',
-            labelStyle    : this.getLabelStyle(field.labelStyle),
-            elementStyle  : this.elementStyle || '',
-            labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
-        };
+        document.cookie = me.prefix + name + "=" + me.encodeValue(value) +
+           ((me.expires == null) ? "" : ("; expires=" + me.expires.toGMTString())) +
+           ((me.path == null) ? "" : ("; path=" + me.path)) +
+           ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
+           ((me.secure == true) ? "; secure" : "");
     },
 
     
-    adjustWidthAnchor: function(value, c){
-        if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
-            var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
-            return value - this.labelAdjust + (adjust ? -3 : 0);
-        }
-        return value;
-    },
-
-    adjustHeightAnchor : function(value, c){
-        if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
-            return value - c.label.getHeight();
-        }
-        return value;
-    },
+    clearCookie : function(name){
+        var me = this;
 
-    
-    isValidParent : function(c, target){
-        return target && this.container.getEl().contains(c.getPositionEl());
+        document.cookie = me.prefix + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
+           ((me.path == null) ? "" : ("; path=" + me.path)) +
+           ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
+           ((me.secure == true) ? "; secure" : "");
     }
-
-    
 });
 
-Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
 
-Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
-    
-    fill : true,
-    
-    autoWidth : true,
-    
-    titleCollapse : true,
+
+Ext.define('Ext.state.LocalStorageProvider', {
     
-    hideCollapseTool : false,
     
-    collapseFirst : false,
+    extend: 'Ext.state.Provider',
     
-    animate : false,
+    alias: 'state.localstorage',
     
-    sequence : false,
     
-    activeOnTop : false,
-
-    type: 'accordion',
-
-    renderItem : function(c){
-        if(this.animate === false){
-            c.animCollapse = false;
-        }
-        c.collapsible = true;
-        if(this.autoWidth){
-            c.autoWidth = true;
-        }
-        if(this.titleCollapse){
-            c.titleCollapse = true;
-        }
-        if(this.hideCollapseTool){
-            c.hideCollapseTool = true;
-        }
-        if(this.collapseFirst !== undefined){
-            c.collapseFirst = this.collapseFirst;
-        }
-        if(!this.activeItem && !c.collapsed){
-            this.setActiveItem(c, true);
-        }else if(this.activeItem && this.activeItem != c){
-            c.collapsed = true;
-        }
-        Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
-        c.header.addClass('x-accordion-hd');
-        c.on('beforeexpand', this.beforeExpand, this);
-    },
-
-    onRemove: function(c){
-        Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
-        if(c.rendered){
-            c.header.removeClass('x-accordion-hd');
-        }
-        c.un('beforeexpand', this.beforeExpand, this);
+   
+    constructor: function(){
+        var me = this;
+        me.callParent(arguments);
+        me.store = me.getStorageObject();
+        me.state = me.readLocalStorage();
     },
-
     
-    beforeExpand : function(p, anim){
-        var ai = this.activeItem;
-        if(ai){
-            if(this.sequence){
-                delete this.activeItem;
-                if (!ai.collapsed){
-                    ai.collapse({callback:function(){
-                        p.expand(anim || true);
-                    }, scope: this});
-                    return false;
-                }
-            }else{
-                ai.collapse(this.animate);
-            }
-        }
-        this.setActive(p);
-        if(this.activeOnTop){
-            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
+    readLocalStorage: function(){
+        var store = this.store,
+            i = 0,
+            len = store.length,
+            prefix = this.prefix,
+            prefixLen = prefix.length,
+            data = {},
+            key;
+            
+        for (; i < len; ++i) {
+            key = store.key(i);
+            if (key.substring(0, prefixLen) == prefix) {
+                data[key.substr(prefixLen)] = this.decodeValue(store.getItem(key));
+            }            
         }
-        
-        this.layout();
+        return data;
     },
-
     
-    setItemSize : function(item, size){
-        if(this.fill && item){
-            var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
-            
-            for (i = 0; i < len; i++) {
-                if((p = ct[i]) != item && !p.hidden){
-                    hh += p.header.getHeight();
-                }
-            };
-            
-            size.height -= hh;
-            
-            
-            item.setSize(size);
+    set : function(name, value){
+        var me = this;
+        
+        me.clear(name);
+        if (typeof value == "undefined" || value === null) {
+            return;
         }
+        me.store.setItem(me.prefix + name, me.encodeValue(value));
+        me.callParent(arguments);
     },
 
     
-    setActiveItem : function(item){
-        this.setActive(item, true);
+    clear : function(name){
+        this.store.removeItem(this.prefix + name);
+        this.callParent(arguments);
     },
-
     
-    setActive : function(item, expand){
-        var ai = this.activeItem;
-        item = this.container.getComponent(item);
-        if(ai != item){
-            if(item.rendered && item.collapsed && expand){
-                item.expand();
-            }else{
-                if(ai){
-                   ai.fireEvent('deactivate', ai);
-                }
-                this.activeItem = item;
-                item.fireEvent('activate', item);
+    getStorageObject: function(){
+        try {
+            var supports = 'localStorage' in window && window['localStorage'] !== null;
+            if (supports) {
+                return window.localStorage;
             }
+        } catch (e) {
+            return false;
         }
-    }
+    }    
 });
-Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
 
 
-Ext.layout.Accordion = Ext.layout.AccordionLayout;
-Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
-    
+Ext.define('Ext.util.Point', {
 
     
-    monitorResize:false,
-
-    type: 'table',
+    extend: 'Ext.util.Region',
 
-    targetCls: 'x-table-layout-ct',
+    statics: {
 
-    
-    tableAttrs:null,
+        
+        fromEvent: function(e) {
+            e = (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e;
+            return new this(e.pageX, e.pageY);
+        }
+    },
 
     
-    setContainer : function(ct){
-        Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
 
-        this.currentRow = 0;
-        this.currentColumn = 0;
-        this.cells = [];
-    },
-    
     
-    onLayout : function(ct, target){
-        var cs = ct.items.items, len = cs.length, c, i;
-
-        if(!this.table){
-            target.addClass('x-table-layout-ct');
-
-            this.table = target.createChild(
-                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
-        }
-        this.renderAll(ct, target);
+    constructor: function(x, y) {
+        this.callParent([y, x, y, x]);
     },
 
     
-    getRow : function(index){
-        var row = this.table.tBodies[0].childNodes[index];
-        if(!row){
-            row = document.createElement('tr');
-            this.table.tBodies[0].appendChild(row);
-        }
-        return row;
+    toString: function() {
+        return "Point[" + this.x + "," + this.y + "]";
     },
 
     
-    getNextCell : function(c){
-        var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
-        var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
-        for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
-            if(!this.cells[rowIndex]){
-                this.cells[rowIndex] = [];
-            }
-            for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
-                this.cells[rowIndex][colIndex] = true;
-            }
-        }
-        var td = document.createElement('td');
-        if(c.cellId){
-            td.id = c.cellId;
-        }
-        var cls = 'x-table-layout-cell';
-        if(c.cellCls){
-            cls += ' ' + c.cellCls;
-        }
-        td.className = cls;
-        if(c.colspan){
-            td.colSpan = c.colspan;
-        }
-        if(c.rowspan){
-            td.rowSpan = c.rowspan;
-        }
-        this.getRow(curRow).appendChild(td);
-        return td;
+    equals: function(p) {
+        return (this.x == p.x && this.y == p.y);
     },
 
     
-    getNextNonSpan: function(colIndex, rowIndex){
-        var cols = this.columns;
-        while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
-            if(cols && colIndex >= cols){
-                rowIndex++;
-                colIndex = 0;
-            }else{
-                colIndex++;
-            }
+    isWithin: function(p, threshold) {
+        if (!Ext.isObject(threshold)) {
+            threshold = {
+                x: threshold,
+                y: threshold
+            };
         }
-        return [colIndex, rowIndex];
-    },
 
-    
-    renderItem : function(c, position, target){
-        
-        if(!this.table){
-            this.table = target.createChild(
-                Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
-        }
-        if(c && !c.rendered){
-            c.render(this.getNextCell(c));
-            this.configureItem(c, position);
-        }else if(c && !this.isValidParent(c, target)){
-            var container = this.getNextCell(c);
-            container.insertBefore(c.getPositionEl().dom, null);
-            c.container = Ext.get(container);
-            this.configureItem(c, position);
-        }
+        return (this.x <= p.x + threshold.x && this.x >= p.x - threshold.x &&
+                this.y <= p.y + threshold.y && this.y >= p.y - threshold.y);
     },
 
     
-    isValidParent : function(c, target){
-        return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
-    },
-    
-    destroy: function(){
-        delete this.table;
-        Ext.layout.TableLayout.superclass.destroy.call(this);
+    roundedEquals: function(p) {
+        return (Math.round(this.x) == Math.round(p.x) && Math.round(this.y) == Math.round(p.y));
     }
-
+}, function() {
     
+    this.prototype.translate = Ext.util.Region.prototype.translateBy;
 });
 
-Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;
-Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
 
-    extraCls: 'x-abs-layout-item',
 
-    type: 'absolute',
+Ext.define('Ext.LoadMask', {
 
-    onLayout : function(ct, target){
-        target.position();
-        this.paddingLeft = target.getPadding('l');
-        this.paddingTop = target.getPadding('t');
-        Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
-    },
+    extend: 'Ext.Component',
+
+    alias: 'widget.loadmask',
 
     
-    adjustWidthAnchor : function(value, comp){
-        return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
+
+    mixins: {
+        floating: 'Ext.util.Floating'
     },
 
+    uses: ['Ext.data.StoreManager'],
+
     
-    adjustHeightAnchor : function(value, comp){
-        return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
-    }
+
     
-});
-Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
 
-Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
     
-    defaultMargins : {left:0,top:0,right:0,bottom:0},
+    msg : 'Loading...',
     
-    padding : '0',
+    msgCls : Ext.baseCSSPrefix + 'mask-loading',
     
-    pack : 'start',
-
     
-    monitorResize : true,
-    type: 'box',
-    scrollOffset : 0,
-    extraCls : 'x-box-item',
-    targetCls : 'x-box-layout-ct',
-    innerCls : 'x-box-inner',
-
-    constructor : function(config){
-        Ext.layout.BoxLayout.superclass.constructor.call(this, config);
-
-        if (Ext.isString(this.defaultMargins)) {
-            this.defaultMargins = this.parseMargins(this.defaultMargins);
-        }
-    },
+    useMsg: true,
 
     
-    onLayout: function(container, target) {
-        Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
-
-        var items = this.getVisibleItems(container),
-            tSize = this.getLayoutTargetSize();
-
-        
-        this.layoutTargetLastSize = tSize;
-
-        
-        this.childBoxCache = this.calculateChildBoxes(items, tSize);
+    disabled: false,
 
-        this.updateInnerCtSize(tSize, this.childBoxCache);
-        this.updateChildBoxes(this.childBoxCache.boxes);
+    baseCls: Ext.baseCSSPrefix + 'mask-msg',
 
-        
-        this.handleTargetOverflow(tSize, container, target);
-    },
+    renderTpl: '<div style="position:relative" class="{msgCls}"></div>',
 
     
-    updateChildBoxes: function(boxes) {
-        for (var i = 0, length = boxes.length; i < length; i++) {
-            var box  = boxes[i],
-                comp = box.component;
+    modal: true,
 
-            if (box.dirtySize) {
-                comp.setSize(box.width, box.height);
-            }
-            
-            if (isNaN(box.left) || isNaN(box.top)) {
-                continue;
-            }
-            comp.setPosition(box.left, box.top);
-        }
+    
+    floating: {
+        shadow: 'frame'
     },
 
     
-    updateInnerCtSize: Ext.emptyFn,
+    focusOnToFront: false,
 
     
-    handleTargetOverflow: function(previousTargetSize, container, target) {
-        var overflow = target.getStyle('overflow');
+    constructor : function(el, config) {
+        var me = this;
 
-        if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
-            var newTargetSize = this.getLayoutTargetSize();
-            if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
-                this.adjustmentPass = true;
-                this.onLayout(container, target);
-            }
+        
+        if (el.isComponent) {
+            me.ownerCt = el;
+            me.bindComponent(el);
+        }
+        
+        else {
+            me.ownerCt = new Ext.Component({
+                el: Ext.get(el),
+                rendered: true,
+                componentLayoutCounter: 1
+            });
+            me.container = el;
         }
+        me.callParent([config]);
 
-        delete this.adjustmentPass;
+        if (me.store) {
+            me.bindStore(me.store, true);
+        }
+        me.renderData = {
+            msgCls: me.msgCls
+        };
+        me.renderSelectors = {
+            msgEl: 'div'
+        };
     },
 
-    
-    isValidParent : function(c, target){
-        return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
+    bindComponent: function(comp) {
+        this.mon(comp, {
+            resize: this.onComponentResize,
+            scope: this
+        });
     },
 
-    
-    getVisibleItems: function(ct) {
-        var ct  = ct || this.container,
-            t   = ct.getLayoutTarget(),
-            cti = ct.items.items,
-            len = cti.length,
-
-            i, c, items = [];
-
-        for (i = 0; i < len; i++) {
-            if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true){
-                items.push(c);
-            }
-        }
-
-        return items;
+    afterRender: function() {
+        this.callParent(arguments);
+        this.container = this.floatParent.getContentTarget();
     },
 
     
-    renderAll : function(ct, target){
-        if(!this.innerCt){
-            
-            
-            this.innerCt = target.createChild({cls:this.innerCls});
-            this.padding = this.parseMargins(this.padding);
+    onComponentResize: function() {
+        var me = this;
+        if (me.rendered && me.isVisible()) {
+            me.toFront();
+            me.center();
         }
-        Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
     },
 
-    getLayoutTargetSize : function(){
-        var target = this.container.getLayoutTarget(), ret;
-        if (target) {
-            ret = target.getViewSize();
+    
+    bindStore : function(store, initial) {
+        var me = this;
 
-            
-            
-            
-            if (Ext.isIE && Ext.isStrict && ret.width == 0){
-                ret =  target.getStyleSize();
+        if (!initial && me.store) {
+            me.mun(me.store, {
+                scope: me,
+                beforeload: me.onBeforeLoad,
+                load: me.onLoad,
+                exception: me.onLoad
+            });
+            if (!store) {
+                me.store = null;
             }
-
-            ret.width -= target.getPadding('lr');
-            ret.height -= target.getPadding('tb');
         }
-        return ret;
-    },
+        if (store) {
+            store = Ext.data.StoreManager.lookup(store);
+            me.mon(store, {
+                scope: me,
+                beforeload: me.onBeforeLoad,
+                load: me.onLoad,
+                exception: me.onLoad
+            });
 
-    
-    renderItem : function(c){
-        if(Ext.isString(c.margins)){
-            c.margins = this.parseMargins(c.margins);
-        }else if(!c.margins){
-            c.margins = this.defaultMargins;
         }
-        Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
-    }
-});
-
-
-Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
-    
-    align : 'left', 
-    type: 'vbox',
-
-    
-
-    
-
-    
-    updateInnerCtSize: function(tSize, calcs) {
-        var innerCtHeight = tSize.height,
-            innerCtWidth  = calcs.meta.maxWidth + this.padding.left + this.padding.right;
-
-        if (this.align == 'stretch') {
-            innerCtWidth = tSize.width;
-        } else if (this.align == 'center') {
-            innerCtWidth = Math.max(tSize.width, innerCtWidth);
+        me.store = store;
+        if (store && store.isLoading()) {
+            me.onBeforeLoad();
         }
+    },
 
-        
-        
-        this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
+    onDisable : function() {
+        this.callParent(arguments);
+        if (this.loading) {
+            this.onLoad();
+        }
     },
 
     
-    calculateChildBoxes: function(visibleItems, targetSize) {
-        var visibleCount = visibleItems.length,
-
-            padding      = this.padding,
-            topOffset    = padding.top,
-            leftOffset   = padding.left,
-            paddingVert  = topOffset  + padding.bottom,
-            paddingHoriz = leftOffset + padding.right,
-
-            width        = targetSize.width - this.scrollOffset,
-            height       = targetSize.height,
-            availWidth   = Math.max(0, width - paddingHoriz),
-
-            isStart      = this.pack == 'start',
-            isCenter     = this.pack == 'center',
-            isEnd        = this.pack == 'end',
-
-            nonFlexHeight= 0,
-            maxWidth     = 0,
-            totalFlex    = 0,
-
-            
-            boxes        = [],
-
+    onBeforeLoad : function() {
+        var me = this,
+            owner = me.ownerCt || me.floatParent,
+            origin;
+        if (!this.disabled) {
             
-            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth;
-
             
-            for (i = 0; i < visibleCount; i++) {
-                child = visibleItems[i];
-                childHeight = child.height;
-                childWidth  = child.width;
-                canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
-
-
-                
-                if (!Ext.isNumber(childHeight)) {
-
-                    
-                    if (child.flex && !childHeight) {
-                        totalFlex += child.flex;
-
-                    
-                    } else {
-                        
-                        
-                        if (!childHeight && canLayout) {
-                            child.doLayout();
-                        }
-
-                        childSize = child.getSize();
-                        childWidth = childSize.width;
-                        childHeight = childSize.height;
-                    }
-                }
-
-                childMargins = child.margins;
-
-                nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom;
-
+            if (owner.componentLayoutCounter) {
+                Ext.Component.prototype.show.call(me);
+            } else {
                 
-                if (!Ext.isNumber(childWidth)) {
-                    if (canLayout) {
-                        child.doLayout();
+                origin = owner.afterComponentLayout;
+                owner.afterComponentLayout = function() {
+                    owner.afterComponentLayout = origin;
+                    origin.apply(owner, arguments);
+                    if(me.loading) {
+                        Ext.Component.prototype.show.call(me);
                     }
-                    childWidth = child.getWidth();
-                }
-
-                maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
-
-                
-                boxes.push({
-                    component: child,
-                    height   : childHeight || undefined,
-                    width    : childWidth || undefined
-                });
-            }
-
-            
-            var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
-
-            if (isCenter) {
-                topOffset += availableHeight / 2;
-            } else if (isEnd) {
-                topOffset += availableHeight;
+                };
             }
+        }
+    },
 
-            
-            var remainingHeight = availableHeight,
-                remainingFlex   = totalFlex;
+    onHide: function(){
+        var me = this;
+        me.callParent(arguments);
+        me.showOnParentShow = true;
+    },
 
+    onShow: function() {
+        var me = this,
+            msgEl = me.msgEl;
             
-            for (i = 0; i < visibleCount; i++) {
-                child = visibleItems[i];
-                calcs = boxes[i];
-
-                childMargins = child.margins;
-                horizMargins = childMargins.left + childMargins.right;
-
-                topOffset   += childMargins.top;
-
-                if (isStart && child.flex && !child.height) {
-                    flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
-                    remainingHeight -= flexedHeight;
-                    remainingFlex   -= child.flex;
-
-                    calcs.height = flexedHeight;
-                    calcs.dirtySize = true;
-                }
-
-                calcs.left = leftOffset + childMargins.left;
-                calcs.top  = topOffset;
-
-                switch (this.align) {
-                    case 'stretch':
-                        stretchWidth = availWidth - horizMargins;
-                        calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
-                        calcs.dirtySize = true;
-                        break;
-                    case 'stretchmax':
-                        stretchWidth = maxWidth - horizMargins;
-                        calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
-                        calcs.dirtySize = true;
-                        break;
-                    case 'center':
-                        var diff = availWidth - calcs.width - horizMargins;
-                        if (diff > 0) {
-                            calcs.left = leftOffset + horizMargins + (diff / 2);
-                        }
-                }
+        me.callParent(arguments);
+        me.loading = true;
+        if (me.useMsg) {
+            msgEl.show().update(me.msg);
+        } else {
+            msgEl.parent().hide();
+        }
+    },
 
-                topOffset += calcs.height + childMargins.bottom;
-            }
+    afterShow: function() {
+        this.callParent(arguments);
+        this.center();
+    },
 
-        return {
-            boxes: boxes,
-            meta : {
-                maxWidth: maxWidth
-            }
-        };
+    
+    onLoad : function() {
+        this.loading = false;
+        Ext.Component.prototype.hide.call(this);
     }
 });
 
-Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
+Ext.define('Ext.view.AbstractView', {
+    extend: 'Ext.Component',
+    alternateClassName: 'Ext.view.AbstractView',
+    requires: [
+        'Ext.LoadMask',
+        'Ext.data.StoreManager',
+        'Ext.CompositeElementLite',
+        'Ext.DomQuery',
+        'Ext.selection.DataViewModel'
+    ],
+
+    inheritableStatics: {
+        getRecord: function(node) {
+            return this.getBoundView(node).getRecord(node);
+        },
 
+        getBoundView: function(node) {
+            return Ext.getCmp(node.boundView);
+        }
+    },
 
-Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
     
-    align: 'top', 
+    
 
-    type : 'hbox',
+    
+    deferInitialRefresh: true,
 
     
-    updateInnerCtSize: function(tSize, calcs) {
-        var innerCtWidth  = tSize.width,
-            innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom;
 
-        if (this.align == 'stretch') {
-            innerCtHeight = tSize.height;
-        } else if (this.align == 'middle') {
-            innerCtHeight = Math.max(tSize.height, innerCtHeight);
-        }
+    
+    itemCls: Ext.baseCSSPrefix + 'dataview-item',
 
-        this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
-    },
+    
 
     
+
     
+    loadingText: 'Loading...',
 
     
-    calculateChildBoxes: function(visibleItems, targetSize) {
-        var visibleCount = visibleItems.length,
+    loadMask: true,
 
-            padding      = this.padding,
-            topOffset    = padding.top,
-            leftOffset   = padding.left,
-            paddingVert  = topOffset  + padding.bottom,
-            paddingHoriz = leftOffset + padding.right,
+    
 
-            width        = targetSize.width - this.scrollOffset,
-            height       = targetSize.height,
-            availHeight  = Math.max(0, height - paddingVert),
+    
+    loadingUseMsg: true,
 
-            isStart      = this.pack == 'start',
-            isCenter     = this.pack == 'center',
-            isEnd        = this.pack == 'end',
-            
 
-            nonFlexWidth = 0,
-            maxHeight    = 0,
-            totalFlex    = 0,
+    
 
-            
-            boxes        = [],
+    
+    selectedItemCls: Ext.baseCSSPrefix + 'item-selected',
 
-            
-            child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight;
+    
+    emptyText: "",
 
-            
-            for (i = 0; i < visibleCount; i++) {
-                child       = visibleItems[i];
-                childHeight = child.height;
-                childWidth  = child.width;
-                canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
+    
+    deferEmptyText: true,
 
-                
-                if (!Ext.isNumber(childWidth)) {
+    
+    trackOver: false,
 
-                    
-                    if (child.flex && !childWidth) {
-                        totalFlex += child.flex;
+    
+    blockRefresh: false,
 
-                    
-                    } else {
-                        
-                        
-                        if (!childWidth && canLayout) {
-                            child.doLayout();
-                        }
+    
 
-                        childSize   = child.getSize();
-                        childWidth  = childSize.width;
-                        childHeight = childSize.height;
-                    }
-                }
 
-                childMargins = child.margins;
+    
+    last: false,
 
-                nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right;
+    triggerEvent: 'itemclick',
+    triggerCtEvent: 'containerclick',
 
-                
-                if (!Ext.isNumber(childHeight)) {
-                    if (canLayout) {
-                        child.doLayout();
-                    }
-                    childHeight = child.getHeight();
-                }
+    addCmpEvents: function() {
+
+    },
 
-                maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
+    
+    initComponent : function(){
+        var me = this,
+            isDef = Ext.isDefined,
+            itemTpl = me.itemTpl,
+            memberFn = {};
 
+        if (itemTpl) {
+            if (Ext.isArray(itemTpl)) {
                 
-                boxes.push({
-                    component: child,
-                    height   : childHeight || undefined,
-                    width    : childWidth || undefined
-                });
+                itemTpl = itemTpl.join('');
+            } else if (Ext.isObject(itemTpl)) {
+                
+                memberFn = Ext.apply(memberFn, itemTpl.initialConfig);
+                itemTpl = itemTpl.html;
             }
 
-            
-            var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz));
-
-            if (isCenter) {
-                leftOffset += availableWidth / 2;
-            } else if (isEnd) {
-                leftOffset += availableWidth;
+            if (!me.itemSelector) {
+                me.itemSelector = '.' + me.itemCls;
             }
 
-            
-            var remainingWidth = availableWidth,
-                remainingFlex  = totalFlex;
-
-            
-            for (i = 0; i < visibleCount; i++) {
-                child = visibleItems[i];
-                calcs = boxes[i];
+            itemTpl = Ext.String.format('<tpl for="."><div class="{0}">{1}</div></tpl>', me.itemCls, itemTpl);
+            me.tpl = Ext.create('Ext.XTemplate', itemTpl, memberFn);
+        }
 
-                childMargins = child.margins;
-                vertMargins  = childMargins.top + childMargins.bottom;
 
-                leftOffset  += childMargins.left;
+        me.callParent();
+        if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
+            me.tpl = Ext.create('Ext.XTemplate', me.tpl);
+        }
 
-                if (isStart && child.flex && !child.width) {
-                    flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
-                    remainingWidth -= flexedWidth;
-                    remainingFlex  -= child.flex;
 
-                    calcs.width = flexedWidth;
-                    calcs.dirtySize = true;
-                }
+        me.addEvents(
+            
+            'beforerefresh',
+            
+            'refresh',
+            
+            'viewready',
+            
+            'itemupdate',
+            
+            'itemadd',
+            
+            'itemremove'
+        );
 
-                calcs.left = leftOffset;
-                calcs.top  = topOffset + childMargins.top;
+        me.addCmpEvents();
 
-                switch (this.align) {
-                    case 'stretch':
-                        stretchHeight = availHeight - vertMargins;
-                        calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
-                        calcs.dirtySize = true;
-                        break;
-                    case 'stretchmax':
-                        stretchHeight = maxHeight - vertMargins;
-                        calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
-                        calcs.dirtySize = true;
-                        break;
-                    case 'middle':
-                        var diff = availHeight - calcs.height - vertMargins;
-                        if (diff > 0) {
-                            calcs.top = topOffset + vertMargins + (diff / 2);
-                        }
-                }
-                leftOffset += calcs.width + childMargins.right;
-            }
+        
+        me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
+        me.all = new Ext.CompositeElementLite();
+    },
 
-        return {
-            boxes: boxes,
-            meta : {
-                maxHeight: maxHeight
-            }
-        };
-    }
-});
+    onRender: function() {
+        var me = this,
+            mask = me.loadMask,
+            cfg = {
+                msg: me.loadingText,
+                msgCls: me.loadingCls,
+                useMsg: me.loadingUseMsg
+            };
 
-Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
+        me.callParent(arguments);
 
-Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
-    monitorResize : true,
+        if (mask) {
+            
+            if (Ext.isObject(mask)) {
+                cfg = Ext.apply(cfg, mask);
+            }
+            
+            
+            
+            
+            me.loadMask = Ext.create('Ext.LoadMask', me, cfg);
+            me.loadMask.on({
+                scope: me,
+                beforeshow: me.onMaskBeforeShow,
+                hide: me.onMaskHide
+            });
+        }
+    },
 
-    type: 'toolbar',
+    onMaskBeforeShow: function(){
+        var loadingHeight = this.loadingHeight;
+        
+        this.getSelectionModel().deselectAll();
+        if (loadingHeight) {
+            this.setCalculatedSize(undefined, loadingHeight);
+        }
+    },
 
-    
-    triggerWidth: 18,
+    onMaskHide: function(){
+        var me = this;
+        
+        if (!me.destroying && me.loadingHeight) {
+            me.setHeight(me.height);
+        }
+    },
 
-    
-    noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
+    afterRender: function() {
+        this.callParent(arguments);
 
-    
-    lastOverflow: false,
+        
+        
+        
+        this.getSelectionModel().bindComponent(this);
+    },
 
     
-    tableHTML: [
-        '<table cellspacing="0" class="x-toolbar-ct">',
-            '<tbody>',
-                '<tr>',
-                    '<td class="x-toolbar-left" align="{0}">',
-                        '<table cellspacing="0">',
-                            '<tbody>',
-                                '<tr class="x-toolbar-left-row"></tr>',
-                            '</tbody>',
-                        '</table>',
-                    '</td>',
-                    '<td class="x-toolbar-right" align="right">',
-                        '<table cellspacing="0" class="x-toolbar-right-ct">',
-                            '<tbody>',
-                                '<tr>',
-                                    '<td>',
-                                        '<table cellspacing="0">',
-                                            '<tbody>',
-                                                '<tr class="x-toolbar-right-row"></tr>',
-                                            '</tbody>',
-                                        '</table>',
-                                    '</td>',
-                                    '<td>',
-                                        '<table cellspacing="0">',
-                                            '<tbody>',
-                                                '<tr class="x-toolbar-extras-row"></tr>',
-                                            '</tbody>',
-                                        '</table>',
-                                    '</td>',
-                                '</tr>',
-                            '</tbody>',
-                        '</table>',
-                    '</td>',
-                '</tr>',
-            '</tbody>',
-        '</table>'
-    ].join(""),
+    getSelectionModel: function(){
+        var me = this,
+            mode = 'SINGLE';
 
-    
-    onLayout : function(ct, target) {
-        
-        if (!this.leftTr) {
-            var align = ct.buttonAlign == 'center' ? 'center' : 'left';
+        if (!me.selModel) {
+            me.selModel = {};
+        }
 
-            target.addClass('x-toolbar-layout-ct');
-            target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
+        if (me.simpleSelect) {
+            mode = 'SIMPLE';
+        } else if (me.multiSelect) {
+            mode = 'MULTI';
+        }
 
-            this.leftTr   = target.child('tr.x-toolbar-left-row', true);
-            this.rightTr  = target.child('tr.x-toolbar-right-row', true);
-            this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
+        Ext.applyIf(me.selModel, {
+            allowDeselect: me.allowDeselect,
+            mode: mode
+        });
 
-            if (this.hiddenItem == undefined) {
-                
-                this.hiddenItems = [];
-            }
+        if (!me.selModel.events) {
+            me.selModel = Ext.create('Ext.selection.DataViewModel', me.selModel);
         }
 
-        var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
-            items    = ct.items.items,
-            position = 0;
+        if (!me.selModel.hasRelaySetup) {
+            me.relayEvents(me.selModel, [
+                'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
+            ]);
+            me.selModel.hasRelaySetup = true;
+        }
 
         
-        for (var i = 0, len = items.length, c; i < len; i++, position++) {
-            c = items[i];
-
-            if (c.isFill) {
-                side   = this.rightTr;
-                position = -1;
-            } else if (!c.rendered) {
-                c.render(this.insertCell(c, side, position));
-            } else {
-                if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
-                    var td = this.insertCell(c, side, position);
-                    td.appendChild(c.getPositionEl().dom);
-                    c.container = Ext.get(td);
-                }
-            }
+        
+        if (me.disableSelection) {
+            me.selModel.locked = true;
         }
 
-        
-        this.cleanup(this.leftTr);
-        this.cleanup(this.rightTr);
-        this.cleanup(this.extrasTr);
-        this.fitToSize(target);
+        return me.selModel;
     },
 
     
-    cleanup : function(el) {
-        var cn = el.childNodes, i, c;
+    refresh: function() {
+        var me = this,
+            el,
+            records;
+
+        if (!me.rendered || me.isDestroyed) {
+            return;
+        }
 
-        for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
-            if (!c.firstChild) {
-                el.removeChild(c);
+        me.fireEvent('beforerefresh', me);
+        el = me.getTargetEl();
+        records = me.store.getRange();
+
+        el.update('');
+        if (records.length < 1) {
+            if (!me.deferEmptyText || me.hasSkippedEmptyText) {
+                el.update(me.emptyText);
             }
+            me.all.clear();
+        } else {
+            me.tpl.overwrite(el, me.collectData(records, 0));
+            me.all.fill(Ext.query(me.getItemSelector(), el.dom));
+            me.updateIndexes(0);
         }
-    },
 
-    
-    insertCell : function(c, target, position) {
-        var td = document.createElement('td');
-        td.className = 'x-toolbar-cell';
+        me.selModel.refresh();
+        me.hasSkippedEmptyText = true;
+        me.fireEvent('refresh', me);
 
-        target.insertBefore(td, target.childNodes[position] || null);
+        
+        
+        if (!me.viewReady) {
+            
+            
+            me.viewReady = true;
+            me.fireEvent('viewready', me);
+        }
+    },
 
-        return td;
+    
+    prepareData: function(data, index, record) {
+        if (record) {
+            Ext.apply(data, record.getAssociatedData());
+        }
+        return data;
     },
 
     
-    hideItem : function(item) {
-        this.hiddenItems.push(item);
+    collectData : function(records, startIndex){
+        var r = [],
+            i = 0,
+            len = records.length,
+            record;
 
-        item.xtbHidden = true;
-        item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
-        item.hide();
+        for(; i < len; i++){
+            record = records[i];
+            r[r.length] = this.prepareData(record[record.persistenceProperty], startIndex + i, record);
+        }
+        return r;
     },
 
     
-    unhideItem : function(item) {
-        item.show();
-        item.xtbHidden = false;
-        this.hiddenItems.remove(item);
+    bufferRender : function(records, index){
+        var div = document.createElement('div');
+        this.tpl.overwrite(div, this.collectData(records, index));
+        return Ext.query(this.getItemSelector(), div);
     },
 
     
-    getItemWidth : function(c) {
-        return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
+    onUpdate : function(ds, record){
+        var me = this,
+            index = me.store.indexOf(record),
+            node;
+
+        if (index > -1){
+            node = me.bufferRender([record], index)[0];
+            
+            if (me.getNode(record)) {
+                me.all.replaceElement(index, node, true);
+                me.updateIndexes(index, index);
+                
+                
+                me.selModel.refresh();
+                me.fireEvent('itemupdate', record, index, node);
+            }
+        }
+
     },
 
     
-    fitToSize : function(target) {
-        if (this.container.enableOverflow === false) {
+    onAdd : function(ds, records, index) {
+        var me = this,
+            nodes;
+
+        if (me.all.getCount() === 0) {
+            me.refresh();
             return;
         }
 
-        var width       = target.dom.clientWidth,
-            tableWidth  = target.dom.firstChild.offsetWidth,
-            clipWidth   = width - this.triggerWidth,
-            lastWidth   = this.lastWidth || 0,
+        nodes = me.bufferRender(records, index);
+        me.doAdd(nodes, records, index);
 
-            hiddenItems = this.hiddenItems,
-            hasHiddens  = hiddenItems.length != 0,
-            isLarger    = width >= lastWidth;
+        me.selModel.refresh();
+        me.updateIndexes(index);
+        me.fireEvent('itemadd', records, index, nodes);
+    },
 
-        this.lastWidth  = width;
+    doAdd: function(nodes, records, index) {
+        var all = this.all;
 
-        if (tableWidth > width || (hasHiddens && isLarger)) {
-            var items     = this.container.items.items,
-                len       = items.length,
-                loopWidth = 0,
-                item;
+        if (index < all.getCount()) {
+            all.item(index).insertSibling(nodes, 'before', true);
+        } else {
+            all.last().insertSibling(nodes, 'after', true);
+        }
 
-            for (var i = 0; i < len; i++) {
-                item = items[i];
+        Ext.Array.insert(all.elements, index, nodes);
+    },
 
-                if (!item.isFill) {
-                    loopWidth += this.getItemWidth(item);
-                    if (loopWidth > clipWidth) {
-                        if (!(item.hidden || item.xtbHidden)) {
-                            this.hideItem(item);
-                        }
-                    } else if (item.xtbHidden) {
-                        this.unhideItem(item);
-                    }
-                }
-            }
-        }
+    
+    onRemove : function(ds, record, index) {
+        var me = this;
 
-        
-        hasHiddens = hiddenItems.length != 0;
+        me.doRemove(record, index);
+        me.updateIndexes(index);
+        if (me.store.getCount() === 0){
+            me.refresh();
+        }
+        me.fireEvent('itemremove', record, index);
+    },
 
-        if (hasHiddens) {
-            this.initMore();
+    doRemove: function(record, index) {
+        this.all.removeElement(index, true);
+    },
 
-            if (!this.lastOverflow) {
-                this.container.fireEvent('overflowchange', this.container, true);
-                this.lastOverflow = true;
-            }
-        } else if (this.more) {
-            this.clearMenu();
-            this.more.destroy();
-            delete this.more;
+    
+    refreshNode : function(index){
+        this.onUpdate(this.store, this.store.getAt(index));
+    },
 
-            if (this.lastOverflow) {
-                this.container.fireEvent('overflowchange', this.container, false);
-                this.lastOverflow = false;
+    
+    updateIndexes : function(startIndex, endIndex) {
+        var ns = this.all.elements,
+            records = this.store.getRange(),
+            i;
+            
+        startIndex = startIndex || 0;
+        endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
+        for(i = startIndex; i <= endIndex; i++){
+            ns[i].viewIndex = i;
+            ns[i].viewRecordId = records[i].internalId;
+            if (!ns[i].boundView) {
+                ns[i].boundView = this.id;
             }
         }
     },
 
     
-    createMenuConfig : function(component, hideOnClick){
-        var config = Ext.apply({}, component.initialConfig),
-            group  = component.toggleGroup;
-
-        Ext.copyTo(config, component, [
-            'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
-        ]);
+    getStore : function(){
+        return this.store;
+    },
 
-        Ext.apply(config, {
-            text       : component.overflowText || component.text,
-            hideOnClick: hideOnClick
-        });
+    
+    bindStore : function(store, initial) {
+        var me = this,
+            maskStore;
 
-        if (group || component.enableToggle) {
-            Ext.apply(config, {
-                group  : group,
-                checked: component.pressed,
-                listeners: {
-                    checkchange: function(item, checked){
-                        component.toggle(checked);
-                    }
+        if (!initial && me.store) {
+            if (store !== me.store && me.store.autoDestroy) {
+                me.store.destroyStore();
+            }
+            else {
+                me.mun(me.store, {
+                    scope: me,
+                    datachanged: me.onDataChanged,
+                    add: me.onAdd,
+                    remove: me.onRemove,
+                    update: me.onUpdate,
+                    clear: me.refresh
+                });
+            }
+            if (!store) {
+                
+                if (me.loadMask && me.loadMask.bindStore) {
+                    me.loadMask.bindStore(null);
                 }
+                me.store = null;
+            }
+        }
+        if (store) {
+            store = Ext.data.StoreManager.lookup(store);
+            me.mon(store, {
+                scope: me,
+                datachanged: me.onDataChanged,
+                add: me.onAdd,
+                remove: me.onRemove,
+                update: me.onUpdate,
+                clear: me.refresh
             });
+            
+            if (me.loadMask && me.loadMask.bindStore) {
+                
+                if (Ext.Array.contains(store.alias, 'store.node')) {
+                    maskStore = this.ownerCt.store;
+                } else {
+                    maskStore = store;
+                }
+                me.loadMask.bindStore(maskStore);
+            }
         }
 
-        delete config.ownerCt;
-        delete config.xtype;
-        delete config.id;
-
-        return config;
-    },
-
-    
-    addComponentToMenu : function(menu, component) {
-        if (component instanceof Ext.Toolbar.Separator) {
-            menu.add('-');
-
-        } else if (Ext.isFunction(component.isXType)) {
-            if (component.isXType('splitbutton')) {
-                menu.add(this.createMenuConfig(component, true));
+        
+        
+        me.viewReady = false;
 
-            } else if (component.isXType('button')) {
-                menu.add(this.createMenuConfig(component, !component.menu));
+        me.store = store;
+        
+        me.getSelectionModel().bind(store);
 
-            } else if (component.isXType('buttongroup')) {
-                component.items.each(function(item){
-                     this.addComponentToMenu(menu, item);
-                }, this);
+        
+        if (store) {
+            if (initial && me.deferInitialRefresh) {
+                Ext.Function.defer(function () {
+                    if (!me.isDestroyed) {
+                        me.refresh(true);
+                    }
+                }, 1);
+            } else {
+                me.refresh(true);
             }
         }
     },
 
     
-    clearMenu : function(){
-        var menu = this.moreMenu;
-        if (menu && menu.items) {
-            menu.items.each(function(item){
-                delete item.menu;
-            });
+    onDataChanged: function() {
+        if (this.blockRefresh !== true) {
+            this.refresh.apply(this, arguments);
         }
     },
 
     
-    beforeMoreShow : function(menu) {
-        var items = this.container.items.items,
-            len   = items.length,
-            item,
-            prev;
+    findItemByChild: function(node){
+        return Ext.fly(node).findParent(this.getItemSelector(), this.getTargetEl());
+    },
 
-        var needsSep = function(group, item){
-            return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
-        };
+    
+    findTargetByEvent: function(e) {
+        return e.getTarget(this.getItemSelector(), this.getTargetEl());
+    },
 
-        this.clearMenu();
-        menu.removeAll();
-        for (var i = 0; i < len; i++) {
-            item = items[i];
-            if (item.xtbHidden) {
-                if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
-                    menu.add('-');
-                }
-                this.addComponentToMenu(menu, item);
-                prev = item;
-            }
-        }
 
-        
-        if (menu.items.length < 1) {
-            menu.add(this.noItemsMenuText);
+    
+    getSelectedNodes: function(){
+        var nodes   = [],
+            records = this.selModel.getSelection(),
+            ln = records.length,
+            i  = 0;
+
+        for (; i < ln; i++) {
+            nodes.push(this.getNode(records[i]));
         }
+
+        return nodes;
     },
 
     
-    initMore : function(){
-        if (!this.more) {
-            
-            this.moreMenu = new Ext.menu.Menu({
-                ownerCt : this.container,
-                listeners: {
-                    beforeshow: this.beforeMoreShow,
-                    scope: this
-                }
-            });
-
-            
-            this.more = new Ext.Button({
-                iconCls: 'x-toolbar-more-icon',
-                cls    : 'x-toolbar-more',
-                menu   : this.moreMenu,
-                ownerCt: this.container
-            });
+    getRecords: function(nodes) {
+        var records = [],
+            i = 0,
+            len = nodes.length,
+            data = this.store.data;
 
-            var td = this.insertCell(this.more, this.extrasTr, 100);
-            this.more.render(td);
+        for (; i < len; i++) {
+            records[records.length] = data.getByKey(nodes[i].viewRecordId);
         }
-    },
-
-    destroy : function(){
-        Ext.destroy(this.more, this.moreMenu);
-        delete this.leftTr;
-        delete this.rightTr;
-        delete this.extrasTr;
-        Ext.layout.ToolbarLayout.superclass.destroy.call(this);
-    }
-});
 
-Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
+        return records;
+    },
 
- Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
-    monitorResize : true,
+    
+    getRecord: function(node){
+        return this.store.data.getByKey(Ext.getDom(node).viewRecordId);
+    },
 
-    type: 'menu',
 
-    setContainer : function(ct){
-        this.monitorResize = !ct.floating;
-        
+    
+    isSelected : function(node) {
         
-        ct.on('autosize', this.doAutoSize, this);
-        Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
+        var r = this.getRecord(node);
+        return this.selModel.isSelected(r);
     },
 
-    renderItem : function(c, position, target){
-        if (!this.itemTpl) {
-            this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
-                '<li id="{itemId}" class="{itemCls}">',
-                    '<tpl if="needsIcon">',
-                        '<img src="{icon}" class="{iconCls}"/>',
-                    '</tpl>',
-                '</li>'
-            );
-        }
-
-        if(c && !c.rendered){
-            if(Ext.isNumber(position)){
-                position = target.dom.childNodes[position];
-            }
-            var a = this.getItemArgs(c);
+    
+    select: function(records, keepExisting, suppressEvent) {
+        this.selModel.select(records, keepExisting, suppressEvent);
+    },
 
+    
+    deselect: function(records, suppressEvent) {
+        this.selModel.deselect(records, suppressEvent);
+    },
 
-            c.render(c.positionEl = position ?
-                this.itemTpl.insertBefore(position, a, true) :
-                this.itemTpl.append(target, a, true));
+    
+    getNode : function(nodeInfo) {
+        if (!this.rendered) {
+            return null;
+        }
+        if (Ext.isString(nodeInfo)) {
+            return document.getElementById(nodeInfo);
+        }
+        if (Ext.isNumber(nodeInfo)) {
+            return this.all.elements[nodeInfo];
+        }
+        if (nodeInfo instanceof Ext.data.Model) {
+            return this.getNodeByRecord(nodeInfo);
+        }
+        return nodeInfo; 
+    },
 
+    
+    getNodeByRecord: function(record) {
+        var ns = this.all.elements,
+            ln = ns.length,
+            i = 0;
 
-            c.positionEl.menuItemId = c.getItemId();
+        for (; i < ln; i++) {
+            if (ns[i].viewRecordId === record.internalId) {
+                return ns[i];
+            }
+        }
 
+        return null;
+    },
 
+    
+    getNodes: function(start, end) {
+        var ns = this.all.elements,
+            nodes = [],
+            i;
 
-            if (!a.isMenuItem && a.needsIcon) {
-                c.positionEl.addClass('x-menu-list-item-indent');
+        start = start || 0;
+        end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
+        if (start <= end) {
+            for (i = start; i <= end && ns[i]; i++) {
+                nodes.push(ns[i]);
             }
-            this.configureItem(c, position);
-        }else if(c && !this.isValidParent(c, target)){
-            if(Ext.isNumber(position)){
-                position = target.dom.childNodes[position];
+        } else {
+            for (i = start; i >= end && ns[i]; i--) {
+                nodes.push(ns[i]);
             }
-            target.dom.insertBefore(c.getActionEl().dom, position || null);
         }
-    },
-
-    getItemArgs : function(c) {
-        var isMenuItem = c instanceof Ext.menu.Item;
-        return {
-            isMenuItem: isMenuItem,
-            needsIcon: !isMenuItem && (c.icon || c.iconCls),
-            icon: c.icon || Ext.BLANK_IMAGE_URL,
-            iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
-            itemId: 'x-menu-el-' + c.id,
-            itemCls: 'x-menu-list-item '
-        };
+        return nodes;
     },
 
     
-    isValidParent : function(c, target) {
-        return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
+    indexOf: function(node) {
+        node = this.getNode(node);
+        if (Ext.isNumber(node.viewIndex)) {
+            return node.viewIndex;
+        }
+        return this.all.indexOf(node);
     },
 
-    onLayout : function(ct, target){
-        Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
-        this.doAutoSize();
+    onDestroy : function() {
+        var me = this;
+
+        me.all.clear();
+        me.callParent();
+        me.bindStore(null);
+        me.selModel.destroy();
     },
 
-    doAutoSize : function(){
-        var ct = this.container, w = ct.width;
-        if(ct.floating){
-            if(w){
-                ct.setWidth(w);
-            }else if(Ext.isIE){
-                ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
-                var el = ct.getEl(), t = el.dom.offsetWidth; 
-                ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
-            }
+    
+    onItemSelect: function(record) {
+        var node = this.getNode(record);
+        
+        if (node) {
+            Ext.fly(node).addCls(this.selectedItemCls);
         }
-    }
-});
-Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
+    },
 
-Ext.Viewport = Ext.extend(Ext.Container, {
-    
-    
-    
-    
-    
-    
-    
     
+    onItemDeselect: function(record) {
+        var node = this.getNode(record);
+        
+        if (node) {
+            Ext.fly(node).removeCls(this.selectedItemCls);
+        }
+    },
+
+    getItemSelector: function() {
+        return this.itemSelector;
+    }
+}, function() {
     
     
     
     
+    Ext.deprecate('extjs', '4.0', function() {
+        Ext.view.AbstractView.override({
+            
+            
+            
 
-    initComponent : function() {
-        Ext.Viewport.superclass.initComponent.call(this);
-        document.getElementsByTagName('html')[0].className += ' x-viewport';
-        this.el = Ext.getBody();
-        this.el.setHeight = Ext.emptyFn;
-        this.el.setWidth = Ext.emptyFn;
-        this.el.setSize = Ext.emptyFn;
-        this.el.dom.scroll = 'no';
-        this.allowDomMove = false;
-        this.autoWidth = true;
-        this.autoHeight = true;
-        Ext.EventManager.onWindowResize(this.fireResize, this);
-        this.renderTo = this.el;
-    },
+            
+            getSelectionCount : function(){
+                if (Ext.global.console) {
+                    Ext.global.console.warn("DataView: getSelectionCount will be removed, please interact with the Ext.selection.DataViewModel");
+                }
+                return this.selModel.getSelection().length;
+            },
 
-    fireResize : function(w, h){
-        this.fireEvent('resize', this, w, h, w, h);
-    }
+            
+            getSelectedRecords : function(){
+                if (Ext.global.console) {
+                    Ext.global.console.warn("DataView: getSelectedRecords will be removed, please interact with the Ext.selection.DataViewModel");
+                }
+                return this.selModel.getSelection();
+            },
+
+            select: function(records, keepExisting, supressEvents) {
+                if (Ext.global.console) {
+                    Ext.global.console.warn("DataView: select will be removed, please access select through a DataView's SelectionModel, ie: view.getSelectionModel().select()");
+                }
+                var sm = this.getSelectionModel();
+                return sm.select.apply(sm, arguments);
+            },
+
+            clearSelections: function() {
+                if (Ext.global.console) {
+                    Ext.global.console.warn("DataView: clearSelections will be removed, please access deselectAll through DataView's SelectionModel, ie: view.getSelectionModel().deselectAll()");
+                }
+                var sm = this.getSelectionModel();
+                return sm.deselectAll();
+            }
+        });
+    });
 });
-Ext.reg('viewport', Ext.Viewport);
 
-Ext.Panel = Ext.extend(Ext.Container, {
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+
+Ext.define('Ext.Action', {
+
     
+
     
+
     
     
     
@@ -14985,13667 +60817,12756 @@ Ext.Panel = Ext.extend(Ext.Container, {
     
     
     
+
     
+    constructor : function(config){
+        this.initialConfig = config;
+        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
+        this.items = [];
+    },
+
     
+    isAction : true,
+
     
+    setText : function(text){
+        this.initialConfig.text = text;
+        this.callEach('setText', [text]);
+    },
+
     
+    getText : function(){
+        return this.initialConfig.text;
+    },
+
     
+    setIconCls : function(cls){
+        this.initialConfig.iconCls = cls;
+        this.callEach('setIconCls', [cls]);
+    },
+
     
+    getIconCls : function(){
+        return this.initialConfig.iconCls;
+    },
+
     
+    setDisabled : function(v){
+        this.initialConfig.disabled = v;
+        this.callEach('setDisabled', [v]);
+    },
+
     
+    enable : function(){
+        this.setDisabled(false);
+    },
+
     
+    disable : function(){
+        this.setDisabled(true);
+    },
+
     
+    isDisabled : function(){
+        return this.initialConfig.disabled;
+    },
+
     
+    setHidden : function(v){
+        this.initialConfig.hidden = v;
+        this.callEach('setVisible', [!v]);
+    },
+
     
+    show : function(){
+        this.setHidden(false);
+    },
+
     
+    hide : function(){
+        this.setHidden(true);
+    },
 
     
+    isHidden : function(){
+        return this.initialConfig.hidden;
+    },
+
     
+    setHandler : function(fn, scope){
+        this.initialConfig.handler = fn;
+        this.initialConfig.scope = scope;
+        this.callEach('setHandler', [fn, scope]);
+    },
+
     
+    each : function(fn, scope){
+        Ext.each(this.items, fn, scope);
+    },
+
     
+    callEach : function(fnName, args){
+        var items = this.items,
+            i = 0,
+            len = items.length;
+
+        for(; i < len; i++){
+            items[i][fnName].apply(items[i], args);
+        }
+    },
+
     
+    addComponent : function(comp){
+        this.items.push(comp);
+        comp.on('destroy', this.removeComponent, this);
+    },
+
     
+    removeComponent : function(comp){
+        Ext.Array.remove(this.items, comp);
+    },
+
     
+    execute : function(){
+        this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
+    }
+});
+
+
+Ext.define('Ext.layout.component.Editor', {
+
     
 
+    alias: ['layout.editor'],
+
+    extend: 'Ext.layout.component.Component',
 
     
-    baseCls : 'x-panel',
+
+    onLayout: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            autoSize = owner.autoSize;
+            
+        if (autoSize === true) {
+            autoSize = {
+                width: 'field',
+                height: 'field'    
+            };
+        }
+        
+        if (autoSize) {
+            width = me.getDimension(owner, autoSize.width, 'Width', width);
+            height = me.getDimension(owner, autoSize.height, 'Height', height);
+        }
+        me.setTargetSize(width, height);
+        owner.field.setSize(width, height);
+    },
     
-    collapsedCls : 'x-panel-collapsed',
+    getDimension: function(owner, type, dimension, actual){
+        var method = 'get' + dimension;
+        switch (type) {
+            case 'boundEl':
+                return owner.boundEl[method]();
+            case 'field':
+                return owner.field[method]();
+            default:
+                return actual;
+        }
+    }
+});
+
+Ext.define('Ext.Editor', {
+
     
-    maskDisabled : true,
+
+    extend: 'Ext.Component',
+
+    alias: 'widget.editor',
+
+    requires: ['Ext.layout.component.Editor'],
+
     
-    animCollapse : Ext.enableFx,
+
+   componentLayout: 'editor',
+
     
-    headerAsText : true,
+
     
-    buttonAlign : 'right',
+    allowBlur: true,
+
     
-    collapsed : false,
+
     
-    collapseFirst : true,
+    revertInvalid: true,
+
     
-    minButtonWidth : 75,
+
     
+
     
-    elements : 'body',
+    value : '',
+
     
-    preventBodyReset : false,
+    alignment: 'c-c?',
 
     
-    padding: undefined,
+    offsets: [0, 0],
 
     
-    resizeEvent: 'bodyresize',
+    shadow : 'frame',
 
     
+    constrain : false,
+
     
+    swallowKeys : true,
+
     
-    toolTarget : 'header',
-    collapseEl : 'bwrap',
-    slideAnchor : 't',
-    disabledClass : '',
+    completeOnEnter : true,
 
     
-    deferHeight : true,
+    cancelOnEsc : true,
+
     
-    expandDefaults: {
-        duration : 0.25
-    },
+    updateEl : false,
+
     
-    collapseDefaults : {
-        duration : 0.25
-    },
 
     
-    initComponent : function(){
-        Ext.Panel.superclass.initComponent.call(this);
+    hidden: true,
+    baseCls: Ext.baseCSSPrefix + 'editor',
 
-        this.addEvents(
-            
-            'bodyresize',
-            
-            'titlechange',
-            
-            'iconchange',
-            
-            'collapse',
-            
-            'expand',
+    initComponent : function() {
+        var me = this,
+            field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
+
+        Ext.apply(field, {
+            inEditor: true,
+            msgTarget: field.msgTarget == 'title' ? 'title' :  'qtip'
+        });
+        me.mon(field, {
+            scope: me,
+            blur: {
+                fn: me.onBlur,
+                
+                delay: 1
+            },
+            specialkey: me.onSpecialKey
+        });
+
+        if (field.grow) {
+            me.mon(field, 'autosize', me.onAutoSize,  me, {delay: 1});
+        }
+        me.floating = {
+            constrain: me.constrain
+        };
+
+        me.callParent(arguments);
+
+        me.addEvents(
             
-            'beforecollapse',
+            'beforestartedit',
+
             
-            'beforeexpand',
+            'startedit',
+
             
-            'beforeclose',
+            'beforecomplete',
             
-            'close',
+            'complete',
             
-            'activate',
+            'canceledit',
             
-            'deactivate'
+            'specialkey'
         );
+    },
 
-        if(this.unstyled){
-            this.baseCls = 'x-plain';
-        }
+    
+    onAutoSize: function(){
+        this.doComponentLayout();
+    },
 
+    
+    onRender : function(ct, position) {
+        var me = this,
+            field = me.field,
+            inputEl = field.inputEl;
 
-        this.toolbars = [];
-        
-        if(this.tbar){
-            this.elements += ',tbar';
-            this.topToolbar = this.createToolbar(this.tbar);
-            this.tbar = null;
+        me.callParent(arguments);
 
+        field.render(me.el);
+        
+        
+        if (inputEl) {
+            inputEl.dom.name = '';
+            if (me.swallowKeys) {
+                inputEl.swallowEvent([
+                    'keypress', 
+                    'keydown'   
+                ]);
+            }
         }
-        if(this.bbar){
-            this.elements += ',bbar';
-            this.bottomToolbar = this.createToolbar(this.bbar);
-            this.bbar = null;
-        }
+    },
 
-        if(this.header === true){
-            this.elements += ',header';
-            this.header = null;
-        }else if(this.headerCfg || (this.title && this.header !== false)){
-            this.elements += ',header';
-        }
+    
+    onSpecialKey : function(field, event) {
+        var me = this,
+            key = event.getKey(),
+            complete = me.completeOnEnter && key == event.ENTER,
+            cancel = me.cancelOnEsc && key == event.ESC;
 
-        if(this.footerCfg || this.footer === true){
-            this.elements += ',footer';
-            this.footer = null;
+        if (complete || cancel) {
+            event.stopEvent();
+            
+            
+            Ext.defer(function() {
+                if (complete) {
+                    me.completeEdit();
+                } else {
+                    me.cancelEdit();
+                }
+                if (field.triggerBlur) {
+                    field.triggerBlur();
+                }
+            }, 10);
         }
 
-        if(this.buttons){
-            this.fbar = this.buttons;
-            this.buttons = null;
-        }
-        if(this.fbar){
-            this.createFbar(this.fbar);
-        }
-        if(this.autoLoad){
-            this.on('render', this.doAutoLoad, this, {delay:10});
-        }
+        this.fireEvent('specialkey', this, field, event);
     },
 
     
-    createFbar : function(fbar){
-        var min = this.minButtonWidth;
-        this.elements += ',footer';
-        this.fbar = this.createToolbar(fbar, {
-            buttonAlign: this.buttonAlign,
-            toolbarCls: 'x-panel-fbar',
-            enableOverflow: false,
-            defaults: function(c){
-                return {
-                    minWidth: c.minWidth || min
-                };
+    startEdit : function(el, value) {
+        var me = this,
+            field = me.field;
+
+        me.completeEdit();
+        me.boundEl = Ext.get(el);
+        value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
+
+        if (!me.rendered) {
+            me.render(me.parentEl || document.body);
+        }
+
+        if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
+            me.startValue = value;
+            me.show();
+            field.reset();
+            field.setValue(value);
+            me.realign(true);
+            field.focus(false, 10);
+            if (field.autoSize) {
+                field.autoSize();
             }
-        });
-        
-        
-        
-        this.fbar.items.each(function(c){
-            c.minWidth = c.minWidth || this.minButtonWidth;
-        }, this);
-        this.buttons = this.fbar.items.items;
+            me.editing = true;
+        }
     },
 
     
-    createToolbar: function(tb, options){
-        var result;
-        
-        if(Ext.isArray(tb)){
-            tb = {
-                items: tb
-            };
+    realign : function(autoSize) {
+        var me = this;
+        if (autoSize === true) {
+            me.doComponentLayout();
         }
-        result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
-        this.toolbars.push(result);
-        return result;
+        me.alignTo(me.boundEl, me.alignment, me.offsets);
     },
 
     
-    createElement : function(name, pnode){
-        if(this[name]){
-            pnode.appendChild(this[name].dom);
+    completeEdit : function(remainVisible) {
+        var me = this,
+            field = me.field,
+            value;
+
+        if (!me.editing) {
             return;
         }
 
-        if(name === 'bwrap' || this.elements.indexOf(name) != -1){
-            if(this[name+'Cfg']){
-                this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
-            }else{
-                var el = document.createElement('div');
-                el.className = this[name+'Cls'];
-                this[name] = Ext.get(pnode.appendChild(el));
-            }
-            if(this[name+'CssClass']){
-                this[name].addClass(this[name+'CssClass']);
+        
+        if (field.assertValue) {
+            field.assertValue();
+        }
+
+        value = me.getValue();
+        if (!field.isValid()) {
+            if (me.revertInvalid !== false) {
+                me.cancelEdit(remainVisible);
             }
-            if(this[name+'Style']){
-                this[name].applyStyles(this[name+'Style']);
+            return;
+        }
+
+        if (String(value) === String(me.startValue) && me.ignoreNoChange) {
+            me.hideEdit(remainVisible);
+            return;
+        }
+
+        if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
+            
+            value = me.getValue();
+            if (me.updateEl && me.boundEl) {
+                me.boundEl.update(value);
             }
+            me.hideEdit(remainVisible);
+            me.fireEvent('complete', me, value, me.startValue);
         }
     },
 
     
-    onRender : function(ct, position){
-        Ext.Panel.superclass.onRender.call(this, ct, position);
-        this.createClasses();
+    onShow : function() {
+        var me = this;
 
-        var el = this.el,
-            d = el.dom,
-            bw,
-            ts;
+        me.callParent(arguments);
+        if (me.hideEl !== false) {
+            me.boundEl.hide();
+        }
+        me.fireEvent("startedit", me.boundEl, me.startValue);
+    },
 
+    
+    cancelEdit : function(remainVisible) {
+        var me = this,
+            startValue = me.startValue,
+            value;
 
-        if(this.collapsible && !this.hideCollapseTool){
-            this.tools = this.tools ? this.tools.slice(0) : [];
-            this.tools[this.collapseFirst?'unshift':'push']({
-                id: 'toggle',
-                handler : this.toggleCollapse,
-                scope: this
-            });
+        if (me.editing) {
+            value = me.getValue();
+            me.setValue(startValue);
+            me.hideEdit(remainVisible);
+            me.fireEvent('canceledit', me, value, startValue);
         }
+    },
 
-        if(this.tools){
-            ts = this.tools;
-            this.elements += (this.header !== false) ? ',header' : '';
+    
+    hideEdit: function(remainVisible) {
+        if (remainVisible !== true) {
+            this.editing = false;
+            this.hide();
         }
-        this.tools = {};
+    },
+
+    
+    onBlur : function() {
+        var me = this;
 
-        el.addClass(this.baseCls);
-        if(d.firstChild){ 
-            this.header = el.down('.'+this.headerCls);
-            this.bwrap = el.down('.'+this.bwrapCls);
-            var cp = this.bwrap ? this.bwrap : el;
-            this.tbar = cp.down('.'+this.tbarCls);
-            this.body = cp.down('.'+this.bodyCls);
-            this.bbar = cp.down('.'+this.bbarCls);
-            this.footer = cp.down('.'+this.footerCls);
-            this.fromMarkup = true;
+        
+        if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) {
+            me.completeEdit();
         }
-        if (this.preventBodyReset === true) {
-            el.addClass('x-panel-reset');
+    },
+
+    
+    onHide : function() {
+        var me = this,
+            field = me.field;
+
+        if (me.editing) {
+            me.completeEdit();
+            return;
         }
-        if(this.cls){
-            el.addClass(this.cls);
+        field.blur();
+        if (field.collapse) {
+            field.collapse();
         }
 
-        if(this.buttons){
-            this.elements += ',footer';
+        
+        if (me.hideEl !== false) {
+            me.boundEl.show();
         }
+        me.callParent(arguments);
+    },
 
-        
+    
+    setValue : function(value) {
+        this.field.setValue(value);
+    },
 
-        
-        if(this.frame){
-            el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
+    
+    getValue : function() {
+        return this.field.getValue();
+    },
 
-            this.createElement('header', d.firstChild.firstChild.firstChild);
-            this.createElement('bwrap', d);
+    beforeDestroy : function() {
+        var me = this;
 
-            
-            bw = this.bwrap.dom;
-            var ml = d.childNodes[1], bl = d.childNodes[2];
-            bw.appendChild(ml);
-            bw.appendChild(bl);
+        Ext.destroy(me.field);
+        delete me.field;
+        delete me.parentEl;
+        delete me.boundEl;
 
-            var mc = bw.firstChild.firstChild.firstChild;
-            this.createElement('tbar', mc);
-            this.createElement('body', mc);
-            this.createElement('bbar', mc);
-            this.createElement('footer', bw.lastChild.firstChild.firstChild);
+        me.callParent(arguments);
+    }
+});
 
-            if(!this.footer){
-                this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
-            }
-            
-            this.ft = Ext.get(this.bwrap.dom.lastChild);
-            this.mc = Ext.get(mc);
-        }else{
-            this.createElement('header', d);
-            this.createElement('bwrap', d);
+Ext.define('Ext.Img', {
+    extend: 'Ext.Component',
+    alias: ['widget.image', 'widget.imagecomponent'],
+    
+    src: '',
 
-            
-            bw = this.bwrap.dom;
-            this.createElement('tbar', bw);
-            this.createElement('body', bw);
-            this.createElement('bbar', bw);
-            this.createElement('footer', bw);
+    getElConfig: function() {
+        return {
+            tag: 'img',
+            src: this.src
+        };
+    },
+    
+    
+    initRenderTpl: Ext.emptyFn,
+    
+    
+    setSrc: function(src) {
+        var me = this,
+            img = me.el;
+        me.src = src;
+        if (img) {
+            img.dom.src = src;
+        }
+    }
+});
 
-            if(!this.header){
-                this.body.addClass(this.bodyCls + '-noheader');
-                if(this.tbar){
-                    this.tbar.addClass(this.tbarCls + '-noheader');
-                }
+
+Ext.define('Ext.Layer', {
+    uses: ['Ext.Shadow'],
+
+    
+    statics: {
+        shims: []
+    },
+
+    extend: 'Ext.Element',
+
+    
+    constructor: function(config, existingEl) {
+        config = config || {};
+        var me = this,
+            dh = Ext.DomHelper,
+            cp = config.parentEl,
+            pel = cp ? Ext.getDom(cp) : document.body,
+        hm = config.hideMode;
+
+        if (existingEl) {
+            me.dom = Ext.getDom(existingEl);
+        }
+        if (!me.dom) {
+            me.dom = dh.append(pel, config.dh || {
+                tag: 'div',
+                cls: Ext.baseCSSPrefix + 'layer'
+            });
+        } else {
+            me.addCls(Ext.baseCSSPrefix + 'layer');
+            if (!me.dom.parentNode) {
+                pel.appendChild(me.dom);
             }
         }
 
-        if(Ext.isDefined(this.padding)){
-            this.body.setStyle('padding', this.body.addUnits(this.padding));
+        if (config.cls) {
+            me.addCls(config.cls);
         }
+        me.constrain = config.constrain !== false;
 
-        if(this.border === false){
-            this.el.addClass(this.baseCls + '-noborder');
-            this.body.addClass(this.bodyCls + '-noborder');
-            if(this.header){
-                this.header.addClass(this.headerCls + '-noborder');
-            }
-            if(this.footer){
-                this.footer.addClass(this.footerCls + '-noborder');
-            }
-            if(this.tbar){
-                this.tbar.addClass(this.tbarCls + '-noborder');
-            }
-            if(this.bbar){
-                this.bbar.addClass(this.bbarCls + '-noborder');
+        
+        
+        
+        if (hm) {
+            me.setVisibilityMode(Ext.Element[hm.toUpperCase()]);
+            if (me.visibilityMode == Ext.Element.ASCLASS) {
+                me.visibilityCls = config.visibilityCls;
             }
+        } else if (config.useDisplay) {
+            me.setVisibilityMode(Ext.Element.DISPLAY);
+        } else {
+            me.setVisibilityMode(Ext.Element.VISIBILITY);
         }
 
-        if(this.bodyBorder === false){
-           this.body.addClass(this.bodyCls + '-noborder');
+        if (config.id) {
+            me.id = me.dom.id = config.id;
+        } else {
+            me.id = Ext.id(me.dom);
+        }
+        me.position('absolute');
+        if (config.shadow) {
+            me.shadowOffset = config.shadowOffset || 4;
+            me.shadow = Ext.create('Ext.Shadow', {
+                offset: me.shadowOffset,
+                mode: config.shadow
+            });
+            me.disableShadow();
+        } else {
+            me.shadowOffset = 0;
         }
+        me.useShim = config.shim !== false && Ext.useShims;
+        if (config.hidden === true) {
+            me.hide();
+        } else {
+            me.show();
+        }
+    },
 
-        this.bwrap.enableDisplayMode('block');
-
-        if(this.header){
-            this.header.unselectable();
+    getZIndex: function() {
+        return parseInt((this.getShim() || this).getStyle('z-index'), 10);
+    },
 
-            
-            if(this.headerAsText){
-                this.header.dom.innerHTML =
-                    '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
+    getShim: function() {
+        var me = this,
+            shim, pn;
 
-                if(this.iconCls){
-                    this.setIconClass(this.iconCls);
-                }
+        if (!me.useShim) {
+            return null;
+        }
+        if (!me.shim) {
+            shim = me.self.shims.shift();
+            if (!shim) {
+                shim = me.createShim();
+                shim.enableDisplayMode('block');
+                shim.hide();
+            }
+            pn = me.dom.parentNode;
+            if (shim.dom.parentNode != pn) {
+                pn.insertBefore(shim.dom, me.dom);
             }
+            me.shim = shim;
         }
+        return me.shim;
+    },
 
-        if(this.floating){
-            this.makeFloating(this.floating);
+    hideShim: function() {
+        var me = this;
+        
+        if (me.shim) {
+            me.shim.setDisplayed(false);
+            me.self.shims.push(me.shim);
+            delete me.shim;
         }
+    },
 
-        if(this.collapsible && this.titleCollapse && this.header){
-            this.mon(this.header, 'click', this.toggleCollapse, this);
-            this.header.setStyle('cursor', 'pointer');
-        }
-        if(ts){
-            this.addTool.apply(this, ts);
+    disableShadow: function() {
+        var me = this;
+        
+        if (me.shadow && !me.shadowDisabled) {
+            me.shadowDisabled = true;
+            me.shadow.hide();
+            me.lastShadowOffset = me.shadowOffset;
+            me.shadowOffset = 0;
         }
+    },
 
+    enableShadow: function(show) {
+        var me = this;
         
-        if(this.fbar){
-            this.footer.addClass('x-panel-btns');
-            this.fbar.ownerCt = this;
-            this.fbar.render(this.footer);
-            this.footer.createChild({cls:'x-clear'});
-        }
-        if(this.tbar && this.topToolbar){
-            this.topToolbar.ownerCt = this;
-            this.topToolbar.render(this.tbar);
-        }
-        if(this.bbar && this.bottomToolbar){
-            this.bottomToolbar.ownerCt = this;
-            this.bottomToolbar.render(this.bbar);
+        if (me.shadow && me.shadowDisabled) {
+            me.shadowDisabled = false;
+            me.shadowOffset = me.lastShadowOffset;
+            delete me.lastShadowOffset;
+            if (show) {
+                me.sync(true);
+            }
         }
     },
 
     
-    setIconClass : function(cls){
-        var old = this.iconCls;
-        this.iconCls = cls;
-        if(this.rendered && this.header){
-            if(this.frame){
-                this.header.addClass('x-panel-icon');
-                this.header.replaceClass(old, this.iconCls);
-            }else{
-                var hd = this.header,
-                    img = hd.child('img.x-panel-inline-icon');
-                if(img){
-                    Ext.fly(img).replaceClass(old, this.iconCls);
-                }else{
-                    var hdspan = hd.child('span.' + this.headerTextCls);
-                    if (hdspan) {
-                        Ext.DomHelper.insertBefore(hdspan.dom, {
-                            tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
-                        });
+    sync: function(doShow) {
+        var me = this,
+            shadow = me.shadow,
+            shadowPos, shimStyle, shadowSize;
+
+        if (!me.updating && me.isVisible() && (shadow || me.useShim)) {
+            var shim = me.getShim(),
+                l = me.getLeft(true),
+                t = me.getTop(true),
+                w = me.dom.offsetWidth,
+                h = me.dom.offsetHeight,
+                shimIndex;
+
+            if (shadow && !me.shadowDisabled) {
+                if (doShow && !shadow.isVisible()) {
+                    shadow.show(me);
+                } else {
+                    shadow.realign(l, t, w, h);
+                }
+                if (shim) {
+                    
+                    shimIndex = shim.getStyle('z-index');
+                    if (shimIndex > me.zindex) {
+                        me.shim.setStyle('z-index', me.zindex - 2);
+                    }
+                    shim.show();
+                    
+                    if (shadow.isVisible()) {
+                        shadowPos = shadow.el.getXY();
+                        shimStyle = shim.dom.style;
+                        shadowSize = shadow.el.getSize();
+                        if (Ext.supports.CSS3BoxShadow) {
+                            shadowSize.height += 6;
+                            shadowSize.width += 4;
+                            shadowPos[0] -= 2;
+                            shadowPos[1] -= 4;
+                        }
+                        shimStyle.left = (shadowPos[0]) + 'px';
+                        shimStyle.top = (shadowPos[1]) + 'px';
+                        shimStyle.width = (shadowSize.width) + 'px';
+                        shimStyle.height = (shadowSize.height) + 'px';
+                    } else {
+                        shim.setSize(w, h);
+                        shim.setLeftTop(l, t);
                     }
-                 }
+                }
+            } else if (shim) {
+                
+                shimIndex = shim.getStyle('z-index');
+                if (shimIndex > me.zindex) {
+                    me.shim.setStyle('z-index', me.zindex - 2);
+                }
+                shim.show();
+                shim.setSize(w, h);
+                shim.setLeftTop(l, t);
             }
         }
-        this.fireEvent('iconchange', this, cls, old);
-    },
-
-    
-    makeFloating : function(cfg){
-        this.floating = true;
-        this.el = new Ext.Layer(Ext.apply({}, cfg, {
-            shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
-            shadowOffset: this.shadowOffset,
-            constrain:false,
-            shim: this.shim === false ? false : undefined
-        }), this.el);
+        return me;
     },
 
-    
-    getTopToolbar : function(){
-        return this.topToolbar;
+    remove: function() {
+        this.hideUnders();
+        this.callParent();
     },
 
     
-    getBottomToolbar : function(){
-        return this.bottomToolbar;
+    beginUpdate: function() {
+        this.updating = true;
     },
 
     
-    getFooterToolbar : function() {
-        return this.fbar;
+    endUpdate: function() {
+        this.updating = false;
+        this.sync(true);
     },
 
     
-    addButton : function(config, handler, scope){
-        if(!this.fbar){
-            this.createFbar([]);
-        }
-        if(handler){
-            if(Ext.isString(config)){
-                config = {text: config};
-            }
-            config = Ext.apply({
-                handler: handler,
-                scope: scope
-            }, config);
+    hideUnders: function() {
+        if (this.shadow) {
+            this.shadow.hide();
         }
-        return this.fbar.add(config);
+        this.hideShim();
     },
 
     
-    addTool : function(){
-        if(!this.rendered){
-            if(!this.tools){
-                this.tools = [];
+    constrainXY: function() {
+        if (this.constrain) {
+            var vw = Ext.Element.getViewWidth(),
+                vh = Ext.Element.getViewHeight(),
+                s = Ext.getDoc().getScroll(),
+                xy = this.getXY(),
+                x = xy[0],
+                y = xy[1],
+                so = this.shadowOffset,
+                w = this.dom.offsetWidth + so,
+                h = this.dom.offsetHeight + so,
+                moved = false; 
+            
+            if ((x + w) > vw + s.left) {
+                x = vw - w - so;
+                moved = true;
+            }
+            if ((y + h) > vh + s.top) {
+                y = vh - h - so;
+                moved = true;
             }
-            Ext.each(arguments, function(arg){
-                this.tools.push(arg);
-            }, this);
-            return;
-        }
-         
-        if(!this[this.toolTarget]){
-            return;
-        }
-        if(!this.toolTemplate){
             
-            var tt = new Ext.Template(
-                 '<div class="x-tool x-tool-{id}">&#160;</div>'
-            );
-            tt.disableFormats = true;
-            tt.compile();
-            Ext.Panel.prototype.toolTemplate = tt;
-        }
-        for(var i = 0, a = arguments, len = a.length; i < len; i++) {
-            var tc = a[i];
-            if(!this.tools[tc.id]){
-                var overCls = 'x-tool-'+tc.id+'-over';
-                var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
-                this.tools[tc.id] = t;
-                t.enableDisplayMode('block');
-                this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
-                if(tc.on){
-                    this.mon(t, tc.on);
-                }
-                if(tc.hidden){
-                    t.hide();
-                }
-                if(tc.qtip){
-                    if(Ext.isObject(tc.qtip)){
-                        Ext.QuickTips.register(Ext.apply({
-                              target: t.id
-                        }, tc.qtip));
-                    } else {
-                        t.dom.qtip = tc.qtip;
-                    }
-                }
-                t.addClassOnOver(overCls);
+            if (x < s.left) {
+                x = s.left;
+                moved = true;
+            }
+            if (y < s.top) {
+                y = s.top;
+                moved = true;
+            }
+            if (moved) {
+                Ext.Layer.superclass.setXY.call(this, [x, y]);
+                this.sync();
             }
         }
+        return this;
     },
 
-    onLayout : function(shallow, force){
-        Ext.Panel.superclass.onLayout.apply(this, arguments);
-        if(this.hasLayout && this.toolbars.length > 0){
-            Ext.each(this.toolbars, function(tb){
-                tb.doLayout(undefined, force);
-            });
-            this.syncHeight();
-        }
+    getConstrainOffset: function() {
+        return this.shadowOffset;
     },
 
-    syncHeight : function(){
-        var h = this.toolbarHeight,
-                bd = this.body,
-                lsh = this.lastSize.height,
-                sz;
-
-        if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
-            return;
-        }
+    
+    setVisible: function(visible, animate, duration, callback, easing) {
+        var me = this,
+            cb;
 
+        
+        cb = function() {
+            if (visible) {
+                me.sync(true);
+            }
+            if (callback) {
+                callback();
+            }
+        };
 
-        if(h != this.getToolbarHeight()){
-            h = Math.max(0, lsh - this.getFrameHeight());
-            bd.setHeight(h);
-            sz = bd.getSize();
-            this.toolbarHeight = this.getToolbarHeight();
-            this.onBodyResize(sz.width, sz.height);
+        
+        if (!visible) {
+            me.hideUnders(true);
         }
-    },
-
-    
-    onShow : function(){
-        if(this.floating){
-            return this.el.show();
+        me.callParent([visible, animate, duration, callback, easing]);
+        if (!animate) {
+            cb();
         }
-        Ext.Panel.superclass.onShow.call(this);
+        return me;
     },
 
     
-    onHide : function(){
-        if(this.floating){
-            return this.el.hide();
-        }
-        Ext.Panel.superclass.onHide.call(this);
+    beforeFx: function() {
+        this.beforeAction();
+        return this.callParent(arguments);
     },
 
     
-    createToolHandler : function(t, tc, overCls, panel){
-        return function(e){
-            t.removeClass(overCls);
-            if(tc.stopEvent !== false){
-                e.stopEvent();
-            }
-            if(tc.handler){
-                tc.handler.call(tc.scope || t, e, t, panel, tc);
-            }
-        };
+    afterFx: function() {
+        this.callParent(arguments);
+        this.sync(this.isVisible());
     },
 
     
-    afterRender : function(){
-        if(this.floating && !this.hidden){
-            this.el.show();
-        }
-        if(this.title){
-            this.setTitle(this.title);
-        }
-        Ext.Panel.superclass.afterRender.call(this); 
-        if (this.collapsed) {
-            this.collapsed = false;
-            this.collapse(false);
+    beforeAction: function() {
+        if (!this.updating && this.shadow) {
+            this.shadow.hide();
         }
-        this.initEvents();
     },
 
     
-    getKeyMap : function(){
-        if(!this.keyMap){
-            this.keyMap = new Ext.KeyMap(this.el, this.keys);
-        }
-        return this.keyMap;
+    setLeft: function(left) {
+        this.callParent(arguments);
+        return this.sync();
     },
 
-    
-    initEvents : function(){
-        if(this.keys){
-            this.getKeyMap();
-        }
-        if(this.draggable){
-            this.initDraggable();
-        }
-        if(this.toolbars.length > 0){
-            Ext.each(this.toolbars, function(tb){
-                tb.doLayout();
-                tb.on({
-                    scope: this,
-                    afterlayout: this.syncHeight,
-                    remove: this.syncHeight
-                });
-            }, this);
-            this.syncHeight();
-        }
+    setTop: function(top) {
+        this.callParent(arguments);
+        return this.sync();
+    },
 
+    setLeftTop: function(left, top) {
+        this.callParent(arguments);
+        return this.sync();
     },
 
-    
-    initDraggable : function(){
+    setXY: function(xy, animate, duration, callback, easing) {
+        var me = this;
         
-        this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
-    },
+        
+        callback = me.createCB(callback);
 
-    
-    beforeEffect : function(anim){
-        if(this.floating){
-            this.el.beforeAction();
-        }
-        if(anim !== false){
-            this.el.addClass('x-panel-animated');
+        me.fixDisplay();
+        me.beforeAction();
+        me.callParent([xy, animate, duration, callback, easing]);
+        if (!animate) {
+            callback();
         }
+        return me;
     },
 
     
-    afterEffect : function(anim){
-        this.syncShadow();
-        this.el.removeClass('x-panel-animated');
-    },
+    createCB: function(callback) {
+        var me = this,
+            showShadow = me.shadow && me.shadow.isVisible();
 
-    
-    createEffect : function(a, cb, scope){
-        var o = {
-            scope:scope,
-            block:true
+        return function() {
+            me.constrainXY();
+            me.sync(showShadow);
+            if (callback) {
+                callback();
+            }
         };
-        if(a === true){
-            o.callback = cb;
-            return o;
-        }else if(!a.callback){
-            o.callback = cb;
-        }else { 
-            o.callback = function(){
-                cb.call(scope);
-                Ext.callback(a.callback, a.scope);
-            };
-        }
-        return Ext.applyIf(o, a);
     },
 
     
-    collapse : function(animate){
-        if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
-            return;
-        }
-        var doAnim = animate === true || (animate !== false && this.animCollapse);
-        this.beforeEffect(doAnim);
-        this.onCollapse(doAnim, animate);
+    setX: function(x, animate, duration, callback, easing) {
+        this.setXY([x, this.getY()], animate, duration, callback, easing);
         return this;
     },
 
     
-    onCollapse : function(doAnim, animArg){
-        if(doAnim){
-            this[this.collapseEl].slideOut(this.slideAnchor,
-                    Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
-                        this.collapseDefaults));
-        }else{
-            this[this.collapseEl].hide(this.hideMode);
-            this.afterCollapse(false);
-        }
+    setY: function(y, animate, duration, callback, easing) {
+        this.setXY([this.getX(), y], animate, duration, callback, easing);
+        return this;
     },
 
     
-    afterCollapse : function(anim){
-        this.collapsed = true;
-        this.el.addClass(this.collapsedCls);
-        if(anim !== false){
-            this[this.collapseEl].hide(this.hideMode);
+    setSize: function(w, h, animate, duration, callback, easing) {
+        var me = this;
+        
+        
+        callback = me.createCB(callback);
+
+        me.beforeAction();
+        me.callParent([w, h, animate, duration, callback, easing]);
+        if (!animate) {
+            callback();
         }
-        this.afterEffect(anim);
+        return me;
+    },
 
+    
+    setWidth: function(w, animate, duration, callback, easing) {
+        var me = this;
         
-        this.cascade(function(c) {
-            if (c.lastSize) {
-                c.lastSize = { width: undefined, height: undefined };
-            }
-        });
-        this.fireEvent('collapse', this);
+        
+        callback = me.createCB(callback);
+
+        me.beforeAction();
+        me.callParent([w, animate, duration, callback, easing]);
+        if (!animate) {
+            callback();
+        }
+        return me;
     },
 
     
-    expand : function(animate){
-        if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
-            return;
+    setHeight: function(h, animate, duration, callback, easing) {
+        var me = this;
+        
+        
+        callback = me.createCB(callback);
+
+        me.beforeAction();
+        me.callParent([h, animate, duration, callback, easing]);
+        if (!animate) {
+            callback();
         }
-        var doAnim = animate === true || (animate !== false && this.animCollapse);
-        this.el.removeClass(this.collapsedCls);
-        this.beforeEffect(doAnim);
-        this.onExpand(doAnim, animate);
-        return this;
+        return me;
     },
 
     
-    onExpand : function(doAnim, animArg){
-        if(doAnim){
-            this[this.collapseEl].slideIn(this.slideAnchor,
-                    Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
-                        this.expandDefaults));
-        }else{
-            this[this.collapseEl].show(this.hideMode);
-            this.afterExpand(false);
+    setBounds: function(x, y, width, height, animate, duration, callback, easing) {
+        var me = this;
+        
+        
+        callback = me.createCB(callback);
+
+        me.beforeAction();
+        if (!animate) {
+            Ext.Layer.superclass.setXY.call(me, [x, y]);
+            Ext.Layer.superclass.setSize.call(me, width, height);
+            callback();
+        } else {
+            me.callParent([x, y, width, height, animate, duration, callback, easing]);
         }
+        return me;
     },
 
     
-    afterExpand : function(anim){
-        this.collapsed = false;
-        if(anim !== false){
-            this[this.collapseEl].show(this.hideMode);
+    setZIndex: function(zindex) {
+        var me = this;
+        
+        me.zindex = zindex;
+        if (me.getShim()) {
+            me.shim.setStyle('z-index', zindex++);
         }
-        this.afterEffect(anim);
-        if (this.deferLayout) {
-            delete this.deferLayout;
-            this.doLayout(true);
+        if (me.shadow) {
+            me.shadow.setZIndex(zindex++);
         }
-        this.fireEvent('expand', this);
+        return me.setStyle('z-index', zindex);
     },
+    
+    setOpacity: function(opacity){
+        if (this.shadow) {
+            this.shadow.setOpacity(opacity);
+        }
+        return this.callParent(arguments);
+    }
+});
+
+
+
+Ext.define('Ext.layout.component.ProgressBar', {
 
     
-    toggleCollapse : function(animate){
-        this[this.collapsed ? 'expand' : 'collapse'](animate);
-        return this;
-    },
+
+    alias: ['layout.progressbar'],
+
+    extend: 'Ext.layout.component.Component',
 
     
-    onDisable : function(){
-        if(this.rendered && this.maskDisabled){
-            this.el.mask();
-        }
-        Ext.Panel.superclass.onDisable.call(this);
+
+    type: 'progressbar',
+
+    onLayout: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            textEl = owner.textEl;
+        
+        me.setElementSize(owner.el, width, height);
+        textEl.setWidth(owner.el.getWidth(true));
+        
+        me.callParent([width, height]);
+        
+        owner.updateProgress(owner.value);
+    }
+});
+
+Ext.define('Ext.ProgressBar', {
+    extend: 'Ext.Component',
+    alias: 'widget.progressbar',
+
+    requires: [
+        'Ext.Template',
+        'Ext.CompositeElement',
+        'Ext.TaskManager',
+        'Ext.layout.component.ProgressBar'
+    ],
+
+    uses: ['Ext.fx.Anim'],
+
+   
+
+   
+
+   
+
+   
+
+   
+    baseCls: Ext.baseCSSPrefix + 'progress',
+
+    config: {
+        
+        animate: false,
+
+        
+        text: ''
     },
 
     
-    onEnable : function(){
-        if(this.rendered && this.maskDisabled){
-            this.el.unmask();
-        }
-        Ext.Panel.superclass.onEnable.call(this);
-    },
+    waitTimer: null,
+
+    renderTpl: [
+        '<div class="{baseCls}-text {baseCls}-text-back">',
+            '<div>&#160;</div>',
+        '</div>',
+        '<div id="{id}-bar" class="{baseCls}-bar">',
+            '<div class="{baseCls}-text">',
+                '<div>&#160;</div>',
+            '</div>',
+        '</div>'
+    ],
+
+    componentLayout: 'progressbar',
 
     
-    onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
-        var w = adjWidth,
-            h = adjHeight;
+    initComponent: function() {
+        this.callParent();
 
-        if(Ext.isDefined(w) || Ext.isDefined(h)){
-            if(!this.collapsed){
-                
-                
-                
+        this.addChildEls('bar');
 
-                if(Ext.isNumber(w)){
-                    this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
-                } else if (w == 'auto') {
-                    w = this.body.setWidth('auto').dom.offsetWidth;
-                } else {
-                    w = this.body.dom.offsetWidth;
-                }
+        this.addEvents(
+            
+            "update"
+        );
+    },
 
-                if(this.tbar){
-                    this.tbar.setWidth(w);
-                    if(this.topToolbar){
-                        this.topToolbar.setSize(w);
-                    }
-                }
-                if(this.bbar){
-                    this.bbar.setWidth(w);
-                    if(this.bottomToolbar){
-                        this.bottomToolbar.setSize(w);
-                        
-                        if (Ext.isIE) {
-                            this.bbar.setStyle('position', 'static');
-                            this.bbar.setStyle('position', '');
-                        }
-                    }
-                }
-                if(this.footer){
-                    this.footer.setWidth(w);
-                    if(this.fbar){
-                        this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
-                    }
-                }
+    afterRender : function() {
+        var me = this;
 
-                
-                if(Ext.isNumber(h)){
-                    h = Math.max(0, h - this.getFrameHeight());
-                    
-                    this.body.setHeight(h);
-                }else if(h == 'auto'){
-                    this.body.setHeight(h);
-                }
+        
+        
+        me.textEl = me.textEl ? Ext.get(me.textEl) : me.el.select('.' + me.baseCls + '-text');
 
-                if(this.disabled && this.el._mask){
-                    this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
-                }
-            }else{
-                
-                this.queuedBodySize = {width: w, height: h};
-                if(!this.queuedExpand && this.allowQueuedExpand !== false){
-                    this.queuedExpand = true;
-                    this.on('expand', function(){
-                        delete this.queuedExpand;
-                        this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
-                    }, this, {single:true});
-                }
-            }
-            this.onBodyResize(w, h);
-        }
-        this.syncShadow();
-        Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
+        me.callParent(arguments);
 
+        if (me.value) {
+            me.updateProgress(me.value, me.text);
+        }
+        else {
+            me.updateText(me.text);
+        }
     },
 
     
-    onBodyResize: function(w, h){
-        this.fireEvent('bodyresize', this, w, h);
+    updateProgress: function(value, text, animate) {
+        var me = this,
+            newWidth;
+            
+        me.value = value || 0;
+        if (text) {
+            me.updateText(text);
+        }
+        if (me.rendered && !me.isDestroyed) {
+            if (me.isVisible(true)) {
+                newWidth = Math.floor(me.value * me.el.getWidth(true));
+                if (Ext.isForcedBorderBox) {
+                    newWidth += me.bar.getBorderWidth("lr");
+                }
+                if (animate === true || (animate !== false && me.animate)) {
+                    me.bar.stopAnimation();
+                    me.bar.animate(Ext.apply({
+                        to: {
+                            width: newWidth + 'px'
+                        }
+                    }, me.animate));
+                } else {
+                    me.bar.setWidth(newWidth);
+                }
+            } else {
+                
+                me.doComponentLayout();
+            }
+        }
+        me.fireEvent('update', me, me.value, text);
+        return me;
     },
 
     
-    getToolbarHeight: function(){
-        var h = 0;
-        if(this.rendered){
-            Ext.each(this.toolbars, function(tb){
-                h += tb.getHeight();
-            }, this);
+    updateText: function(text) {
+        var me = this;
+        
+        me.text = text;
+        if (me.rendered) {
+            me.textEl.update(me.text);
         }
-        return h;
+        return me;
     },
 
-    
-    adjustBodyHeight : function(h){
-        return h;
+    applyText : function(text) {
+        this.updateText(text);
     },
 
     
-    adjustBodyWidth : function(w){
-        return w;
+    wait: function(o) {
+        var me = this;
+            
+        if (!me.waitTimer) {
+            scope = me;
+            o = o || {};
+            me.updateText(o.text);
+            me.waitTimer = Ext.TaskManager.start({
+                run: function(i){
+                    var inc = o.increment || 10;
+                    i -= 1;
+                    me.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
+                },
+                interval: o.interval || 1000,
+                duration: o.duration,
+                onStop: function(){
+                    if (o.fn) {
+                        o.fn.apply(o.scope || me);
+                    }
+                    me.reset();
+                },
+                scope: scope
+            });
+        }
+        return me;
     },
 
     
-    onPosition : function(){
-        this.syncShadow();
+    isWaiting: function(){
+        return this.waitTimer !== null;
     },
 
     
-    getFrameWidth : function(){
-        var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
-
-        if(this.frame){
-            var l = this.bwrap.dom.firstChild;
-            w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
-            w += this.mc.getFrameWidth('lr');
+    reset: function(hide){
+        var me = this;
+        
+        me.updateProgress(0);
+        me.clearTimer();
+        if (hide === true) {
+            me.hide();
         }
-        return w;
+        return me;
     },
 
     
-    getFrameHeight : function() {
-        var h = Math.max(0, this.getHeight() - this.body.getHeight());
-
-        if (isNaN(h)) {
-            h = 0;
+    clearTimer: function(){
+        var me = this;
+        
+        if (me.waitTimer) {
+            me.waitTimer.onStop = null; 
+            Ext.TaskManager.stop(me.waitTimer);
+            me.waitTimer = null;
         }
-        return h;
+    },
 
+    onDestroy: function(){
+        var me = this;
         
-    },
+        me.clearTimer();
+        if (me.rendered) {
+            if (me.textEl.isComposite) {
+                me.textEl.clear();
+            }
+            Ext.destroyMembers(me, 'textEl', 'progressBar');
+        }
+        me.callParent();
+    }
+});
 
-    
-    getInnerWidth : function(){
-        return this.getSize().width - this.getFrameWidth();
-    },
 
-    
-    getInnerHeight : function(){
-        return this.body.getHeight();
-        
-    },
+Ext.define('Ext.ShadowPool', {
+    singleton: true,
+    requires: ['Ext.DomHelper'],
 
-    
-    syncShadow : function(){
-        if(this.floating){
-            this.el.sync(true);
+    markup: function() {
+        if (Ext.supports.CSS3BoxShadow) {
+            return '<div class="' + Ext.baseCSSPrefix + 'css-shadow" role="presentation"></div>';
+        } else if (Ext.isIE) {
+            return '<div class="' + Ext.baseCSSPrefix + 'ie-shadow" role="presentation"></div>';
+        } else {
+            return '<div class="' + Ext.baseCSSPrefix + 'frame-shadow" role="presentation">' +
+                '<div class="xst" role="presentation">' +
+                    '<div class="xstl" role="presentation"></div>' +
+                    '<div class="xstc" role="presentation"></div>' +
+                    '<div class="xstr" role="presentation"></div>' +
+                '</div>' +
+                '<div class="xsc" role="presentation">' +
+                    '<div class="xsml" role="presentation"></div>' +
+                    '<div class="xsmc" role="presentation"></div>' +
+                    '<div class="xsmr" role="presentation"></div>' +
+                '</div>' +
+                '<div class="xsb" role="presentation">' +
+                    '<div class="xsbl" role="presentation"></div>' +
+                    '<div class="xsbc" role="presentation"></div>' +
+                    '<div class="xsbr" role="presentation"></div>' +
+                '</div>' +
+            '</div>';
         }
-    },
+    }(),
 
-    
-    getLayoutTarget : function(){
-        return this.body;
+    shadows: [],
+
+    pull: function() {
+        var sh = this.shadows.shift();
+        if (!sh) {
+            sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, this.markup));
+            sh.autoBoxAdjust = false;
+        }
+        return sh;
     },
 
-    
-    getContentTarget : function(){
-        return this.body;
+    push: function(sh) {
+        this.shadows.push(sh);
     },
+    
+    reset: function() {
+        Ext.Array.each(this.shadows, function(shadow) {
+            shadow.remove();
+        });
+        this.shadows = [];
+    }
+});
+
+Ext.define('Ext.Shadow', {
+    requires: ['Ext.ShadowPool'],
 
     
-    setTitle : function(title, iconCls){
-        this.title = title;
-        if(this.header && this.headerAsText){
-            this.header.child('span').update(title);
-        }
-        if(iconCls){
-            this.setIconClass(iconCls);
+    constructor: function(config) {
+        var me = this,
+            adjusts = {
+                h: 0
+            },
+            offset,
+            rad;
+        
+        Ext.apply(me, config);
+        if (!Ext.isString(me.mode)) {
+            me.mode = me.defaultMode;
+        }
+        offset = me.offset;
+        rad = Math.floor(offset / 2);
+        me.opacity = 50;
+        switch (me.mode.toLowerCase()) {
+            
+            case "drop":
+                if (Ext.supports.CSS3BoxShadow) {
+                    adjusts.w = adjusts.h = -offset;
+                    adjusts.l = adjusts.t = offset;
+                } else {
+                    adjusts.w = 0;
+                    adjusts.l = adjusts.t = offset;
+                    adjusts.t -= 1;
+                    if (Ext.isIE) {
+                        adjusts.l -= offset + rad;
+                        adjusts.t -= offset + rad;
+                        adjusts.w -= rad;
+                        adjusts.h -= rad;
+                        adjusts.t += 1;
+                    }
+                }
+                break;
+            case "sides":
+                if (Ext.supports.CSS3BoxShadow) {
+                    adjusts.h -= offset;
+                    adjusts.t = offset;
+                    adjusts.l = adjusts.w = 0;
+                } else {
+                    adjusts.w = (offset * 2);
+                    adjusts.l = -offset;
+                    adjusts.t = offset - 1;
+                    if (Ext.isIE) {
+                        adjusts.l -= (offset - rad);
+                        adjusts.t -= offset + rad;
+                        adjusts.l += 1;
+                        adjusts.w -= (offset - rad) * 2;
+                        adjusts.w -= rad + 1;
+                        adjusts.h -= 1;
+                    }
+                }
+                break;
+            case "frame":
+                if (Ext.supports.CSS3BoxShadow) {
+                    adjusts.l = adjusts.w = adjusts.t = 0;
+                } else {
+                    adjusts.w = adjusts.h = (offset * 2);
+                    adjusts.l = adjusts.t = -offset;
+                    adjusts.t += 1;
+                    adjusts.h -= 2;
+                    if (Ext.isIE) {
+                        adjusts.l -= (offset - rad);
+                        adjusts.t -= (offset - rad);
+                        adjusts.l += 1;
+                        adjusts.w -= (offset + rad + 1);
+                        adjusts.h -= (offset + rad);
+                        adjusts.h += 1;
+                    }
+                    break;
+                }
         }
-        this.fireEvent('titlechange', this, title);
-        return this;
+        me.adjusts = adjusts;
     },
 
     
-    getUpdater : function(){
-        return this.body.getUpdater();
-    },
+    
+    offset: 4,
 
-     
-    load : function(){
-        var um = this.body.getUpdater();
-        um.update.apply(um, arguments);
-        return this;
-    },
+    
+    defaultMode: "drop",
 
     
-    beforeDestroy : function(){
-        Ext.Panel.superclass.beforeDestroy.call(this);
-        if(this.header){
-            this.header.removeAllListeners();
-        }
-        if(this.tools){
-            for(var k in this.tools){
-                Ext.destroy(this.tools[k]);
-            }
-        }
-        if(this.toolbars.length > 0){
-            Ext.each(this.toolbars, function(tb){
-                tb.un('afterlayout', this.syncHeight, this);
-                tb.un('remove', this.syncHeight, this);
-            }, this);
-        }
-        if(Ext.isArray(this.buttons)){
-            while(this.buttons.length) {
-                Ext.destroy(this.buttons[0]);
+    show: function(target) {
+        var me = this,
+            index;
+        
+        target = Ext.get(target);
+        if (!me.el) {
+            me.el = Ext.ShadowPool.pull();
+            if (me.el.dom.nextSibling != target.dom) {
+                me.el.insertBefore(target);
             }
         }
-        if(this.rendered){
-            Ext.destroy(
-                this.ft,
-                this.header,
-                this.footer,
-                this.tbar,
-                this.bbar,
-                this.body,
-                this.mc,
-                this.bwrap,
-                this.dd
-            );
-            if (this.fbar) {
-                Ext.destroy(
-                    this.fbar,
-                    this.fbar.el
-                );
-            }
+        index = (parseInt(target.getStyle("z-index"), 10) - 1) || 0;
+        me.el.setStyle("z-index", me.zIndex || index);
+        if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
+            me.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=" + me.opacity + ") progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (me.offset) + ")";
         }
-        Ext.destroy(this.toolbars);
+        me.realign(
+            target.getLeft(true),
+            target.getTop(true),
+            target.dom.offsetWidth,
+            target.dom.offsetHeight
+        );
+        me.el.dom.style.display = "block";
     },
 
     
-    createClasses : function(){
-        this.headerCls = this.baseCls + '-header';
-        this.headerTextCls = this.baseCls + '-header-text';
-        this.bwrapCls = this.baseCls + '-bwrap';
-        this.tbarCls = this.baseCls + '-tbar';
-        this.bodyCls = this.baseCls + '-body';
-        this.bbarCls = this.baseCls + '-bbar';
-        this.footerCls = this.baseCls + '-footer';
+    isVisible: function() {
+        return this.el ? true: false;
     },
 
     
-    createGhost : function(cls, useShim, appendTo){
-        var el = document.createElement('div');
-        el.className = 'x-panel-ghost ' + (cls ? cls : '');
-        if(this.header){
-            el.appendChild(this.el.dom.firstChild.cloneNode(true));
-        }
-        Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
-        el.style.width = this.el.dom.offsetWidth + 'px';;
-        if(!appendTo){
-            this.container.dom.appendChild(el);
-        }else{
-            Ext.getDom(appendTo).appendChild(el);
+    realign: function(l, t, targetWidth, targetHeight) {
+        if (!this.el) {
+            return;
         }
-        if(useShim !== false && this.el.useShim !== false){
-            var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
-            layer.show();
-            return layer;
-        }else{
-            return new Ext.Element(el);
+        var adjusts = this.adjusts,
+            d = this.el.dom,
+            targetStyle = d.style,
+            shadowWidth,
+            shadowHeight,
+            cn,
+            sww, 
+            sws, 
+            shs;
+
+        targetStyle.left = (l + adjusts.l) + "px";
+        targetStyle.top = (t + adjusts.t) + "px";
+        shadowWidth = Math.max(targetWidth + adjusts.w, 0);
+        shadowHeight = Math.max(targetHeight + adjusts.h, 0);
+        sws = shadowWidth + "px";
+        shs = shadowHeight + "px";
+        if (targetStyle.width != sws || targetStyle.height != shs) {
+            targetStyle.width = sws;
+            targetStyle.height = shs;
+            if (Ext.supports.CSS3BoxShadow) {
+                targetStyle.boxShadow = '0 0 ' + this.offset + 'px 0 #888';
+            } else {
+
+                
+                if (!Ext.isIE) {
+                    cn = d.childNodes;
+                    sww = Math.max(0, (shadowWidth - 12)) + "px";
+                    cn[0].childNodes[1].style.width = sww;
+                    cn[1].childNodes[1].style.width = sww;
+                    cn[2].childNodes[1].style.width = sww;
+                    cn[1].style.height = Math.max(0, (shadowHeight - 12)) + "px";
+                }
+            }
         }
     },
 
     
-    doAutoLoad : function(){
-        var u = this.body.getUpdater();
-        if(this.renderer){
-            u.setRenderer(this.renderer);
+    hide: function() {
+        var me = this;
+        
+        if (me.el) {
+            me.el.dom.style.display = "none";
+            Ext.ShadowPool.push(me.el);
+            delete me.el;
         }
-        u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
     },
 
     
-    getTool : function(id) {
-        return this.tools[id];
+    setZIndex: function(z) {
+        this.zIndex = z;
+        if (this.el) {
+            this.el.setStyle("z-index", z);
+        }
+    },
+    
+    
+    setOpacity: function(opacity){
+        if (this.el) {
+            if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
+                opacity = Math.floor(opacity * 100 / 2) / 100;
+            }
+            this.opacity = opacity;
+            this.el.setOpacity(opacity);
+        }
     }
-
-
 });
-Ext.reg('panel', Ext.Panel);
 
-Ext.Editor = function(field, config){
-    if(field.field){
-        this.field = Ext.create(field.field, 'textfield');
-        config = Ext.apply({}, field); 
-        delete config.field;
-    }else{
-        this.field = field;
-    }
-    Ext.Editor.superclass.constructor.call(this, config);
-};
+Ext.define('Ext.button.Split', {
+
+    
+    alias: 'widget.splitbutton',
 
-Ext.extend(Ext.Editor, Ext.Component, {
+    extend: 'Ext.button.Button',
+    alternateClassName: 'Ext.SplitButton',
     
     
-    allowBlur: true,
     
     
+
+    
+    arrowCls      : 'split',
+    split         : true,
+
     
+    initComponent : function(){
+        this.callParent();
+        
+        this.addEvents("arrowclick");
+    },
+
     
+    setArrowHandler : function(handler, scope){
+        this.arrowHandler = handler;
+        this.scope = scope;
+    },
+
     
-    value : "",
+    onClick : function(e, t) {
+        var me = this;
+        
+        e.preventDefault();
+        if (!me.disabled) {
+            if (me.overMenuTrigger) {
+                me.maybeShowMenu();
+                me.fireEvent("arrowclick", me, e);
+                if (me.arrowHandler) {
+                    me.arrowHandler.call(me.scope || me, me, e);
+                }
+            } else {
+                me.doToggle();
+                me.fireHandler();
+            }
+        }
+    }
+});
+
+Ext.define('Ext.button.Cycle', {
+
     
-    alignment: "c-c?",
+
+    alias: 'widget.cycle',
+
+    extend: 'Ext.button.Split',
+    alternateClassName: 'Ext.CycleButton',
+
     
-    offsets: [0, 0],
+
     
-    shadow : "frame",
     
-    constrain : false,
     
-    swallowKeys : true,
     
-    completeOnEnter : true,
     
-    cancelOnEsc : true,
     
-    updateEl : false,
-
-    initComponent : function(){
-        Ext.Editor.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            "beforestartedit",
-            
-            "startedit",
-            
-            "beforecomplete",
-            
-            "complete",
-            
-            "canceledit",
-            
-            "specialkey"
-        );
-    },
 
     
-    onRender : function(ct, position){
-        this.el = new Ext.Layer({
-            shadow: this.shadow,
-            cls: "x-editor",
-            parentEl : ct,
-            shim : this.shim,
-            shadowOffset: this.shadowOffset || 4,
-            id: this.id,
-            constrain: this.constrain
-        });
-        if(this.zIndex){
-            this.el.setZIndex(this.zIndex);
-        }
-        this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
-        if(this.field.msgTarget != 'title'){
-            this.field.msgTarget = 'qtip';
-        }
-        this.field.inEditor = true;
-        this.mon(this.field, {
-            scope: this,
-            blur: this.onBlur,
-            specialkey: this.onSpecialKey
-        });
-        if(this.field.grow){
-            this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
-        }
-        this.field.render(this.el).show();
-        this.field.getEl().dom.name = '';
-        if(this.swallowKeys){
-            this.field.el.swallowEvent([
-                'keypress', 
-                'keydown'   
-            ]);
+    getButtonText: function(item) {
+        var me = this,
+            text = '';
+
+        if (item && me.showText === true) {
+            if (me.prependText) {
+                text += me.prependText;
+            }
+            text += item.text;
+            return text;
         }
+        return me.text;
     },
 
     
-    onSpecialKey : function(field, e){
-        var key = e.getKey(),
-            complete = this.completeOnEnter && key == e.ENTER,
-            cancel = this.cancelOnEsc && key == e.ESC;
-        if(complete || cancel){
-            e.stopEvent();
-            if(complete){
-                this.completeEdit();
-            }else{
-                this.cancelEdit();
+    setActiveItem: function(item, suppressEvent) {
+        var me = this;
+
+        if (!Ext.isObject(item)) {
+            item = me.menu.getComponent(item);
+        }
+        if (item) {
+            if (!me.rendered) {
+                me.text = me.getButtonText(item);
+                me.iconCls = item.iconCls;
+            } else {
+                me.setText(me.getButtonText(item));
+                me.setIconCls(item.iconCls);
+            }
+            me.activeItem = item;
+            if (!item.checked) {
+                item.setChecked(true, false);
+            }
+            if (me.forceIcon) {
+                me.setIconCls(me.forceIcon);
             }
-            if(field.triggerBlur){
-                field.triggerBlur();
+            if (!suppressEvent) {
+                me.fireEvent('change', me, item);
             }
         }
-        this.fireEvent('specialkey', field, e);
     },
 
     
-    startEdit : function(el, value){
-        if(this.editing){
-            this.completeEdit();
-        }
-        this.boundEl = Ext.get(el);
-        var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
-        if(!this.rendered){
-            this.render(this.parentEl || document.body);
-        }
-        if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
-            this.startValue = v;
-            this.field.reset();
-            this.field.setValue(v);
-            this.realign(true);
-            this.editing = true;
-            this.show();
-        }
+    getActiveItem: function() {
+        return this.activeItem;
     },
 
     
-    doAutoSize : function(){
-        if(this.autoSize){
-            var sz = this.boundEl.getSize(),
-                fs = this.field.getSize();
+    initComponent: function() {
+        var me = this,
+            checked = 0,
+            items;
 
-            switch(this.autoSize){
-                case "width":
-                    this.setSize(sz.width, fs.height);
-                    break;
-                case "height":
-                    this.setSize(fs.width, sz.height);
-                    break;
-                case "none":
-                    this.setSize(fs.width, fs.height);
-                    break;
-                default:
-                    this.setSize(sz.width, sz.height);
+        me.addEvents(
+            
+            "change"
+        );
+
+        if (me.changeHandler) {
+            me.on('change', me.changeHandler, me.scope || me);
+            delete me.changeHandler;
+        }
+
+        
+        
+        items = (me.menu.items||[]).concat(me.items||[]);
+        me.menu = Ext.applyIf({
+            cls: Ext.baseCSSPrefix + 'cycle-menu',
+            items: []
+        }, me.menu);
+
+        
+        Ext.each(items, function(item, i) {
+            item = Ext.applyIf({
+                group: me.id,
+                itemIndex: i,
+                checkHandler: me.checkHandler,
+                scope: me,
+                checked: item.checked || false
+            }, item);
+            me.menu.items.push(item);
+            if (item.checked) {
+                checked = i;
             }
+        });
+        me.itemCount = me.menu.items.length;
+        me.callParent(arguments);
+        me.on('click', me.toggleSelected, me);
+        me.setActiveItem(checked, me);
+
+        
+        if (me.width && me.showText) {
+            me.addCls(Ext.baseCSSPrefix + 'cycle-fixed-width');
         }
     },
 
     
-    setSize : function(w, h){
-        delete this.field.lastSize;
-        this.field.setSize(w, h);
-        if(this.el){
-            
-            if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
-                
-                this.el.setSize(w, h);
-            }
-            this.el.sync();
+    checkHandler: function(item, pressed) {
+        if (pressed) {
+            this.setActiveItem(item);
         }
     },
 
     
-    realign : function(autoSize){
-        if(autoSize === true){
-            this.doAutoSize();
-        }
-        this.el.alignTo(this.boundEl, this.alignment, this.offsets);
+    toggleSelected: function() {
+        var me = this,
+            m = me.menu,
+            checkItem;
+
+        checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0);
+        checkItem.setChecked(true);
+    }
+});
+
+Ext.define('Ext.container.ButtonGroup', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.buttongroup',
+    alternateClassName: 'Ext.ButtonGroup',
+
+    
+
+    
+    baseCls: Ext.baseCSSPrefix + 'btn-group',
+
+    
+    layout: {
+        type: 'table'
     },
 
+    defaultType: 'button',
+
     
-    completeEdit : function(remainVisible){
-        if(!this.editing){
-            return;
-        }
+    frame: true,
+
+    frameHeader: false,
+
+    internalDefaults: {removeMode: 'container', hideParent: true},
+
+    initComponent : function(){
         
-        if (this.field.assertValue) {
-            this.field.assertValue();
-        }
-        var v = this.getValue();
-        if(!this.field.isValid()){
-            if(this.revertInvalid !== false){
-                this.cancelEdit(remainVisible);
-            }
-            return;
-        }
-        if(String(v) === String(this.startValue) && this.ignoreNoChange){
-            this.hideEdit(remainVisible);
-            return;
-        }
-        if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
-            v = this.getValue();
-            if(this.updateEl && this.boundEl){
-                this.boundEl.update(v);
-            }
-            this.hideEdit(remainVisible);
-            this.fireEvent("complete", this, v, this.startValue);
+        var me = this,
+            cols = me.columns;
+
+        me.noTitleCls = me.baseCls + '-notitle';
+        if (cols) {
+            me.layout = Ext.apply({}, {columns: cols}, me.layout);
         }
-    },
 
-    
-    onShow : function(){
-        this.el.show();
-        if(this.hideEl !== false){
-            this.boundEl.hide();
+        if (!me.title) {
+            me.addCls(me.noTitleCls);
         }
-        this.field.show().focus(false, true);
-        this.fireEvent("startedit", this.boundEl, this.startValue);
+        me.callParent(arguments);
     },
 
-    
-    cancelEdit : function(remainVisible){
-        if(this.editing){
-            var v = this.getValue();
-            this.setValue(this.startValue);
-            this.hideEdit(remainVisible);
-            this.fireEvent("canceledit", this, v, this.startValue);
+    afterLayout: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        
+        
+        if (me.layout.table && (Ext.isIEQuirks || Ext.isIE6) && !me.width) {
+            var t = me.getTargetEl();
+            t.setWidth(me.layout.table.offsetWidth + t.getPadding('lr'));
         }
-    },
 
-    
-    hideEdit: function(remainVisible){
-        if(remainVisible !== true){
-            this.editing = false;
-            this.hide();
+        
+        if (Ext.isIE7) {
+            me.el.repaint();
         }
     },
 
-    
-    onBlur : function(){
+    afterRender: function() {
+        var me = this;
+
         
-        if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
-            this.completeEdit();
+        if (me.header) {
+            
+            delete me.header.items.items[0].flex;
+
+            
+            me.suspendLayout = true;
+            me.header.insert(1, {
+                xtype: 'component',
+                ui   : me.ui,
+                flex : 1
+            });
+            me.header.insert(0, {
+                xtype: 'component',
+                ui   : me.ui,
+                flex : 1
+            });
+            me.suspendLayout = false;
         }
+
+        me.callParent(arguments);
     },
 
     
-    onHide : function(){
-        if(this.editing){
-            this.completeEdit();
-            return;
-        }
-        this.field.blur();
-        if(this.field.collapse){
-            this.field.collapse();
-        }
-        this.el.hide();
-        if(this.hideEl !== false){
-            this.boundEl.show();
+    onBeforeAdd: function(component) {
+        if (component.is('button')) {
+            component.ui = component.ui + '-toolbar';
         }
+        this.callParent(arguments);
     },
 
     
-    setValue : function(v){
-        this.field.setValue(v);
-    },
+    applyDefaults: function(c) {
+        if (!Ext.isString(c)) {
+            c = this.callParent(arguments);
+            var d = this.internalDefaults;
+            if (c.events) {
+                Ext.applyIf(c.initialConfig, d);
+                Ext.apply(c, d);
+            } else {
+                Ext.applyIf(c, d);
+            }
+        }
+        return c;
+    }
 
     
-    getValue : function(){
-        return this.field.getValue();
-    },
+    
+    
+    
+    
+});
 
-    beforeDestroy : function(){
-        Ext.destroyMembers(this, 'field');
 
-        delete this.parentEl;
-        delete this.boundEl;
-    }
-});
-Ext.reg('editor', Ext.Editor);
+Ext.define('Ext.container.Viewport', {
+    extend: 'Ext.container.Container',
+    alias: 'widget.viewport',
+    requires: ['Ext.EventManager'],
+    alternateClassName: 'Ext.Viewport',
 
-Ext.ColorPalette = Ext.extend(Ext.Component, {
-       
     
-    itemCls : 'x-color-palette',
     
-    value : null,
     
-    clickEvent :'click',
+
     
-    ctype : 'Ext.ColorPalette',
 
     
-    allowReselect : false,
 
     
-    colors : [
-        '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
-        '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
-        'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
-        'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
-        'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
-    ],
 
     
+
     
+
     
+
     
-    initComponent : function(){
-        Ext.ColorPalette.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'select'
-        );
 
-        if(this.handler){
-            this.on('select', this.handler, this.scope, true);
-        }    
-    },
+    
 
     
-    onRender : function(container, position){
-        this.autoEl = {
-            tag: 'div',
-            cls: this.itemCls
-        };
-        Ext.ColorPalette.superclass.onRender.call(this, container, position);
-        var t = this.tpl || new Ext.XTemplate(
-            '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
-        );
-        t.overwrite(this.el, this.colors);
-        this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
-        if(this.clickEvent != 'click'){
-               this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
-        }
-    },
 
     
-    afterRender : function(){
-        Ext.ColorPalette.superclass.afterRender.call(this);
-        if(this.value){
-            var s = this.value;
-            this.value = null;
-            this.select(s, true);
-        }
-    },
 
     
-    handleClick : function(e, t){
-        e.preventDefault();
-        if(!this.disabled){
-            var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
-            this.select(c.toUpperCase());
-        }
+
+    isViewport: true,
+
+    ariaRole: 'application',
+
+    initComponent : function() {
+        var me = this,
+            html = Ext.fly(document.body.parentNode),
+            el;
+        me.callParent(arguments);
+        html.addCls(Ext.baseCSSPrefix + 'viewport');
+        if (me.autoScroll) {
+            html.setStyle('overflow', 'auto');
+        }
+        me.el = el = Ext.getBody();
+        el.setHeight = Ext.emptyFn;
+        el.setWidth = Ext.emptyFn;
+        el.setSize = Ext.emptyFn;
+        el.dom.scroll = 'no';
+        me.allowDomMove = false;
+        Ext.EventManager.onWindowResize(me.fireResize, me);
+        me.renderTo = me.el;
+        me.width = Ext.Element.getViewportWidth();
+        me.height = Ext.Element.getViewportHeight();
     },
 
-    
-    select : function(color, suppressEvent){
-        color = color.replace('#', '');
-        if(color != this.value || this.allowReselect){
-            var el = this.el;
-            if(this.value){
-                el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
-            }
-            el.child('a.color-'+color).addClass('x-color-palette-sel');
-            this.value = color;
-            if(suppressEvent !== true){
-                this.fireEvent('select', this, color);
-            }
-        }
+    fireResize : function(w, h){
+        
+        this.setSize(w, h);
     }
-
-    
 });
-Ext.reg('colorpalette', Ext.ColorPalette);
-Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
+
+
+
+
+
+Ext.define('Ext.dd.DDTarget', {
+    extend: 'Ext.dd.DragDrop',
+
     
-    todayText : 'Today',
+    constructor: function(id, sGroup, config) {
+        if (id) {
+            this.initTarget(id, sGroup, config);
+        }
+    },
+
     
-    okText : '&#160;OK&#160;',
+    getDragEl: Ext.emptyFn,
     
-    cancelText : 'Cancel',
+    isValidHandleChild: Ext.emptyFn,
     
+    startDrag: Ext.emptyFn,
     
+    endDrag: Ext.emptyFn,
     
-    todayTip : '{0} (Spacebar)',
+    onDrag: Ext.emptyFn,
     
-    minText : 'This date is before the minimum date',
+    onDragDrop: Ext.emptyFn,
     
-    maxText : 'This date is after the maximum date',
+    onDragEnter: Ext.emptyFn,
     
-    format : 'm/d/y',
+    onDragOut: Ext.emptyFn,
     
-    disabledDaysText : 'Disabled',
+    onDragOver: Ext.emptyFn,
     
-    disabledDatesText : 'Disabled',
+    onInvalidDrop: Ext.emptyFn,
     
-    monthNames : Date.monthNames,
+    onMouseDown: Ext.emptyFn,
     
-    dayNames : Date.dayNames,
+    onMouseUp: Ext.emptyFn,
     
-    nextText : 'Next Month (Control+Right)',
+    setXConstraint: Ext.emptyFn,
     
-    prevText : 'Previous Month (Control+Left)',
+    setYConstraint: Ext.emptyFn,
     
-    monthYearText : 'Choose a month (Control+Up/Down to move years)',
+    resetConstraints: Ext.emptyFn,
     
-    startDay : 0,
+    clearConstraints: Ext.emptyFn,
     
-    showToday : true,
+    clearTicks: Ext.emptyFn,
     
+    setInitPosition: Ext.emptyFn,
     
+    setDragElId: Ext.emptyFn,
     
+    setHandleElId: Ext.emptyFn,
     
+    setOuterHandleElId: Ext.emptyFn,
     
-
+    addInvalidHandleClass: Ext.emptyFn,
     
+    addInvalidHandleId: Ext.emptyFn,
     
-    focusOnSelect: true,
-
+    addInvalidHandleType: Ext.emptyFn,
     
+    removeInvalidHandleClass: Ext.emptyFn,
     
-    initHour: 12, 
-
+    removeInvalidHandleId: Ext.emptyFn,
     
-    initComponent : function(){
-        Ext.DatePicker.superclass.initComponent.call(this);
+    removeInvalidHandleType: Ext.emptyFn,
 
-        this.value = this.value ?
-                 this.value.clearTime(true) : new Date().clearTime();
+    toString: function() {
+        return ("DDTarget " + this.id);
+    }
+});
 
-        this.addEvents(
-            
-            'select'
-        );
+Ext.define('Ext.dd.DragTracker', {
 
-        if(this.handler){
-            this.on('select', this.handler,  this.scope || this);
-        }
+    uses: ['Ext.util.Region'],
 
-        this.initDisabledDays();
+    mixins: {
+        observable: 'Ext.util.Observable'
     },
 
     
-    initDisabledDays : function(){
-        if(!this.disabledDatesRE && this.disabledDates){
-            var dd = this.disabledDates,
-                len = dd.length - 1,
-                re = '(?:';
+    active: false,
 
-            Ext.each(dd, function(d, i){
-                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
-                if(i != len){
-                    re += '|';
-                }
-            }, this);
-            this.disabledDatesRE = new RegExp(re + ')');
-        }
-    },
+    
 
     
-    setDisabledDates : function(dd){
-        if(Ext.isArray(dd)){
-            this.disabledDates = dd;
-            this.disabledDatesRE = null;
-        }else{
-            this.disabledDatesRE = dd;
-        }
-        this.initDisabledDays();
-        this.update(this.value, true);
-    },
+    trackOver: false,
 
     
-    setDisabledDays : function(dd){
-        this.disabledDays = dd;
-        this.update(this.value, true);
-    },
 
     
-    setMinDate : function(dt){
-        this.minDate = dt;
-        this.update(this.value, true);
-    },
 
     
-    setMaxDate : function(dt){
-        this.maxDate = dt;
-        this.update(this.value, true);
-    },
+    tolerance: 5,
 
     
-    setValue : function(value){
-        this.value = value.clearTime(true);
-        this.update(this.value);
-    },
+    autoStart: false,
 
     
-    getValue : function(){
-        return this.value;
-    },
 
     
-    focus : function(){
-        this.update(this.activeDate);
-    },
 
     
-    onEnable: function(initial){
-        Ext.DatePicker.superclass.onEnable.call(this);
-        this.doDisabled(false);
-        this.update(initial ? this.value : this.activeDate);
-        if(Ext.isIE){
-            this.el.repaint();
-        }
 
-    },
+    constructor : function(config){
+        Ext.apply(this, config);
+        this.addEvents(
+            
+            'mouseover',
+
+            
+            'mouseout',
+
+            
+            'mousedown',
+
+            
+            'mouseup',
+
+            
+            'mousemove',
+
+            
+            'beforedragstart',
+
+            
+            'dragstart',
+
+            
+            'dragend',
 
-    
-    onDisable : function(){
-        Ext.DatePicker.superclass.onDisable.call(this);
-        this.doDisabled(true);
-        if(Ext.isIE && !Ext.isIE8){
             
-             Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
-                 Ext.fly(el).repaint();
-             });
+            'drag'
+        );
+
+        this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
+
+        if (this.el) {
+            this.initEl(this.el);
         }
-    },
 
-    
-    doDisabled : function(disabled){
-        this.keyNav.setDisabled(disabled);
-        this.prevRepeater.setDisabled(disabled);
-        this.nextRepeater.setDisabled(disabled);
-        if(this.showToday){
-            this.todayKeyListener.setDisabled(disabled);
-            this.todayBtn.setDisabled(disabled);
+        
+        this.mixins.observable.constructor.call(this);
+        if (this.disabled) {
+            this.disable();
         }
+
     },
 
     
-    onRender : function(container, position){
-        var m = [
-             '<table cellspacing="0">',
-                '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
-                '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
-                dn = this.dayNames,
-                i;
-        for(i = 0; i < 7; i++){
-            var d = this.startDay+i;
-            if(d > 6){
-                d = d-7;
-            }
-            m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
-        }
-        m[m.length] = '</tr></thead><tbody><tr>';
-        for(i = 0; i < 42; i++) {
-            if(i % 7 === 0 && i !== 0){
-                m[m.length] = '</tr><tr>';
-            }
-            m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
-        }
-        m.push('</tr></tbody></table></td></tr>',
-                this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
-                '</table><div class="x-date-mp"></div>');
-
-        var el = document.createElement('div');
-        el.className = 'x-date-picker';
-        el.innerHTML = m.join('');
+    initEl: function(el) {
+        this.el = Ext.get(el);
 
-        container.dom.insertBefore(el, position);
+        
+        this.handle = Ext.get(this.delegate);
 
-        this.el = Ext.get(el);
-        this.eventEl = Ext.get(el.firstChild);
+        
+        this.delegate = this.handle ? undefined : this.delegate;
 
-        this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
-            handler: this.showPrevMonth,
-            scope: this,
-            preventDefault:true,
-            stopDefault:true
-        });
+        if (!this.handle) {
+            this.handle = this.el;
+        }
 
-        this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
-            handler: this.showNextMonth,
-            scope: this,
-            preventDefault:true,
-            stopDefault:true
+        
+        
+        this.mon(this.handle, {
+            mousedown: this.onMouseDown,
+            delegate: this.delegate,
+            scope: this
         });
 
-        this.monthPicker = this.el.down('div.x-date-mp');
-        this.monthPicker.enableDisplayMode('block');
+        
+        
+        
+        if (this.trackOver || this.overCls) {
+            this.mon(this.handle, {
+                mouseover: this.onMouseOver,
+                mouseout: this.onMouseOut,
+                delegate: this.delegate,
+                scope: this
+            });
+        }
+    },
 
-        this.keyNav = new Ext.KeyNav(this.eventEl, {
-            'left' : function(e){
-                if(e.ctrlKey){
-                    this.showPrevMonth();
-                }else{
-                    this.update(this.activeDate.add('d', -1));
-                }
-            },
+    disable: function() {
+        this.disabled = true;
+    },
 
-            'right' : function(e){
-                if(e.ctrlKey){
-                    this.showNextMonth();
-                }else{
-                    this.update(this.activeDate.add('d', 1));
-                }
-            },
+    enable: function() {
+        this.disabled = false;
+    },
 
-            'up' : function(e){
-                if(e.ctrlKey){
-                    this.showNextYear();
-                }else{
-                    this.update(this.activeDate.add('d', -7));
-                }
-            },
+    destroy : function() {
+        this.clearListeners();
+        delete this.el;
+    },
 
-            'down' : function(e){
-                if(e.ctrlKey){
-                    this.showPrevYear();
-                }else{
-                    this.update(this.activeDate.add('d', 7));
+    
+    
+    onMouseOver: function(e, target) {
+        var me = this;
+        if (!me.disabled) {
+            if (Ext.EventManager.contains(e) || me.delegate) {
+                me.mouseIsOut = false;
+                if (me.overCls) {
+                    me.el.addCls(me.overCls);
                 }
-            },
+                me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle);
+            }
+        }
+    },
 
-            'pageUp' : function(e){
-                this.showNextMonth();
-            },
+    
+    
+    onMouseOut: function(e) {
+        if (this.mouseIsDown) {
+            this.mouseIsOut = true;
+        } else {
+            if (this.overCls) {
+                this.el.removeCls(this.overCls);
+            }
+            this.fireEvent('mouseout', this, e);
+        }
+    },
 
-            'pageDown' : function(e){
-                this.showPrevMonth();
-            },
+    onMouseDown: function(e, target){
+        
+        if (this.disabled ||e.dragTracked) {
+            return;
+        }
 
-            'enter' : function(e){
-                e.stopPropagation();
-                return true;
-            },
+        
+        this.dragTarget = this.delegate ? target : this.handle.dom;
+        this.startXY = this.lastXY = e.getXY();
+        this.startRegion = Ext.fly(this.dragTarget).getRegion();
 
-            scope : this
-        });
+        if (this.fireEvent('mousedown', this, e) === false ||
+            this.fireEvent('beforedragstart', this, e) === false ||
+            this.onBeforeStart(e) === false) {
+            return;
+        }
 
-        this.el.unselectable();
+        
+        
+        this.mouseIsDown = true;
 
-        this.cells = this.el.select('table.x-date-inner tbody td');
-        this.textNodes = this.el.query('table.x-date-inner tbody span');
+        
+        e.dragTracked = true;
 
-        this.mbtn = new Ext.Button({
-            text: '&#160;',
-            tooltip: this.monthYearText,
-            renderTo: this.el.child('td.x-date-middle', true)
+        if (this.preventDefault !== false) {
+            e.preventDefault();
+        }
+        Ext.getDoc().on({
+            scope: this,
+            mouseup: this.onMouseUp,
+            mousemove: this.onMouseMove,
+            selectstart: this.stopSelect
         });
-        this.mbtn.el.child('em').addClass('x-btn-arrow');
-
-        if(this.showToday){
-            this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
-            var today = (new Date()).dateFormat(this.format);
-            this.todayBtn = new Ext.Button({
-                renderTo: this.el.child('td.x-date-bottom', true),
-                text: String.format(this.todayText, today),
-                tooltip: String.format(this.todayTip, today),
-                handler: this.selectToday,
-                scope: this
-            });
+        if (this.autoStart) {
+            this.timer =  Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
         }
-        this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
-        this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
-        this.mon(this.mbtn, 'click', this.showMonthPicker, this);
-        this.onEnable(true);
     },
 
-    
-    createMonthPicker : function(){
-        if(!this.monthPicker.dom.firstChild){
-            var buf = ['<table border="0" cellspacing="0">'];
-            for(var i = 0; i < 6; i++){
-                buf.push(
-                    '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
-                    '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
-                    i === 0 ?
-                    '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
-                    '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
-                );
-            }
-            buf.push(
-                '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
-                    this.okText,
-                    '</button><button type="button" class="x-date-mp-cancel">',
-                    this.cancelText,
-                    '</button></td></tr>',
-                '</table>'
-            );
-            this.monthPicker.update(buf.join(''));
+    onMouseMove: function(e, target){
+        
+        
+        if (this.active && Ext.isIE && !e.browserEvent.button) {
+            e.preventDefault();
+            this.onMouseUp(e);
+            return;
+        }
 
-            this.mon(this.monthPicker, 'click', this.onMonthClick, this);
-            this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
+        e.preventDefault();
+        var xy = e.getXY(),
+            s = this.startXY;
 
-            this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
-            this.mpYears = this.monthPicker.select('td.x-date-mp-year');
+        this.lastXY = xy;
+        if (!this.active) {
+            if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
+                this.triggerStart(e);
+            } else {
+                return;
+            }
+        }
 
-            this.mpMonths.each(function(m, a, i){
-                i += 1;
-                if((i%2) === 0){
-                    m.dom.xmonth = 5 + Math.round(i * 0.5);
-                }else{
-                    m.dom.xmonth = Math.round((i-1) * 0.5);
-                }
-            });
+        
+        if (this.fireEvent('mousemove', this, e) === false) {
+            this.onMouseUp(e);
+        } else {
+            this.onDrag(e);
+            this.fireEvent('drag', this, e);
         }
     },
 
-    
-    showMonthPicker : function(){
-        if(!this.disabled){
-            this.createMonthPicker();
-            var size = this.el.getSize();
-            this.monthPicker.setSize(size);
-            this.monthPicker.child('table').setSize(size);
-
-            this.mpSelMonth = (this.activeDate || this.value).getMonth();
-            this.updateMPMonth(this.mpSelMonth);
-            this.mpSelYear = (this.activeDate || this.value).getFullYear();
-            this.updateMPYear(this.mpSelYear);
+    onMouseUp: function(e) {
+        
+        
+        this.mouseIsDown = false;
 
-            this.monthPicker.slideIn('t', {duration:0.2});
+        
+        if (this.mouseIsOut) {
+            this.mouseIsOut = false;
+            this.onMouseOut(e);
         }
+        e.preventDefault();
+        this.fireEvent('mouseup', this, e);
+        this.endDrag(e);
     },
 
     
-    updateMPYear : function(y){
-        this.mpyear = y;
-        var ys = this.mpYears.elements;
-        for(var i = 1; i <= 10; i++){
-            var td = ys[i-1], y2;
-            if((i%2) === 0){
-                y2 = y + Math.round(i * 0.5);
-                td.firstChild.innerHTML = y2;
-                td.xyear = y2;
-            }else{
-                y2 = y - (5-Math.round(i * 0.5));
-                td.firstChild.innerHTML = y2;
-                td.xyear = y2;
-            }
-            this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
+    endDrag: function(e) {
+        var doc = Ext.getDoc(),
+        wasActive = this.active;
+
+        doc.un('mousemove', this.onMouseMove, this);
+        doc.un('mouseup', this.onMouseUp, this);
+        doc.un('selectstart', this.stopSelect, this);
+        this.clearStart();
+        this.active = false;
+        if (wasActive) {
+            this.onEnd(e);
+            this.fireEvent('dragend', this, e);
         }
-    },
+        
+        delete this._constrainRegion;
 
-    
-    updateMPMonth : function(sm){
-        this.mpMonths.each(function(m, a, i){
-            m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
-        });
+        
+        delete Ext.EventObject.dragTracked;
     },
 
-    
-    selectMPMonth : function(m){
+    triggerStart: function(e) {
+        this.clearStart();
+        this.active = true;
+        this.onStart(e);
+        this.fireEvent('dragstart', this, e);
+    },
 
+    clearStart : function() {
+        if (this.timer) {
+            clearTimeout(this.timer);
+            delete this.timer;
+        }
     },
 
-    
-    onMonthClick : function(e, t){
+    stopSelect : function(e) {
         e.stopEvent();
-        var el = new Ext.Element(t), pn;
-        if(el.is('button.x-date-mp-cancel')){
-            this.hideMonthPicker();
-        }
-        else if(el.is('button.x-date-mp-ok')){
-            var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
-            if(d.getMonth() != this.mpSelMonth){
-                
-                d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
-            }
-            this.update(d);
-            this.hideMonthPicker();
-        }
-        else if((pn = el.up('td.x-date-mp-month', 2))){
-            this.mpMonths.removeClass('x-date-mp-sel');
-            pn.addClass('x-date-mp-sel');
-            this.mpSelMonth = pn.dom.xmonth;
-        }
-        else if((pn = el.up('td.x-date-mp-year', 2))){
-            this.mpYears.removeClass('x-date-mp-sel');
-            pn.addClass('x-date-mp-sel');
-            this.mpSelYear = pn.dom.xyear;
-        }
-        else if(el.is('a.x-date-mp-prev')){
-            this.updateMPYear(this.mpyear-10);
-        }
-        else if(el.is('a.x-date-mp-next')){
-            this.updateMPYear(this.mpyear+10);
-        }
+        return false;
     },
 
     
-    onMonthDblClick : function(e, t){
-        e.stopEvent();
-        var el = new Ext.Element(t), pn;
-        if((pn = el.up('td.x-date-mp-month', 2))){
-            this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
-            this.hideMonthPicker();
-        }
-        else if((pn = el.up('td.x-date-mp-year', 2))){
-            this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
-            this.hideMonthPicker();
-        }
+    onBeforeStart : function(e) {
+
     },
 
     
-    hideMonthPicker : function(disableAnim){
-        if(this.monthPicker){
-            if(disableAnim === true){
-                this.monthPicker.hide();
-            }else{
-                this.monthPicker.slideOut('t', {duration:0.2});
-            }
-        }
+    onStart : function(xy) {
+
     },
 
     
-    showPrevMonth : function(e){
-        this.update(this.activeDate.add('mo', -1));
+    onDrag : function(e) {
+
     },
 
     
-    showNextMonth : function(e){
-        this.update(this.activeDate.add('mo', 1));
+    onEnd : function(e) {
+
     },
 
     
-    showPrevYear : function(){
-        this.update(this.activeDate.add('y', -1));
+    getDragTarget : function(){
+        return this.dragTarget;
     },
 
     
-    showNextYear : function(){
-        this.update(this.activeDate.add('y', 1));
+    getDragCt : function(){
+        return this.el;
     },
 
     
-    handleMouseWheel : function(e){
-        e.stopEvent();
-        if(!this.disabled){
-            var delta = e.getWheelDelta();
-            if(delta > 0){
-                this.showPrevMonth();
-            } else if(delta < 0){
-                this.showNextMonth();
+    getConstrainRegion: function() {
+        if (this.constrainTo) {
+            if (this.constrainTo instanceof Ext.util.Region) {
+                return this.constrainTo;
+            }
+            if (!this._constrainRegion) {
+                this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
+            }
+        } else {
+            if (!this._constrainRegion) {
+                this._constrainRegion = this.getDragCt().getViewRegion();
             }
         }
+        return this._constrainRegion;
     },
 
-    
-    handleDateClick : function(e, t){
-        e.stopEvent();
-        if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
-            this.cancelFocus = this.focusOnSelect === false;
-            this.setValue(new Date(t.dateValue));
-            delete this.cancelFocus;
-            this.fireEvent('select', this, this.value);
-        }
+    getXY : function(constrain){
+        return constrain ? this.constrainModes[constrain](this, this.lastXY) : this.lastXY;
     },
 
     
-    selectToday : function(){
-        if(this.todayBtn && !this.todayBtn.disabled){
-            this.setValue(new Date().clearTime());
-            this.fireEvent('select', this, this.value);
-        }
+    getOffset : function(constrain){
+        var xy = this.getXY(constrain),
+            s = this.startXY;
+
+        return [xy[0]-s[0], xy[1]-s[1]];
     },
 
-    
-    update : function(date, forceRefresh){
-        if(this.rendered){
-            var vd = this.activeDate, vis = this.isVisible();
-            this.activeDate = date;
-            if(!forceRefresh && vd && this.el){
-                var t = date.getTime();
-                if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
-                    this.cells.removeClass('x-date-selected');
-                    this.cells.each(function(c){
-                       if(c.dom.firstChild.dateValue == t){
-                           c.addClass('x-date-selected');
-                           if(vis && !this.cancelFocus){
-                               Ext.fly(c.dom.firstChild).focus(50);
-                           }
-                           return false;
-                       }
-                    }, this);
-                    return;
-                }
-            }
-            var days = date.getDaysInMonth(),
-                firstOfMonth = date.getFirstDateOfMonth(),
-                startingPos = firstOfMonth.getDay()-this.startDay;
+    constrainModes: {
+        
+        point: function(me, xy) {
+            var dr = me.dragRegion,
+                constrainTo = me.getConstrainRegion();
 
-            if(startingPos < 0){
-                startingPos += 7;
+            
+            if (!constrainTo) {
+                return xy;
             }
-            days += startingPos;
 
-            var pm = date.add('mo', -1),
-                prevStart = pm.getDaysInMonth()-startingPos,
-                cells = this.cells.elements,
-                textEls = this.textNodes,
-                
-                d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
-                today = new Date().clearTime().getTime(),
-                sel = date.clearTime(true).getTime(),
-                min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
-                max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
-                ddMatch = this.disabledDatesRE,
-                ddText = this.disabledDatesText,
-                ddays = this.disabledDays ? this.disabledDays.join('') : false,
-                ddaysText = this.disabledDaysText,
-                format = this.format;
+            dr.x = dr.left = dr[0] = dr.right = xy[0];
+            dr.y = dr.top = dr[1] = dr.bottom = xy[1];
+            dr.constrainTo(constrainTo);
 
-            if(this.showToday){
-                var td = new Date().clearTime(),
-                    disable = (td < min || td > max ||
-                    (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
-                    (ddays && ddays.indexOf(td.getDay()) != -1));
+            return [dr.left, dr.top];
+        },
 
-                if(!this.disabled){
-                    this.todayBtn.setDisabled(disable);
-                    this.todayKeyListener[disable ? 'disable' : 'enable']();
-                }
+        
+        dragTarget: function(me, xy) {
+            var s = me.startXY,
+                dr = me.startRegion.copy(),
+                constrainTo = me.getConstrainRegion(),
+                adjust;
+
+            
+            if (!constrainTo) {
+                return xy;
             }
 
-            var setCellClass = function(cal, cell){
-                cell.title = '';
-                var t = d.clearTime(true).getTime();
-                cell.firstChild.dateValue = t;
-                if(t == today){
-                    cell.className += ' x-date-today';
-                    cell.title = cal.todayText;
-                }
-                if(t == sel){
-                    cell.className += ' x-date-selected';
-                    if(vis){
-                        Ext.fly(cell.firstChild).focus(50);
-                    }
-                }
-                
-                if(t < min) {
-                    cell.className = ' x-date-disabled';
-                    cell.title = cal.minText;
-                    return;
-                }
-                if(t > max) {
-                    cell.className = ' x-date-disabled';
-                    cell.title = cal.maxText;
-                    return;
-                }
-                if(ddays){
-                    if(ddays.indexOf(d.getDay()) != -1){
-                        cell.title = ddaysText;
-                        cell.className = ' x-date-disabled';
-                    }
-                }
-                if(ddMatch && format){
-                    var fvalue = d.dateFormat(format);
-                    if(ddMatch.test(fvalue)){
-                        cell.title = ddText.replace('%0', fvalue);
-                        cell.className = ' x-date-disabled';
-                    }
-                }
-            };
+            
+            
+            
+            dr.translateBy(xy[0]-s[0], xy[1]-s[1]);
 
-            var i = 0;
-            for(; i < startingPos; i++) {
-                textEls[i].innerHTML = (++prevStart);
-                d.setDate(d.getDate()+1);
-                cells[i].className = 'x-date-prevday';
-                setCellClass(this, cells[i]);
-            }
-            for(; i < days; i++){
-                var intDay = i - startingPos + 1;
-                textEls[i].innerHTML = (intDay);
-                d.setDate(d.getDate()+1);
-                cells[i].className = 'x-date-active';
-                setCellClass(this, cells[i]);
+            
+            if (dr.right > constrainTo.right) {
+                xy[0] += adjust = (constrainTo.right - dr.right);    
+                dr.left += adjust;
             }
-            var extraDays = 0;
-            for(; i < 42; i++) {
-                 textEls[i].innerHTML = (++extraDays);
-                 d.setDate(d.getDate()+1);
-                 cells[i].className = 'x-date-nextday';
-                 setCellClass(this, cells[i]);
+            if (dr.left < constrainTo.left) {
+                xy[0] += (constrainTo.left - dr.left);      
             }
 
-            this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
-
-            if(!this.internalRender){
-                var main = this.el.dom.firstChild,
-                    w = main.offsetWidth;
-                this.el.setWidth(w + this.el.getBorderWidth('lr'));
-                Ext.fly(main).setWidth(w);
-                this.internalRender = true;
-                
-                
-                
-                if(Ext.isOpera && !this.secondPass){
-                    main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
-                    this.secondPass = true;
-                    this.update.defer(10, this, [date]);
-                }
+            
+            if (dr.bottom > constrainTo.bottom) {
+                xy[1] += adjust = (constrainTo.bottom - dr.bottom);  
+                dr.top += adjust;
             }
-        }
-    },
-
-    
-    beforeDestroy : function() {
-        if(this.rendered){
-            Ext.destroy(
-                this.keyNav,
-                this.monthPicker,
-                this.eventEl,
-                this.mbtn,
-                this.nextRepeater,
-                this.prevRepeater,
-                this.cells.el,
-                this.todayBtn
-            );
-            delete this.textNodes;
-            delete this.cells.elements;
+            if (dr.top < constrainTo.top) {
+                xy[1] += (constrainTo.top - dr.top);        
+            }
+            return xy;
         }
     }
-
-    
 });
 
-Ext.reg('datepicker', Ext.DatePicker);
+Ext.define('Ext.dd.DragZone', {
 
-Ext.LoadMask = function(el, config){
-    this.el = Ext.get(el);
-    Ext.apply(this, config);
-    if(this.store){
-        this.store.on({
-            scope: this,
-            beforeload: this.onBeforeLoad,
-            load: this.onLoad,
-            exception: this.onLoad
-        });
-        this.removeMask = Ext.value(this.removeMask, false);
-    }else{
-        var um = this.el.getUpdater();
-        um.showLoadIndicator = false; 
-        um.on({
-            scope: this,
-            beforeupdate: this.onBeforeLoad,
-            update: this.onLoad,
-            failure: this.onLoad
-        });
-        this.removeMask = Ext.value(this.removeMask, true);
-    }
-};
+    extend: 'Ext.dd.DragSource',
 
-Ext.LoadMask.prototype = {
-    
-    
-    
-    msg : 'Loading...',
     
-    msgCls : 'x-mask-loading',
+    constructor : function(el, config){
+        this.callParent([el, config]);
+        if (this.containerScroll) {
+            Ext.dd.ScrollManager.register(this.el);
+        }
+    },
 
     
-    disabled: false,
 
     
-    disable : function(){
-       this.disabled = true;
-    },
 
     
-    enable : function(){
-        this.disabled = false;
+    getDragData : function(e){
+        return Ext.dd.Registry.getHandleFromEvent(e);
     },
 
     
-    onLoad : function(){
-        this.el.unmask(this.removeMask);
+    onInitDrag : function(x, y){
+        this.proxy.update(this.dragData.ddel.cloneNode(true));
+        this.onStartDrag(x, y);
+        return true;
     },
 
     
-    onBeforeLoad : function(){
-        if(!this.disabled){
-            this.el.mask(this.msg, this.msgCls);
+    afterRepair : function(){
+        var me = this;
+        if (Ext.enableFx) {
+            Ext.fly(me.dragData.ddel).highlight(me.repairHighlightColor);
         }
+        me.dragging = false;
     },
 
     
-    show: function(){
-        this.onBeforeLoad();
-    },
-
-    
-    hide: function(){
-        this.onLoad();
+    getRepairXY : function(e){
+        return Ext.Element.fly(this.dragData.ddel).getXY();
     },
 
-    
     destroy : function(){
-        if(this.store){
-            this.store.un('beforeload', this.onBeforeLoad, this);
-            this.store.un('load', this.onLoad, this);
-            this.store.un('exception', this.onLoad, this);
-        }else{
-            var um = this.el.getUpdater();
-            um.un('beforeupdate', this.onBeforeLoad, this);
-            um.un('update', this.onLoad, this);
-            um.un('failure', this.onLoad, this);
+        this.callParent();
+        if (this.containerScroll) {
+            Ext.dd.ScrollManager.unregister(this.el);
         }
     }
-};Ext.ns('Ext.slider');
-
-
-Ext.slider.Thumb = Ext.extend(Object, {
-
-    
-    constructor: function(config) {
-        
-        Ext.apply(this, config || {}, {
-            cls: 'x-slider-thumb',
-
-            
-            constrain: false
-        });
-
-        Ext.slider.Thumb.superclass.constructor.call(this, config);
+});
 
-        if (this.slider.vertical) {
-            Ext.apply(this, Ext.slider.Thumb.Vertical);
-        }
-    },
 
-    
-    render: function() {
-        this.el = this.slider.innerEl.insertFirst({cls: this.cls});
+Ext.define('Ext.dd.ScrollManager', {
+    singleton: true,
+    requires: [
+        'Ext.dd.DragDropManager'
+    ],
 
-        this.initEvents();
+    constructor: function() {
+        var ddm = Ext.dd.DragDropManager;
+        ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this);
+        ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this);
+        this.doScroll = Ext.Function.bind(this.doScroll, this);
+        this.ddmInstance = ddm;
+        this.els = {};
+        this.dragEl = null;
+        this.proc = {};
     },
 
-    
-    enable: function() {
-        this.disabled = false;
-        this.el.removeClass(this.slider.disabledClass);
+    onStop: function(e){
+        var sm = Ext.dd.ScrollManager;
+        sm.dragEl = null;
+        sm.clearProc();
     },
 
-    
-    disable: function() {
-        this.disabled = true;
-        this.el.addClass(this.slider.disabledClass);
+    triggerRefresh: function() {
+        if (this.ddmInstance.dragCurrent) {
+            this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups);
+        }
     },
 
-    
-    initEvents: function() {
-        var el = this.el;
-
-        el.addClassOnOver('x-slider-thumb-over');
+    doScroll: function() {
+        if (this.ddmInstance.dragCurrent) {
+            var proc   = this.proc,
+                procEl = proc.el,
+                ddScrollConfig = proc.el.ddScrollConfig,
+                inc = ddScrollConfig ? ddScrollConfig.increment : this.increment;
 
-        this.tracker = new Ext.dd.DragTracker({
-            onBeforeStart: this.onBeforeDragStart.createDelegate(this),
-            onStart      : this.onDragStart.createDelegate(this),
-            onDrag       : this.onDrag.createDelegate(this),
-            onEnd        : this.onDragEnd.createDelegate(this),
-            tolerance    : 3,
-            autoStart    : 300
-        });
-
-        this.tracker.initEl(el);
+            if (!this.animate) {
+                if (procEl.scroll(proc.dir, inc)) {
+                    this.triggerRefresh();
+                }
+            } else {
+                procEl.scroll(proc.dir, inc, true, this.animDuration, this.triggerRefresh);
+            }
+        }
     },
 
-    
-    onBeforeDragStart : function(e) {
-        if (this.disabled) {
-            return false;
-        } else {
-            this.slider.promoteThumb(this);
-            return true;
+    clearProc: function() {
+        var proc = this.proc;
+        if (proc.id) {
+            clearInterval(proc.id);
         }
+        proc.id = 0;
+        proc.el = null;
+        proc.dir = "";
     },
 
-    
-    onDragStart: function(e){
-        this.el.addClass('x-slider-thumb-drag');
-        this.dragging = true;
-        this.dragStartValue = this.value;
+    startProc: function(el, dir) {
+        this.clearProc();
+        this.proc.el = el;
+        this.proc.dir = dir;
+        var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
+            freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
+                  ? el.ddScrollConfig.frequency
+                  : this.frequency;
 
-        this.slider.fireEvent('dragstart', this.slider, e, this);
+        if (group === undefined || this.ddmInstance.dragCurrent.ddGroup == group) {
+            this.proc.id = setInterval(this.doScroll, freq);
+        }
     },
 
-    
-    onDrag: function(e) {
-        var slider   = this.slider,
-            index    = this.index,
-            newValue = this.getNewValue();
+    onFire: function(e, isDrop) {
+        if (isDrop || !this.ddmInstance.dragCurrent) {
+            return;
+        }
+        if (!this.dragEl || this.dragEl != this.ddmInstance.dragCurrent) {
+            this.dragEl = this.ddmInstance.dragCurrent;
+            
+            this.refreshCache();
+        }
 
-        if (this.constrain) {
-            var above = slider.thumbs[index + 1],
-                below = slider.thumbs[index - 1];
+        var xy = e.getXY(),
+            pt = e.getPoint(),
+            proc = this.proc,
+            els = this.els;
 
-            if (below != undefined && newValue <= below.value) newValue = below.value;
-            if (above != undefined && newValue >= above.value) newValue = above.value;
+        for (var id in els) {
+            var el = els[id], r = el._region;
+            var c = el.ddScrollConfig ? el.ddScrollConfig : this;
+            if (r && r.contains(pt) && el.isScrollable()) {
+                if (r.bottom - pt.y <= c.vthresh) {
+                    if(proc.el != el){
+                        this.startProc(el, "down");
+                    }
+                    return;
+                }else if (r.right - pt.x <= c.hthresh) {
+                    if (proc.el != el) {
+                        this.startProc(el, "left");
+                    }
+                    return;
+                } else if(pt.y - r.top <= c.vthresh) {
+                    if (proc.el != el) {
+                        this.startProc(el, "up");
+                    }
+                    return;
+                } else if(pt.x - r.left <= c.hthresh) {
+                    if (proc.el != el) {
+                        this.startProc(el, "right");
+                    }
+                    return;
+                }
+            }
         }
-
-        slider.setValue(index, newValue, false);
-        slider.fireEvent('drag', slider, e, this);
+        this.clearProc();
     },
 
-    getNewValue: function() {
-        var slider   = this.slider,
-            pos      = slider.innerEl.translatePoints(this.tracker.getXY());
-
-        return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
+    
+    register : function(el){
+        if (Ext.isArray(el)) {
+            for(var i = 0, len = el.length; i < len; i++) {
+                    this.register(el[i]);
+            }
+        } else {
+            el = Ext.get(el);
+            this.els[el.id] = el;
+        }
     },
 
     
-    onDragEnd: function(e) {
-        var slider = this.slider,
-            value  = this.value;
-
-        this.el.removeClass('x-slider-thumb-drag');
-
-        this.dragging = false;
-        slider.fireEvent('dragend', slider, e);
-
-        if (this.dragStartValue != value) {
-            slider.fireEvent('changecomplete', slider, value, this);
+    unregister : function(el){
+        if(Ext.isArray(el)){
+            for (var i = 0, len = el.length; i < len; i++) {
+                this.unregister(el[i]);
+            }
+        }else{
+            el = Ext.get(el);
+            delete this.els[el.id];
         }
     },
-    
-    
-    destroy: function(){
-        Ext.destroyMembers(this, 'tracker', 'el');
-    }
-});
-
 
-Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
-    
-    
-    vertical: false,
-    
-    minValue: 0,
-    
-    maxValue: 100,
-    
-    decimalPrecision: 0,
     
-    keyIncrement: 1,
+    vthresh : 25,
     
-    increment: 0,
+    hthresh : 25,
 
     
-    clickRange: [5,15],
+    increment : 100,
 
     
-    clickToChange : true,
-    
-    animate: true,
+    frequency : 500,
 
     
-    dragging: false,
+    animate: true,
 
     
-    constrainThumbs: true,
+    animDuration: 0.4,
 
     
-    topThumbZIndex: 10000,
+    ddGroup: undefined,
 
     
-    initComponent : function(){
-        if(!Ext.isDefined(this.value)){
-            this.value = this.minValue;
+    refreshCache : function(){
+        var els = this.els,
+            id;
+        for (id in els) {
+            if(typeof els[id] == 'object'){ 
+                els[id]._region = els[id].getRegion();
+            }
         }
+    }
+});
 
-        
-        this.thumbs = [];
-
-        Ext.slider.MultiSlider.superclass.initComponent.call(this);
-
-        this.keyIncrement = Math.max(this.increment, this.keyIncrement);
-        this.addEvents(
-            
-            'beforechange',
 
-            
-            'change',
+Ext.define('Ext.dd.DropTarget', {
+    extend: 'Ext.dd.DDTarget',
+    requires: ['Ext.dd.ScrollManager'],
 
-            
-            'changecomplete',
+    
+    constructor : function(el, config){
+        this.el = Ext.get(el);
 
-            
-            'dragstart',
+        Ext.apply(this, config);
 
-            
-            'drag',
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.register(this.el);
+        }
 
-            
-            'dragend'
-        );
+        this.callParent([this.el.dom, this.ddGroup || this.group,
+              {isTarget: true}]);
+    },
 
-        
-        if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
+    
+    
+    
+    dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
+    
+    dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
 
-        var values = this.values;
+    
+    isTarget : true,
 
-        for (var i=0; i < values.length; i++) {
-            this.addThumb(values[i]);
-        }
+    
+    isNotifyTarget : true,
 
-        if(this.vertical){
-            Ext.apply(this, Ext.slider.Vertical);
+    
+    notifyEnter : function(dd, e, data){
+        if(this.overClass){
+            this.el.addCls(this.overClass);
         }
+        return this.dropAllowed;
     },
 
     
-    addThumb: function(value) {
-        var thumb = new Ext.slider.Thumb({
-            value    : value,
-            slider   : this,
-            index    : this.thumbs.length,
-            constrain: this.constrainThumbs
-        });
-        this.thumbs.push(thumb);
-
-        
-        if (this.rendered) thumb.render();
+    notifyOver : function(dd, e, data){
+        return this.dropAllowed;
     },
 
     
-    promoteThumb: function(topThumb) {
-        var thumbs = this.thumbs,
-            zIndex, thumb;
-
-        for (var i = 0, j = thumbs.length; i < j; i++) {
-            thumb = thumbs[i];
-
-            if (thumb == topThumb) {
-                zIndex = this.topThumbZIndex;
-            } else {
-                zIndex = '';
-            }
-
-            thumb.el.setStyle('zIndex', zIndex);
+    notifyOut : function(dd, e, data){
+        if(this.overClass){
+            this.el.removeCls(this.overClass);
         }
     },
 
     
-    onRender : function() {
-        this.autoEl = {
-            cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
-            cn : {
-                cls: 'x-slider-end',
-                cn : {
-                    cls:'x-slider-inner',
-                    cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
-                }
-            }
-        };
-
-        Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
-
-        this.endEl   = this.el.first();
-        this.innerEl = this.endEl.first();
-        this.focusEl = this.innerEl.child('.x-slider-focus');
+    notifyDrop : function(dd, e, data){
+        return false;
+    },
 
-        
-        for (var i=0; i < this.thumbs.length; i++) {
-            this.thumbs[i].render();
+    destroy : function(){
+        this.callParent();
+        if(this.containerScroll){
+            Ext.dd.ScrollManager.unregister(this.el);
         }
+    }
+});
 
-        
-        var thumb      = this.innerEl.child('.x-slider-thumb');
-        this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
 
-        this.initEvents();
+Ext.define('Ext.dd.Registry', {
+    singleton: true,
+    constructor: function() {
+        this.elements = {}; 
+        this.handles = {}; 
+        this.autoIdSeed = 0;
     },
-
     
-    initEvents : function(){
-        this.mon(this.el, {
-            scope    : this,
-            mousedown: this.onMouseDown,
-            keydown  : this.onKeyDown
-        });
-
-        this.focusEl.swallowEvent("click", true);
+    getId: function(el, autogen){
+        if(typeof el == "string"){
+            return el;
+        }
+        var id = el.id;
+        if(!id && autogen !== false){
+            id = "extdd-" + (++this.autoIdSeed);
+            el.id = id;
+        }
+        return id;
     },
-
     
-    onMouseDown : function(e){
-        if(this.disabled){
-            return;
+    
+    register : function(el, data){
+        data = data || {};
+        if (typeof el == "string") {
+            el = document.getElementById(el);
         }
-
-        
-        var thumbClicked = false;
-        for (var i=0; i < this.thumbs.length; i++) {
-            thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
+        data.ddel = el;
+        this.elements[this.getId(el)] = data;
+        if (data.isHandle !== false) {
+            this.handles[data.ddel.id] = data;
         }
-
-        if (this.clickToChange && !thumbClicked) {
-            var local = this.innerEl.translatePoints(e.getXY());
-            this.onClickChange(local);
+        if (data.handles) {
+            var hs = data.handles;
+            for (var i = 0, len = hs.length; i < len; i++) {
+                this.handles[this.getId(hs[i])] = data;
+            }
         }
-        this.focus();
     },
 
     
-    onClickChange : function(local) {
-        if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
-            
-            var thumb = this.getNearest(local, 'left'),
-                index = thumb.index;
-
-            this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
+    unregister : function(el){
+        var id = this.getId(el, false);
+        var data = this.elements[id];
+        if(data){
+            delete this.elements[id];
+            if(data.handles){
+                var hs = data.handles;
+                for (var i = 0, len = hs.length; i < len; i++) {
+                    delete this.handles[this.getId(hs[i], false)];
+                }
+            }
         }
     },
 
     
-    getNearest: function(local, prop) {
-        var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
-            clickValue = this.reverseValue(localValue),
-            nearestDistance = (this.maxValue - this.minValue) + 5, 
-            index = 0,
-            nearest = null;
-
-        for (var i=0; i < this.thumbs.length; i++) {
-            var thumb = this.thumbs[i],
-                value = thumb.value,
-                dist  = Math.abs(value - clickValue);
-
-            if (Math.abs(dist <= nearestDistance)) {
-                nearest = thumb;
-                index = i;
-                nearestDistance = dist;
-            }
+    getHandle : function(id){
+        if(typeof id != "string"){ 
+            id = id.id;
         }
-        return nearest;
+        return this.handles[id];
     },
 
     
-    onKeyDown : function(e){
-        
-        if(this.disabled || this.thumbs.length !== 1){
-            e.preventDefault();
-            return;
-        }
-        var k = e.getKey(),
-            val;
-        switch(k){
-            case e.UP:
-            case e.RIGHT:
-                e.stopEvent();
-                val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
-                this.setValue(0, val, undefined, true);
-            break;
-            case e.DOWN:
-            case e.LEFT:
-                e.stopEvent();
-                val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
-                this.setValue(0, val, undefined, true);
-            break;
-            default:
-                e.preventDefault();
-        }
+    getHandleFromEvent : function(e){
+        var t = e.getTarget();
+        return t ? this.handles[t.id] : null;
     },
 
     
-    doSnap : function(value){
-        if (!(this.increment && value)) {
-            return value;
-        }
-        var newValue = value,
-            inc = this.increment,
-            m = value % inc;
-        if (m != 0) {
-            newValue -= m;
-            if (m * 2 >= inc) {
-                newValue += inc;
-            } else if (m * 2 < -inc) {
-                newValue -= inc;
-            }
+    getTarget : function(id){
+        if(typeof id != "string"){ 
+            id = id.id;
         }
-        return newValue.constrain(this.minValue,  this.maxValue);
+        return this.elements[id];
     },
 
     
-    afterRender : function(){
-        Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
-
-        for (var i=0; i < this.thumbs.length; i++) {
-            var thumb = this.thumbs[i];
+    getTargetFromEvent : function(e){
+        var t = e.getTarget();
+        return t ? this.elements[t.id] || this.handles[t.id] : null;
+    }
+});
 
-            if (thumb.value !== undefined) {
-                var v = this.normalizeValue(thumb.value);
+Ext.define('Ext.dd.DropZone', {
+    extend: 'Ext.dd.DropTarget',
+    requires: ['Ext.dd.Registry'],
 
-                if (v !== thumb.value) {
-                    
-                    this.setValue(i, v, false);
-                } else {
-                    this.moveThumb(i, this.translateValue(v), false);
-                }
-            }
-        };
+    
+    getTargetFromEvent : function(e){
+        return Ext.dd.Registry.getTargetFromEvent(e);
     },
 
     
-    getRatio : function(){
-        var w = this.innerEl.getWidth(),
-            v = this.maxValue - this.minValue;
-        return v == 0 ? w : (w/v);
+    onNodeEnter : function(n, dd, e, data){
+        
     },
 
     
-    normalizeValue : function(v){
-        v = this.doSnap(v);
-        v = Ext.util.Format.round(v, this.decimalPrecision);
-        v = v.constrain(this.minValue, this.maxValue);
-        return v;
+    onNodeOver : function(n, dd, e, data){
+        return this.dropAllowed;
     },
 
     
-    setMinValue : function(val){
-        this.minValue = val;
-        var i = 0,
-            thumbs = this.thumbs,
-            len = thumbs.length,
-            t;
-            
-        for(; i < len; ++i){
-            t = thumbs[i];
-            t.value = t.value < val ? val : t.value;
-        }
-        this.syncThumb();
+    onNodeOut : function(n, dd, e, data){
+        
     },
 
     
-    setMaxValue : function(val){
-        this.maxValue = val;
-        var i = 0,
-            thumbs = this.thumbs,
-            len = thumbs.length,
-            t;
-            
-        for(; i < len; ++i){
-            t = thumbs[i];
-            t.value = t.value > val ? val : t.value;
-        }
-        this.syncThumb();
+    onNodeDrop : function(n, dd, e, data){
+        return false;
     },
 
     
-    setValue : function(index, v, animate, changeComplete) {
-        var thumb = this.thumbs[index],
-            el    = thumb.el;
-
-        v = this.normalizeValue(v);
-
-        if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
-            thumb.value = v;
-            if(this.rendered){
-                this.moveThumb(index, this.translateValue(v), animate !== false);
-                this.fireEvent('change', this, v, thumb);
-                if(changeComplete){
-                    this.fireEvent('changecomplete', this, v, thumb);
-                }
-            }
-        }
+    onContainerOver : function(dd, e, data){
+        return this.dropNotAllowed;
     },
 
     
-    translateValue : function(v) {
-        var ratio = this.getRatio();
-        return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
+    onContainerDrop : function(dd, e, data){
+        return false;
     },
 
     
-    reverseValue : function(pos){
-        var ratio = this.getRatio();
-        return (pos + (this.minValue * ratio)) / ratio;
+    notifyEnter : function(dd, e, data){
+        return this.dropNotAllowed;
     },
 
     
-    moveThumb: function(index, v, animate){
-        var thumb = this.thumbs[index].el;
-
-        if(!animate || this.animate === false){
-            thumb.setLeft(v);
-        }else{
-            thumb.shift({left: v, stopFx: true, duration:.35});
+    notifyOver : function(dd, e, data){
+        var n = this.getTargetFromEvent(e);
+        if(!n) { 
+            if(this.lastOverNode){
+                this.onNodeOut(this.lastOverNode, dd, e, data);
+                this.lastOverNode = null;
+            }
+            return this.onContainerOver(dd, e, data);
+        }
+        if(this.lastOverNode != n){
+            if(this.lastOverNode){
+                this.onNodeOut(this.lastOverNode, dd, e, data);
+            }
+            this.onNodeEnter(n, dd, e, data);
+            this.lastOverNode = n;
         }
+        return this.onNodeOver(n, dd, e, data);
     },
 
     
-    focus : function(){
-        this.focusEl.focus(10);
+    notifyOut : function(dd, e, data){
+        if(this.lastOverNode){
+            this.onNodeOut(this.lastOverNode, dd, e, data);
+            this.lastOverNode = null;
+        }
     },
 
     
-    onResize : function(w, h){
-        var thumbs = this.thumbs,
-            len = thumbs.length,
-            i = 0;
-            
-        
-        for(; i < len; ++i){
-            thumbs[i].el.stopFx();    
-        }
-        
-        if(Ext.isNumber(w)){
-            this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
+    notifyDrop : function(dd, e, data){
+        if(this.lastOverNode){
+            this.onNodeOut(this.lastOverNode, dd, e, data);
+            this.lastOverNode = null;
         }
-        this.syncThumb();
-        Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
+        var n = this.getTargetFromEvent(e);
+        return n ?
+            this.onNodeDrop(n, dd, e, data) :
+            this.onContainerDrop(dd, e, data);
     },
 
     
-    onDisable: function(){
-        Ext.slider.MultiSlider.superclass.onDisable.call(this);
-
-        for (var i=0; i < this.thumbs.length; i++) {
-            var thumb = this.thumbs[i],
-                el    = thumb.el;
-
-            thumb.disable();
-
-            if(Ext.isIE){
-                
-                
-                var xy = el.getXY();
-                el.hide();
+    triggerCacheRefresh : function() {
+        Ext.dd.DDM.refreshCache(this.groups);
+    }
+});
 
-                this.innerEl.addClass(this.disabledClass).dom.disabled = true;
+Ext.define('Ext.flash.Component', {
+    extend: 'Ext.Component',
+    alternateClassName: 'Ext.FlashComponent',
+    alias: 'widget.flash',
 
-                if (!this.thumbHolder) {
-                    this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
-                }
+    
+    flashVersion : '9.0.115',
 
-                this.thumbHolder.show().setXY(xy);
-            }
-        }
-    },
+    
+    backgroundColor: '#ffffff',
 
     
-    onEnable: function(){
-        Ext.slider.MultiSlider.superclass.onEnable.call(this);
+    wmode: 'opaque',
 
-        for (var i=0; i < this.thumbs.length; i++) {
-            var thumb = this.thumbs[i],
-                el    = thumb.el;
+    
 
-            thumb.enable();
+    
 
-            if (Ext.isIE) {
-                this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
+    
 
-                if (this.thumbHolder) this.thumbHolder.hide();
+    
 
-                el.show();
-                this.syncThumb();
-            }
-        }
-    },
+    
+    swfWidth: '100%',
 
     
-    syncThumb : function() {
-        if (this.rendered) {
-            for (var i=0; i < this.thumbs.length; i++) {
-                this.moveThumb(i, this.translateValue(this.thumbs[i].value));
-            }
-        }
-    },
+    swfHeight: '100%',
 
     
-    getValue : function(index) {
-        return this.thumbs[index].value;
-    },
+    expressInstall: false,
 
     
-    getValues: function() {
-        var values = [];
 
-        for (var i=0; i < this.thumbs.length; i++) {
-            values.push(this.thumbs[i].value);
-        }
+    
+    renderTpl: ['<div id="{swfId}"></div>'],
 
-        return values;
-    },
+    initComponent: function() {
 
-    
-    beforeDestroy : function(){
-        var thumbs = this.thumbs;
-        for(var i = 0, len = thumbs.length; i < len; ++i){
-            thumbs[i].destroy();
-            thumbs[i] = null;
-        }
-        Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
-        Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
-    }
-});
+        this.callParent();
+        this.addEvents(
+            
+            'success',
 
-Ext.reg('multislider', Ext.slider.MultiSlider);
+            
+            'failure'
+        );
+    },
 
+    onRender: function() {
+        var me = this,
+            params, vars, undef,
+            swfId = me.getSwfId();
 
-Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
-    constructor: function(config) {
-      config = config || {};
+        me.renderData.swfId = swfId;
 
-      Ext.applyIf(config, {
-          values: [config.value || 0]
-      });
+        me.callParent(arguments);
 
-      Ext.slider.SingleSlider.superclass.constructor.call(this, config);
+        params = Ext.apply({
+            allowScriptAccess: 'always',
+            bgcolor: me.backgroundColor,
+            wmode: me.wmode
+        }, me.flashParams);
+
+        vars = Ext.apply({
+            allowedDomain: document.location.hostname
+        }, me.flashVars);
+
+        new swfobject.embedSWF(
+            me.url,
+            swfId,
+            me.swfWidth,
+            me.swfHeight,
+            me.flashVersion,
+            me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef,
+            vars,
+            params,
+            me.flashAttributes,
+            Ext.bind(me.swfCallback, me)
+        );
     },
 
     
-    getValue: function() {
-        
-        return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
+    swfCallback: function(e) {
+        var me = this;
+        if (e.success) {
+            me.swf = Ext.get(e.ref);
+            me.onSuccess();
+            me.fireEvent('success', me);
+        } else {
+            me.onFailure();
+            me.fireEvent('failure', me);
+        }
     },
 
     
-    setValue: function(value, animate) {
-        var args = Ext.toArray(arguments),
-            len  = args.length;
+    getSwfId: function() {
+        return this.swfId || (this.swfId = "extswf" + this.getAutoId());
+    },
 
+    onSuccess: function() {
         
         
-        
-        if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
-            args.unshift(0);
-        }
-
-        return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
+        this.swf.setStyle('visibility', 'inherit');
     },
 
-    
-    syncThumb : function() {
-        return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
+    onFailure: Ext.emptyFn,
+
+    beforeDestroy: function() {
+        var me = this,
+            swf = me.swf;
+        if (swf) {
+            swfobject.removeSWF(me.getSwfId());
+            Ext.destroy(swf);
+            delete me.swf;
+        }
+        me.callParent();
     },
-    
-    
-    getNearest : function(){
+
+    statics: {
         
-        return this.thumbs[0];    
+        EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf'
     }
 });
 
 
-Ext.Slider = Ext.slider.SingleSlider;
+Ext.define('Ext.form.action.Action', {
+    alternateClassName: 'Ext.form.Action',
+
+    
 
-Ext.reg('slider', Ext.slider.SingleSlider);
+    
 
+    
 
-Ext.slider.Vertical = {
-    onResize : function(w, h){
-        this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
-        this.syncThumb();
-    },
+    
 
-    getRatio : function(){
-        var h = this.innerEl.getHeight(),
-            v = this.maxValue - this.minValue;
-        return h/v;
-    },
+    
 
-    moveThumb: function(index, v, animate) {
-        var thumb = this.thumbs[index],
-            el    = thumb.el;
+    
 
-        if (!animate || this.animate === false) {
-            el.setBottom(v);
-        } else {
-            el.shift({bottom: v, stopFx: true, duration:.35});
-        }
-    },
+    
 
-    onClickChange : function(local) {
-        if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
-            var thumb = this.getNearest(local, 'top'),
-                index = thumb.index,
-                value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
+    
 
-            this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
-        }
-    }
-};
+    
 
+    
 
-Ext.slider.Thumb.Vertical = {
-    getNewValue: function() {
-        var slider   = this.slider,
-            innerEl  = slider.innerEl,
-            pos      = innerEl.translatePoints(this.tracker.getXY()),
-            bottom   = innerEl.getHeight() - pos.top;
+    
 
-        return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
-    }
-};
+    
 
-Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
-   
-    baseCls : 'x-progress',
     
+    submitEmptyText : true,
     
-    animate : false,
 
     
-    waitTimer : null,
 
     
-    initComponent : function(){
-        Ext.ProgressBar.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            "update"
-        );
-    },
 
     
-    onRender : function(ct, position){
-        var tpl = new Ext.Template(
-            '<div class="{cls}-wrap">',
-                '<div class="{cls}-inner">',
-                    '<div class="{cls}-bar">',
-                        '<div class="{cls}-text">',
-                            '<div>&#160;</div>',
-                        '</div>',
-                    '</div>',
-                    '<div class="{cls}-text {cls}-text-back">',
-                        '<div>&#160;</div>',
-                    '</div>',
-                '</div>',
-            '</div>'
-        );
 
-        this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
-            : tpl.append(ct, {cls: this.baseCls}, true);
-                
-        if(this.id){
-            this.el.dom.id = this.id;
+    
+    constructor: function(config) {
+        if (config) {
+            Ext.apply(this, config);
         }
-        var inner = this.el.dom.firstChild;
-        this.progressBar = Ext.get(inner.firstChild);
 
-        if(this.textEl){
-            
-            this.textEl = Ext.get(this.textEl);
-            delete this.textTopEl;
-        }else{
-            
-            this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
-            var textBackEl = Ext.get(inner.childNodes[1]);
-            this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
-            this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
-            this.textEl.setWidth(inner.offsetWidth);
+        
+        var params = config.params;
+        if (Ext.isString(params)) {
+            this.params = Ext.Object.fromQueryString(params);
         }
-        this.progressBar.setHeight(inner.offsetHeight);
     },
+
     
-    
-    afterRender : function(){
-        Ext.ProgressBar.superclass.afterRender.call(this);
-        if(this.value){
-            this.updateProgress(this.value, this.text);
-        }else{
-            this.updateText(this.text);
-        }
-    },
+    run: Ext.emptyFn,
 
     
-    updateProgress : function(value, text, animate){
-        this.value = value || 0;
-        if(text){
-            this.updateText(text);
-        }
-        if(this.rendered && !this.isDestroyed){
-            var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
-            this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
-            if(this.textTopEl){
-                
-                this.textTopEl.removeClass('x-hidden').setWidth(w);
-            }
-        }
-        this.fireEvent('update', this, value, text);
-        return this;
-    },
 
     
-    wait : function(o){
-        if(!this.waitTimer){
-            var scope = this;
-            o = o || {};
-            this.updateText(o.text);
-            this.waitTimer = Ext.TaskMgr.start({
-                run: function(i){
-                    var inc = o.increment || 10;
-                    i -= 1;
-                    this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
-                },
-                interval: o.interval || 1000,
-                duration: o.duration,
-                onStop: function(){
-                    if(o.fn){
-                        o.fn.apply(o.scope || this);
-                    }
-                    this.reset();
-                },
-                scope: scope
-            });
-        }
-        return this;
-    },
 
     
-    isWaiting : function(){
-        return this.waitTimer !== null;
+    onFailure : function(response){
+        this.response = response;
+        this.failureType = Ext.form.action.Action.CONNECT_FAILURE;
+        this.form.afterAction(this, false);
     },
 
     
-    updateText : function(text){
-        this.text = text || '&#160;';
-        if(this.rendered){
-            this.textEl.update(this.text);
+    processResponse : function(response){
+        this.response = response;
+        if (!response.responseText && !response.responseXML) {
+            return true;
         }
-        return this;
+        return (this.result = this.handleResponse(response));
     },
+
     
-    
-    syncProgressBar : function(){
-        if(this.value){
-            this.updateProgress(this.value, this.text);
-        }
-        return this;
+    getUrl: function() {
+        return this.url || this.form.url;
     },
 
     
-    setSize : function(w, h){
-        Ext.ProgressBar.superclass.setSize.call(this, w, h);
-        if(this.textTopEl){
-            var inner = this.el.dom.firstChild;
-            this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
-        }
-        this.syncProgressBar();
-        return this;
+    getMethod: function() {
+        return (this.method || this.form.method || 'POST').toUpperCase();
     },
 
     
-    reset : function(hide){
-        this.updateProgress(0);
-        if(this.textTopEl){
-            this.textTopEl.addClass('x-hidden');
-        }
-        this.clearTimer();
-        if(hide === true){
-            this.hide();
-        }
-        return this;
+    getParams: function() {
+        return Ext.apply({}, this.params, this.form.baseParams);
     },
+
     
-    
-    clearTimer : function(){
-        if(this.waitTimer){
-            this.waitTimer.onStop = null; 
-            Ext.TaskMgr.stop(this.waitTimer);
-            this.waitTimer = null;
-        }
+    createCallback: function() {
+        var me = this,
+            undef,
+            form = me.form;
+        return {
+            success: me.onSuccess,
+            failure: me.onFailure,
+            scope: me,
+            timeout: (this.timeout * 1000) || (form.timeout * 1000),
+            upload: form.fileUpload ? me.onSuccess : undef
+        };
     },
-    
-    onDestroy: function(){
-        this.clearTimer();
-        if(this.rendered){
-            if(this.textEl.isComposite){
-                this.textEl.clear();
-            }
-            Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
-        }
-        Ext.ProgressBar.superclass.onDestroy.call(this);
-    }
-});
-Ext.reg('progress', Ext.ProgressBar);
 
-(function() {
+    statics: {
+        
+        CLIENT_INVALID: 'client',
+
+        
+        SERVER_INVALID: 'server',
+
+        
+        CONNECT_FAILURE: 'connect',
 
-var Event=Ext.EventManager;
-var Dom=Ext.lib.Dom;
+        
+        LOAD_FAILURE: 'load'
 
 
-Ext.dd.DragDrop = function(id, sGroup, config) {
-    if(id) {
-        this.init(id, sGroup, config);
     }
-};
+});
 
-Ext.dd.DragDrop.prototype = {
 
-    
+Ext.define('Ext.form.action.Submit', {
+    extend:'Ext.form.action.Action',
+    alternateClassName: 'Ext.form.Action.Submit',
+    alias: 'formaction.submit',
 
-    
-    id: null,
+    type: 'submit',
 
     
-    config: null,
 
     
-    dragElId: null,
+    run : function(){
+        var form = this.form;
+        if (this.clientValidation === false || form.isValid()) {
+            this.doSubmit();
+        } else {
+            
+            this.failureType = Ext.form.action.Action.CLIENT_INVALID;
+            form.afterAction(this, false);
+        }
+    },
 
     
-    handleElId: null,
+    doSubmit: function() {
+        var formEl,
+            ajaxOptions = Ext.apply(this.createCallback(), {
+                url: this.getUrl(),
+                method: this.getMethod(),
+                headers: this.headers
+            });
 
-    
-    invalidHandleTypes: null,
+        
+        
+        if (this.form.hasUpload()) {
+            formEl = ajaxOptions.form = this.buildForm();
+            ajaxOptions.isUpload = true;
+        } else {
+            ajaxOptions.params = this.getParams();
+        }
 
-    
-    invalidHandleIds: null,
+        Ext.Ajax.request(ajaxOptions);
 
-    
-    invalidHandleClasses: null,
+        if (formEl) {
+            Ext.removeNode(formEl);
+        }
+    },
 
     
-    startPageX: 0,
+    getParams: function() {
+        var nope = false,
+            configParams = this.callParent(),
+            fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
+        return Ext.apply({}, fieldParams, configParams);
+    },
 
     
-    startPageY: 0,
+    buildForm: function() {
+        var fieldsSpec = [],
+            formSpec,
+            formEl,
+            basicForm = this.form,
+            params = this.getParams(),
+            uploadFields = [];
 
-    
-    groups: null,
+        basicForm.getFields().each(function(field) {
+            if (field.isFileUpload()) {
+                uploadFields.push(field);
+            }
+        });
 
-    
-    locked: false,
+        function addField(name, val) {
+            fieldsSpec.push({
+                tag: 'input',
+                type: 'hidden',
+                name: name,
+                value: Ext.String.htmlEncode(val)
+            });
+        }
 
-    
-    lock: function() {
-        this.locked = true;
+        
+        Ext.iterate(params, function(key, val) {
+            if (Ext.isArray(val)) {
+                Ext.each(val, function(v) {
+                    addField(key, v);
+                });
+            } else {
+                addField(key, val);
+            }
+        });
+
+        formSpec = {
+            tag: 'form',
+            action: this.getUrl(),
+            method: this.getMethod(),
+            target: this.target || '_self',
+            style: 'display:none',
+            cn: fieldsSpec
+        };
+
+        
+        if (uploadFields.length) {
+            formSpec.encoding = formSpec.enctype = 'multipart/form-data';
+        }
+
+        
+        formEl = Ext.DomHelper.append(Ext.getBody(), formSpec);
+
+        
+        
+        
+        Ext.Array.each(uploadFields, function(field) {
+            if (field.rendered) { 
+                formEl.appendChild(field.extractFileInput());
+            }
+        });
+
+        return formEl;
     },
 
-    
-    moveOnly: false,
+
 
     
-    unlock: function() {
-        this.locked = false;
+    onSuccess: function(response) {
+        var form = this.form,
+            success = true,
+            result = this.processResponse(response);
+        if (result !== true && !result.success) {
+            if (result.errors) {
+                form.markInvalid(result.errors);
+            }
+            this.failureType = Ext.form.action.Action.SERVER_INVALID;
+            success = false;
+        }
+        form.afterAction(this, success);
     },
 
     
-    isTarget: true,
+    handleResponse: function(response) {
+        var form = this.form,
+            errorReader = form.errorReader,
+            rs, errors, i, len, records;
+        if (errorReader) {
+            rs = errorReader.read(response);
+            records = rs.records;
+            errors = [];
+            if (records) {
+                for(i = 0, len = records.length; i < len; i++) {
+                    errors[i] = records[i].data;
+                }
+            }
+            if (errors.length < 1) {
+                errors = null;
+            }
+            return {
+                success : rs.success,
+                errors : errors
+            };
+        }
+        return Ext.decode(response.responseText);
+    }
+});
 
-    
-    padding: null,
 
-    
-    _domRef: null,
+Ext.define('Ext.util.ComponentDragger', {
 
     
-    __ygDragDrop: true,
 
     
-    constrainX: false,
 
     
-    constrainY: false,
 
-    
-    minX: 0,
+    extend: 'Ext.dd.DragTracker',
 
-    
-    maxX: 0,
+    autoStart: 500,
 
     
-    minY: 0,
+    constructor: function(comp, config) {
+        this.comp = comp;
+        this.initialConstrainTo = config.constrainTo;
+        this.callParent([ config ]);
+    },
 
-    
-    maxY: 0,
+    onStart: function(e) {
+        var me = this,
+            comp = me.comp;
 
-    
-    maintainOffset: false,
+        
+        this.startPosition = comp.getPosition();
 
-    
-    xTicks: null,
+        
+        
+        if (comp.ghost && !comp.liveDrag) {
+             me.proxy = comp.ghost();
+             me.dragTarget = me.proxy.header.el;
+        }
 
-    
-    yTicks: null,
+        
+        if (me.constrain || me.constrainDelegate) {
+            me.constrainTo = me.calculateConstrainRegion();
+        }
+    },
 
-    
-    primaryButtonOnly: true,
+    calculateConstrainRegion: function() {
+        var me = this,
+            comp = me.comp,
+            c = me.initialConstrainTo,
+            delegateRegion,
+            elRegion,
+            shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
 
-    
-    available: false,
+        
+        if (!(c instanceof Ext.util.Region)) {
+            c =  Ext.fly(c).getViewRegion();
+        }
 
-    
-    hasOuterHandles: false,
+        
+        if (shadowSize) {
+            c.adjust(0, -shadowSize, -shadowSize, shadowSize);
+        }
 
-    
-    b4StartDrag: function(x, y) { },
+        
+        
+        
+        if (!me.constrainDelegate) {
+            delegateRegion = Ext.fly(me.dragTarget).getRegion();
+            elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
 
-    
-    startDrag: function(x, y) {  },
+            c.adjust(
+                delegateRegion.top - elRegion.top,
+                delegateRegion.right - elRegion.right,
+                delegateRegion.bottom - elRegion.bottom,
+                delegateRegion.left - elRegion.left
+            );
+        }
+        return c;
+    },
 
     
-    b4Drag: function(e) { },
+    onDrag: function(e) {
+        var me = this,
+            comp = (me.proxy && !me.comp.liveDrag) ? me.proxy : me.comp,
+            offset = me.getOffset(me.constrain || me.constrainDelegate ? 'dragTarget' : null);
 
-    
-    onDrag: function(e) {  },
+        comp.setPosition(me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]);
+    },
 
-    
-    onDragEnter: function(e, id) {  },
+    onEnd: function(e) {
+        if (this.proxy && !this.comp.liveDrag) {
+            this.comp.unghost();
+        }
+    }
+});
 
-    
-    b4DragOver: function(e) { },
+Ext.define("Ext.form.Labelable", {
+    requires: ['Ext.XTemplate'],
 
     
-    onDragOver: function(e, id) {  },
+    labelableRenderTpl: [
+        '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
+            '<label id="{id}-labelEl"<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"',
+                '<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
+                '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
+            '</label>',
+        '</tpl>',
+        '<div class="{baseBodyCls} {fieldBodyCls}" id="{id}-bodyEl" role="presentation">{subTplMarkup}</div>',
+        '<div id="{id}-errorEl" class="{errorMsgCls}" style="display:none"></div>',
+        '<div class="{clearCls}" role="presentation"><!-- --></div>',
+        {
+            compiled: true,
+            disableFormats: true
+        }
+    ],
 
     
-    b4DragOut: function(e) { },
+    activeErrorsTpl: [
+        '<tpl if="errors && errors.length">',
+            '<ul><tpl for="errors"><li<tpl if="xindex == xcount"> class="last"</tpl>>{.}</li></tpl></ul>',
+        '</tpl>'
+    ],
 
     
-    onDragOut: function(e, id) {  },
+    isFieldLabelable: true,
 
     
-    b4DragDrop: function(e) { },
+    formItemCls: Ext.baseCSSPrefix + 'form-item',
 
     
-    onDragDrop: function(e, id) {  },
+    labelCls: Ext.baseCSSPrefix + 'form-item-label',
 
     
-    onInvalidDrop: function(e) {  },
 
     
-    b4EndDrag: function(e) { },
+    errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg',
 
     
-    endDrag: function(e) {  },
+    baseBodyCls: Ext.baseCSSPrefix + 'form-item-body',
 
     
-    b4MouseDown: function(e) {  },
+    fieldBodyCls: '',
 
     
-    onMouseDown: function(e) {  },
+    clearCls: Ext.baseCSSPrefix + 'clear',
 
     
-    onMouseUp: function(e) {  },
+    invalidCls : Ext.baseCSSPrefix + 'form-invalid',
 
     
-    onAvailable: function () {
-    },
+    fieldLabel: undefined,
 
     
-    defaultPadding : {left:0, right:0, top:0, bottom:0},
+    labelAlign : 'left',
 
     
-    constrainTo : function(constrainTo, pad, inContent){
-        if(Ext.isNumber(pad)){
-            pad = {left: pad, right:pad, top:pad, bottom:pad};
-        }
-        pad = pad || this.defaultPadding;
-        var b = Ext.get(this.getEl()).getBox(),
-            ce = Ext.get(constrainTo),
-            s = ce.getScroll(),
-            c, 
-            cd = ce.dom;
-        if(cd == document.body){
-            c = { x: s.left, y: s.top, width: Ext.lib.Dom.getViewWidth(), height: Ext.lib.Dom.getViewHeight()};
-        }else{
-            var xy = ce.getXY();
-            c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
-        }
-
-
-        var topSpace = b.y - c.y,
-            leftSpace = b.x - c.x;
-
-        this.resetConstraints();
-        this.setXConstraint(leftSpace - (pad.left||0), 
-                c.width - leftSpace - b.width - (pad.right||0), 
-                               this.xTickSize
-        );
-        this.setYConstraint(topSpace - (pad.top||0), 
-                c.height - topSpace - b.height - (pad.bottom||0), 
-                               this.yTickSize
-        );
-    },
+    labelWidth: 100,
 
     
-    getEl: function() {
-        if (!this._domRef) {
-            this._domRef = Ext.getDom(this.id);
-        }
-
-        return this._domRef;
-    },
+    labelPad : 5,
 
     
-    getDragEl: function() {
-        return Ext.getDom(this.dragElId);
-    },
+    labelSeparator : ':',
 
     
-    init: function(id, sGroup, config) {
-        this.initTarget(id, sGroup, config);
-        Event.on(this.id, "mousedown", this.handleMouseDown, this);
-        
-    },
 
     
-    initTarget: function(id, sGroup, config) {
-
-        
-        this.config = config || {};
-
-        
-        this.DDM = Ext.dd.DDM;
-        
-        this.groups = {};
+    hideLabel: false,
 
-        
-        
-        if (typeof id !== "string") {
-            id = Ext.id(id);
-        }
+    
+    hideEmptyLabel: true,
 
-        
-        this.id = id;
+    
+    preventMark: false,
 
-        
-        this.addToGroup((sGroup) ? sGroup : "default");
+    
+    autoFitErrors: true,
 
-        
-        
-        this.handleElId = id;
+    
+    msgTarget: 'qtip',
 
-        
-        this.setDragElId(id);
+    
 
-        
-        this.invalidHandleTypes = { A: "A" };
-        this.invalidHandleIds = {};
-        this.invalidHandleClasses = [];
 
-        this.applyConfig();
+    
+    initLabelable: function() {
+        this.addCls(this.formItemCls);
 
-        this.handleOnAvailable();
+        this.addEvents(
+            
+            'errorchange'
+        );
     },
 
     
-    applyConfig: function() {
-
-        
-        
-        this.padding           = this.config.padding || [0, 0, 0, 0];
-        this.isTarget          = (this.config.isTarget !== false);
-        this.maintainOffset    = (this.config.maintainOffset);
-        this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
-
+    getFieldLabel: function() {
+        return this.fieldLabel || '';
     },
 
     
-    handleOnAvailable: function() {
-        this.available = true;
-        this.resetConstraints();
-        this.onAvailable();
-    },
+    getLabelableRenderData: function() {
+        var me = this,
+            labelAlign = me.labelAlign,
+            labelCls = me.labelCls,
+            labelClsExtra = me.labelClsExtra,
+            labelPad = me.labelPad,
+            labelStyle;
 
-     
-    setPadding: function(iTop, iRight, iBot, iLeft) {
         
-        if (!iRight && 0 !== iRight) {
-            this.padding = [iTop, iTop, iTop, iTop];
-        } else if (!iBot && 0 !== iBot) {
-            this.padding = [iTop, iRight, iTop, iRight];
+        
+        if (labelAlign === 'top') {
+            labelStyle = 'margin-bottom:' + labelPad + 'px;';
         } else {
-            this.padding = [iTop, iRight, iBot, iLeft];
-        }
-    },
-
-    
-    setInitPosition: function(diffX, diffY) {
-        var el = this.getEl();
-
-        if (!this.DDM.verifyEl(el)) {
-            return;
+            labelStyle = 'margin-right:' + labelPad + 'px;';
+            
+            if (Ext.isBorderBox) {
+                labelStyle += 'width:' + me.labelWidth + 'px;';
+            }
         }
 
-        var dx = diffX || 0;
-        var dy = diffY || 0;
+        return Ext.copyTo(
+            {
+                inputId: me.getInputId(),
+                fieldLabel: me.getFieldLabel(),
+                labelCls: labelClsExtra ? labelCls + ' ' + labelClsExtra : labelCls,
+                labelStyle: labelStyle + (me.labelStyle || ''),
+                subTplMarkup: me.getSubTplMarkup()
+            },
+            me,
+            'hideLabel,hideEmptyLabel,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
+            true
+        );
+    },
 
-        var p = Dom.getXY( el );
+    onLabelableRender: function () {
+        this.addChildEls(
+            
+            'labelEl',
 
-        this.initPageX = p[0] - dx;
-        this.initPageY = p[1] - dy;
+            
+            'bodyEl',
 
-        this.lastPageX = p[0];
-        this.lastPageY = p[1];
+            
+            'errorEl'
+        );
+    },
 
-        this.setStartPosition(p);
+    
+    getSubTplMarkup: function() {
+        return '';
     },
 
     
-    setStartPosition: function(pos) {
-        var p = pos || Dom.getXY( this.getEl() );
-        this.deltaSetXY = null;
+    getInputId: function() {
+        return '';
+    },
 
-        this.startPageX = p[0];
-        this.startPageY = p[1];
+    
+    getActiveError : function() {
+        return this.activeError || '';
     },
 
     
-    addToGroup: function(sGroup) {
-        this.groups[sGroup] = true;
-        this.DDM.regDragDrop(this, sGroup);
+    hasActiveError: function() {
+        return !!this.getActiveError();
     },
 
     
-    removeFromGroup: function(sGroup) {
-        if (this.groups[sGroup]) {
-            delete this.groups[sGroup];
-        }
+    setActiveError: function(msg) {
+        this.activeError = msg;
+        this.activeErrors = [msg];
+        this.renderActiveError();
+    },
 
-        this.DDM.removeDDFromGroup(this, sGroup);
+    
+    getActiveErrors: function() {
+        return this.activeErrors || [];
     },
 
     
-    setDragElId: function(id) {
-        this.dragElId = id;
+    setActiveErrors: function(errors) {
+        this.activeErrors = errors;
+        this.activeError = this.getTpl('activeErrorsTpl').apply({errors: errors});
+        this.renderActiveError();
     },
 
     
-    setHandleElId: function(id) {
-        if (typeof id !== "string") {
-            id = Ext.id(id);
-        }
-        this.handleElId = id;
-        this.DDM.regHandle(this.id, id);
+    unsetActiveError: function() {
+        delete this.activeError;
+        delete this.activeErrors;
+        this.renderActiveError();
     },
 
     
-    setOuterHandleElId: function(id) {
-        if (typeof id !== "string") {
-            id = Ext.id(id);
+    renderActiveError: function() {
+        var me = this,
+            activeError = me.getActiveError(),
+            hasError = !!activeError;
+
+        if (activeError !== me.lastActiveError) {
+            me.fireEvent('errorchange', me, activeError);
+            me.lastActiveError = activeError;
         }
-        Event.on(id, "mousedown",
-                this.handleMouseDown, this);
-        this.setHandleElId(id);
 
-        this.hasOuterHandles = true;
-    },
+        if (me.rendered && !me.isDestroyed && !me.preventMark) {
+            
+            me.el[hasError ? 'addCls' : 'removeCls'](me.invalidCls);
 
-    
-    unreg: function() {
-        Event.un(this.id, "mousedown",
-                this.handleMouseDown);
-        this._domRef = null;
-        this.DDM._remove(this);
-    },
+            
+            me.getActionEl().dom.setAttribute('aria-invalid', hasError);
 
-    destroy : function(){
-        this.unreg();
+            
+            me.errorEl.dom.innerHTML = activeError;
+        }
     },
 
     
-    isLocked: function() {
-        return (this.DDM.isLocked() || this.locked);
+    setFieldDefaults: function(defaults) {
+        var me = this;
+        Ext.iterate(defaults, function(key, val) {
+            if (!me.hasOwnProperty(key)) {
+                me[key] = val;
+            }
+        });
     },
 
     
-    handleMouseDown: function(e, oDD){
-        if (this.primaryButtonOnly && e.button != 0) {
-            return;
-        }
+    getBodyNaturalWidth: function() {
+        return this.bodyEl.getWidth();
+    }
 
-        if (this.isLocked()) {
-            return;
-        }
+});
 
-        this.DDM.refreshCache(this.groups);
 
-        var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e));
-        if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) )  {
-        } else {
-            if (this.clickValidator(e)) {
+Ext.define('Ext.form.field.Field', {
+    
+    isFormField : true,
 
-                
-                this.setStartPosition();
+    
 
-                this.b4MouseDown(e);
-                this.onMouseDown(e);
+    
 
-                this.DDM.handleMouseDown(e, this);
+    
+    disabled : false,
 
-                this.DDM.stopEvent(e);
-            } else {
+    
+    submitValue: true,
 
+    
+    validateOnChange: true,
 
-            }
-        }
+    
+    suspendCheckChange: 0,
+
+    
+    initField: function() {
+        this.addEvents(
+            
+            'change',
+            
+            'validitychange',
+            
+            'dirtychange'
+        );
+
+        this.initValue();
     },
 
-    clickValidator: function(e) {
-        var target = e.getTarget();
-        return ( this.isValidHandleChild(target) &&
-                    (this.id == this.handleElId ||
-                        this.DDM.handleWasClicked(target, this.id)) );
+    
+    initValue: function() {
+        var me = this;
+
+        
+        me.originalValue = me.lastValue = me.value;
+
+        
+        me.suspendCheckChange++;
+        me.setValue(me.value);
+        me.suspendCheckChange--;
     },
 
     
-    addInvalidHandleType: function(tagName) {
-        var type = tagName.toUpperCase();
-        this.invalidHandleTypes[type] = type;
+    getName: function() {
+        return this.name;
     },
 
     
-    addInvalidHandleId: function(id) {
-        if (typeof id !== "string") {
-            id = Ext.id(id);
-        }
-        this.invalidHandleIds[id] = id;
+    getValue: function() {
+        return this.value;
     },
 
     
-    addInvalidHandleClass: function(cssClass) {
-        this.invalidHandleClasses.push(cssClass);
+    setValue: function(value) {
+        var me = this;
+        me.value = value;
+        me.checkChange();
+        return me;
     },
 
     
-    removeInvalidHandleType: function(tagName) {
-        var type = tagName.toUpperCase();
-        
-        delete this.invalidHandleTypes[type];
+    isEqual: function(value1, value2) {
+        return String(value1) === String(value2);
+    },
+    
+    
+    isEqualAsString: function(value1, value2){
+        return String(Ext.value(value1, '')) === String(Ext.value(value2, ''));    
     },
 
     
-    removeInvalidHandleId: function(id) {
-        if (typeof id !== "string") {
-            id = Ext.id(id);
+    getSubmitData: function() {
+        var me = this,
+            data = null;
+        if (!me.disabled && me.submitValue && !me.isFileUpload()) {
+            data = {};
+            data[me.getName()] = '' + me.getValue();
         }
-        delete this.invalidHandleIds[id];
+        return data;
     },
 
     
-    removeInvalidHandleClass: function(cssClass) {
-        for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
-            if (this.invalidHandleClasses[i] == cssClass) {
-                delete this.invalidHandleClasses[i];
-            }
+    getModelData: function() {
+        var me = this,
+            data = null;
+        if (!me.disabled && !me.isFileUpload()) {
+            data = {};
+            data[me.getName()] = me.getValue();
         }
+        return data;
     },
 
     
-    isValidHandleChild: function(node) {
+    reset : function(){
+        var me = this;
 
-        var valid = true;
+        me.setValue(me.originalValue);
+        me.clearInvalid();
         
-        var nodeName;
-        try {
-            nodeName = node.nodeName.toUpperCase();
-        } catch(e) {
-            nodeName = node.nodeName;
-        }
-        valid = valid && !this.invalidHandleTypes[nodeName];
-        valid = valid && !this.invalidHandleIds[node.id];
-
-        for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
-            valid = !Ext.fly(node).hasClass(this.invalidHandleClasses[i]);
-        }
-
-
-        return valid;
-
+        delete me.wasValid;
     },
 
     
-    setXTicks: function(iStartX, iTickSize) {
-        this.xTicks = [];
-        this.xTickSize = iTickSize;
-
-        var tickMap = {};
+    resetOriginalValue: function() {
+        this.originalValue = this.getValue();
+        this.checkDirty();
+    },
 
-        for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
-            if (!tickMap[i]) {
-                this.xTicks[this.xTicks.length] = i;
-                tickMap[i] = true;
+    
+    checkChange: function() {
+        if (!this.suspendCheckChange) {
+            var me = this,
+                newVal = me.getValue(),
+                oldVal = me.lastValue;
+            if (!me.isEqual(newVal, oldVal) && !me.isDestroyed) {
+                me.lastValue = newVal;
+                me.fireEvent('change', me, newVal, oldVal);
+                me.onChange(newVal, oldVal);
             }
         }
+    },
 
-        for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
-            if (!tickMap[i]) {
-                this.xTicks[this.xTicks.length] = i;
-                tickMap[i] = true;
-            }
+    
+    onChange: function(newVal, oldVal) {
+        if (this.validateOnChange) {
+            this.validate();
         }
-
-        this.xTicks.sort(this.DDM.numericSort) ;
+        this.checkDirty();
     },
 
     
-    setYTicks: function(iStartY, iTickSize) {
-        this.yTicks = [];
-        this.yTickSize = iTickSize;
-
-        var tickMap = {};
-
-        for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
-            if (!tickMap[i]) {
-                this.yTicks[this.yTicks.length] = i;
-                tickMap[i] = true;
-            }
-        }
+    isDirty : function() {
+        var me = this;
+        return !me.disabled && !me.isEqual(me.getValue(), me.originalValue);
+    },
 
-        for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
-            if (!tickMap[i]) {
-                this.yTicks[this.yTicks.length] = i;
-                tickMap[i] = true;
-            }
+    
+    checkDirty: function() {
+        var me = this,
+            isDirty = me.isDirty();
+        if (isDirty !== me.wasDirty) {
+            me.fireEvent('dirtychange', me, isDirty);
+            me.onDirtyChange(isDirty);
+            me.wasDirty = isDirty;
         }
-
-        this.yTicks.sort(this.DDM.numericSort) ;
     },
 
     
-    setXConstraint: function(iLeft, iRight, iTickSize) {
-        this.leftConstraint = iLeft;
-        this.rightConstraint = iRight;
-
-        this.minX = this.initPageX - iLeft;
-        this.maxX = this.initPageX + iRight;
-        if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
+    onDirtyChange: Ext.emptyFn,
 
-        this.constrainX = true;
+    
+    getErrors: function(value) {
+        return [];
     },
 
     
-    clearConstraints: function() {
-        this.constrainX = false;
-        this.constrainY = false;
-        this.clearTicks();
+    isValid : function() {
+        var me = this;
+        return me.disabled || Ext.isEmpty(me.getErrors());
     },
 
     
-    clearTicks: function() {
-        this.xTicks = null;
-        this.yTicks = null;
-        this.xTickSize = 0;
-        this.yTickSize = 0;
+    validate : function() {
+        var me = this,
+            isValid = me.isValid();
+        if (isValid !== me.wasValid) {
+            me.wasValid = isValid;
+            me.fireEvent('validitychange', me, isValid);
+        }
+        return isValid;
     },
 
     
-    setYConstraint: function(iUp, iDown, iTickSize) {
-        this.topConstraint = iUp;
-        this.bottomConstraint = iDown;
-
-        this.minY = this.initPageY - iUp;
-        this.maxY = this.initPageY + iDown;
-        if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
-
-        this.constrainY = true;
-
+    batchChanges: function(fn) {
+        try {
+            this.suspendCheckChange++;
+            fn();
+        } catch(e){
+            throw e;
+        } finally {
+            this.suspendCheckChange--;
+        }
+        this.checkChange();
     },
 
     
-    resetConstraints: function() {
-        
-        if (this.initPageX || this.initPageX === 0) {
-            
-            var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
-            var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
+    isFileUpload: function() {
+        return false;
+    },
 
-            this.setInitPosition(dx, dy);
+    
+    extractFileInput: function() {
+        return null;
+    },
 
-        
-        } else {
-            this.setInitPosition();
-        }
+    
+    markInvalid: Ext.emptyFn,
 
-        if (this.constrainX) {
-            this.setXConstraint( this.leftConstraint,
-                                 this.rightConstraint,
-                                 this.xTickSize        );
-        }
+    
+    clearInvalid: Ext.emptyFn
 
-        if (this.constrainY) {
-            this.setYConstraint( this.topConstraint,
-                                 this.bottomConstraint,
-                                 this.yTickSize         );
-        }
-    },
+});
 
-    
-    getTick: function(val, tickArray) {
-        if (!tickArray) {
-            
-            
-            return val;
-        } else if (tickArray[0] >= val) {
-            
-            
-            return tickArray[0];
-        } else {
-            for (var i=0, len=tickArray.length; i<len; ++i) {
-                var next = i + 1;
-                if (tickArray[next] && tickArray[next] >= val) {
-                    var diff1 = val - tickArray[i];
-                    var diff2 = tickArray[next] - val;
-                    return (diff2 > diff1) ? tickArray[i] : tickArray[next];
-                }
-            }
 
-            
-            
-            return tickArray[tickArray.length - 1];
-        }
-    },
+Ext.define('Ext.layout.component.field.Field', {
 
     
-    toString: function() {
-        return ("DragDrop " + this.id);
-    }
 
-};
+    alias: ['layout.field'],
 
-})();
+    extend: 'Ext.layout.component.Component',
 
+    uses: ['Ext.tip.QuickTip', 'Ext.util.TextMetrics'],
 
+    
 
+    type: 'field',
 
-if (!Ext.dd.DragDropMgr) {
+    beforeLayout: function(width, height) {
+        var me = this;
+        return me.callParent(arguments) || (!me.owner.preventMark && me.activeError !== me.owner.getActiveError());
+    },
 
+    onLayout: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            labelStrategy = me.getLabelStrategy(),
+            errorStrategy = me.getErrorStrategy(),
+            isDefined = Ext.isDefined,
+            isNumber = Ext.isNumber,
+            lastSize, autoWidth, autoHeight, info, undef;
 
-Ext.dd.DragDropMgr = function() {
+        lastSize = me.lastComponentSize || {};
+        if (!isDefined(width)) {
+            width = lastSize.width;
+            if (width < 0) { 
+                width = undef;
+            }
+        }
+        if (!isDefined(height)) {
+            height = lastSize.height;
+            if (height < 0) { 
+                height = undef;
+            }
+        }
+        autoWidth = !isNumber(width);
+        autoHeight = !isNumber(height);
 
-    var Event = Ext.EventManager;
+        info = {
+            autoWidth: autoWidth,
+            autoHeight: autoHeight,
+            width: autoWidth ? owner.getBodyNaturalWidth() : width, 
+            height: height,
+            setOuterWidth: false, 
 
-    return {
+            
+            insets: {
+                top: 0,
+                right: 0,
+                bottom: 0,
+                left: 0
+            }
+        };
 
         
-        ids: {},
-
         
-        handleIds: {},
-
         
-        dragCurrent: null,
 
         
-        dragOvers: {},
+        labelStrategy.prepare(owner, info);
+        errorStrategy.prepare(owner, info);
 
         
-        deltaX: 0,
+        labelStrategy.adjustHorizInsets(owner, info);
+        errorStrategy.adjustHorizInsets(owner, info);
 
         
-        deltaY: 0,
+        labelStrategy.layoutHoriz(owner, info);
+        errorStrategy.layoutHoriz(owner, info);
 
         
-        preventDefault: true,
+        labelStrategy.adjustVertInsets(owner, info);
+        errorStrategy.adjustVertInsets(owner, info);
 
         
-        stopPropagation: true,
+        labelStrategy.layoutVert(owner, info);
+        errorStrategy.layoutVert(owner, info);
 
         
-        initialized: false,
+        if (autoWidth && autoHeight) {
+            
+            me.setElementSize(owner.el, (info.setOuterWidth ? info.width : undef), info.height);
+        } else {
+            me.setTargetSize((!autoWidth || info.setOuterWidth ? info.width : undef), info.height);
+        }
+        me.sizeBody(info);
 
-        
-        locked: false,
+        me.activeError = owner.getActiveError();
+    },
+    
+    onFocus: function(){
+        this.getErrorStrategy().onFocus(this.owner);    
+    },
 
-        
-        init: function() {
-            this.initialized = true;
-        },
 
-        
-        POINT: 0,
+    
+    sizeBody: function(info) {
+        var me = this,
+            owner = me.owner,
+            insets = info.insets,
+            totalWidth = info.width,
+            totalHeight = info.height,
+            width = Ext.isNumber(totalWidth) ? totalWidth - insets.left - insets.right : totalWidth,
+            height = Ext.isNumber(totalHeight) ? totalHeight - insets.top - insets.bottom : totalHeight;
 
         
-        INTERSECT: 1,
+        me.setElementSize(owner.bodyEl, width, height);
 
         
-        mode: 0,
+        me.sizeBodyContents(width, height);
+    },
 
-        
-        _execOnAll: function(sMethod, args) {
-            for (var i in this.ids) {
-                for (var j in this.ids[i]) {
-                    var oDD = this.ids[i][j];
-                    if (! this.isTypeOfDD(oDD)) {
-                        continue;
+    
+    sizeBodyContents: Ext.emptyFn,
+
+
+    
+    getLabelStrategy: function() {
+        var me = this,
+            strategies = me.labelStrategies,
+            labelAlign = me.owner.labelAlign;
+        return strategies[labelAlign] || strategies.base;
+    },
+
+    
+    getErrorStrategy: function() {
+        var me = this,
+            owner = me.owner,
+            strategies = me.errorStrategies,
+            msgTarget = owner.msgTarget;
+        return !owner.preventMark && Ext.isString(msgTarget) ?
+                (strategies[msgTarget] || strategies.elementId) :
+                strategies.none;
+    },
+
+
+
+    
+    labelStrategies: (function() {
+        var applyIf = Ext.applyIf,
+            emptyFn = Ext.emptyFn,
+            base = {
+                prepare: function(owner, info) {
+                    var cls = owner.labelCls + '-' + owner.labelAlign,
+                        labelEl = owner.labelEl;
+                    if (labelEl && !labelEl.hasCls(cls)) {
+                        labelEl.addCls(cls);
+                    }
+                },
+                adjustHorizInsets: emptyFn,
+                adjustVertInsets: emptyFn,
+                layoutHoriz: emptyFn,
+                layoutVert: emptyFn
+            },
+            left = applyIf({
+                prepare: function(owner, info) {
+                    base.prepare(owner, info);
+                    
+                    if (info.autoWidth) {
+                        info.width += (!owner.labelEl ? 0 : owner.labelWidth + owner.labelPad);
+                    }
+                    
+                    info.setOuterWidth = true;
+                },
+                adjustHorizInsets: function(owner, info) {
+                    if (owner.labelEl) {
+                        info.insets.left += owner.labelWidth + owner.labelPad;
+                    }
+                },
+                layoutHoriz: function(owner, info) {
+                    
+                    
+                    
+                    
+                    
+                    var labelEl = owner.labelEl;
+                    if (labelEl && !owner.isLabelSized && !Ext.isBorderBox) {
+                        labelEl.setWidth(owner.labelWidth);
+                        owner.isLabelSized = true;
                     }
-                    oDD[sMethod].apply(oDD, args);
                 }
-            }
-        },
+            }, base);
 
-        
-        _onLoad: function() {
 
-            this.init();
+        return {
+            base: base,
 
+            
+            top: applyIf({
+                adjustVertInsets: function(owner, info) {
+                    var labelEl = owner.labelEl;
+                    if (labelEl) {
+                        info.insets.top += Ext.util.TextMetrics.measure(labelEl, owner.fieldLabel, info.width).height +
+                                           labelEl.getFrameWidth('tb') + owner.labelPad;
+                    }
+                }
+            }, base),
 
-            Event.on(document, "mouseup",   this.handleMouseUp, this, true);
-            Event.on(document, "mousemove", this.handleMouseMove, this, true);
-            Event.on(window,   "unload",    this._onUnload, this, true);
-            Event.on(window,   "resize",    this._onResize, this, true);
             
+            left: left,
 
-        },
+            
+            right: left
+        };
+    })(),
 
-        
-        _onResize: function(e) {
-            this._execOnAll("resetConstraints", []);
-        },
 
-        
-        lock: function() { this.locked = true; },
 
-        
-        unlock: function() { this.locked = false; },
+    
+    errorStrategies: (function() {
+        function setDisplayed(el, displayed) {
+            var wasDisplayed = el.getStyle('display') !== 'none';
+            if (displayed !== wasDisplayed) {
+                el.setDisplayed(displayed);
+            }
+        }
 
+        function setStyle(el, name, value) {
+            if (el.getStyle(name) !== value) {
+                el.setStyle(name, value);
+            }
+        }
         
-        isLocked: function() { return this.locked; },
+        function showTip(owner) {
+            var tip = Ext.layout.component.field.Field.tip,
+                target;
+                
+            if (tip && tip.isVisible()) {
+                target = tip.activeTarget;
+                if (target && target.el === owner.getActionEl().dom) {
+                    tip.toFront(true);
+                }
+            }
+        }
 
-        
-        locationCache: {},
+        var applyIf = Ext.applyIf,
+            emptyFn = Ext.emptyFn,
+            base = {
+                prepare: function(owner) {
+                    setDisplayed(owner.errorEl, false);
+                },
+                adjustHorizInsets: emptyFn,
+                adjustVertInsets: emptyFn,
+                layoutHoriz: emptyFn,
+                layoutVert: emptyFn,
+                onFocus: emptyFn
+            };
 
-        
-        useCache: true,
+        return {
+            none: base,
 
-        
-        clickPixelThresh: 3,
+            
+            side: applyIf({
+                prepare: function(owner) {
+                    var errorEl = owner.errorEl;
+                    errorEl.addCls(Ext.baseCSSPrefix + 'form-invalid-icon');
+                    Ext.layout.component.field.Field.initTip();
+                    errorEl.dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
+                    setDisplayed(errorEl, owner.hasActiveError());
+                },
+                adjustHorizInsets: function(owner, info) {
+                    if (owner.autoFitErrors && owner.hasActiveError()) {
+                        info.insets.right += owner.errorEl.getWidth();
+                    }
+                },
+                layoutHoriz: function(owner, info) {
+                    if (owner.hasActiveError()) {
+                        setStyle(owner.errorEl, 'left', info.width - info.insets.right + 'px');
+                    }
+                },
+                layoutVert: function(owner, info) {
+                    if (owner.hasActiveError()) {
+                        setStyle(owner.errorEl, 'top', info.insets.top + 'px');
+                    }
+                },
+                onFocus: showTip
+            }, base),
 
-        
-        clickTimeThresh: 350,
+            
+            under: applyIf({
+                prepare: function(owner) {
+                    var errorEl = owner.errorEl,
+                        cls = Ext.baseCSSPrefix + 'form-invalid-under';
+                    if (!errorEl.hasCls(cls)) {
+                        errorEl.addCls(cls);
+                    }
+                    setDisplayed(errorEl, owner.hasActiveError());
+                },
+                adjustVertInsets: function(owner, info) {
+                    if (owner.autoFitErrors) {
+                        info.insets.bottom += owner.errorEl.getHeight();
+                    }
+                },
+                layoutHoriz: function(owner, info) {
+                    var errorEl = owner.errorEl,
+                        insets = info.insets;
 
-        
-        dragThreshMet: false,
+                    setStyle(errorEl, 'width', info.width - insets.right - insets.left + 'px');
+                    setStyle(errorEl, 'marginLeft', insets.left + 'px');
+                }
+            }, base),
 
-        
-        clickTimeout: null,
+            
+            qtip: applyIf({
+                prepare: function(owner) {
+                    setDisplayed(owner.errorEl, false);
+                    Ext.layout.component.field.Field.initTip();
+                    owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
+                },
+                onFocus: showTip
+            }, base),
 
-        
-        startX: 0,
+            
+            title: applyIf({
+                prepare: function(owner) {
+                    setDisplayed(owner.errorEl, false);
+                    owner.el.dom.title = owner.getActiveError() || '';
+                }
+            }, base),
 
-        
-        startY: 0,
+            
+            elementId: applyIf({
+                prepare: function(owner) {
+                    setDisplayed(owner.errorEl, false);
+                    var targetEl = Ext.fly(owner.msgTarget);
+                    if (targetEl) {
+                        targetEl.dom.innerHTML = owner.getActiveError() || '';
+                        targetEl.setDisplayed(owner.hasActiveError());
+                    }
+                }
+            }, base)
+        };
+    })(),
 
+    statics: {
         
-        regDragDrop: function(oDD, sGroup) {
-            if (!this.initialized) { this.init(); }
-
-            if (!this.ids[sGroup]) {
-                this.ids[sGroup] = {};
+        initTip: function() {
+            var tip = this.tip;
+            if (!tip) {
+                tip = this.tip = Ext.create('Ext.tip.QuickTip', {
+                    baseCls: Ext.baseCSSPrefix + 'form-invalid-tip',
+                    renderTo: Ext.getBody()
+                });
+                tip.tagConfig = Ext.apply({}, {attribute: 'errorqtip'}, tip.tagConfig);
             }
-            this.ids[sGroup][oDD.id] = oDD;
         },
 
         
-        removeDDFromGroup: function(oDD, sGroup) {
-            if (!this.ids[sGroup]) {
-                this.ids[sGroup] = {};
+        destroyTip: function() {
+            var tip = this.tip;
+            if (tip) {
+                tip.destroy();
+                delete this.tip;
             }
+        }
+    }
+
+});
 
-            var obj = this.ids[sGroup];
-            if (obj && obj[oDD.id]) {
-                delete obj[oDD.id];
-            }
-        },
+
+Ext.define('Ext.form.field.VTypes', (function(){
+    
+    var alpha = /^[a-zA-Z_]+$/,
+        alphanum = /^[a-zA-Z0-9_]+$/,
+        email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
+        url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
+
+    
+    return {
+        singleton: true,
+        alternateClassName: 'Ext.form.VTypes',
 
         
-        _remove: function(oDD) {
-            for (var g in oDD.groups) {
-                if (g && this.ids[g] && this.ids[g][oDD.id]) {
-                    delete this.ids[g][oDD.id];
-                }
-            }
-            delete this.handleIds[oDD.id];
+        'email' : function(v){
+            return email.test(v);
         },
+        
+        'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
+        
+        'emailMask' : /[a-z0-9_\.\-@\+]/i,
 
         
-        regHandle: function(sDDId, sHandleId) {
-            if (!this.handleIds[sDDId]) {
-                this.handleIds[sDDId] = {};
-            }
-            this.handleIds[sDDId][sHandleId] = sHandleId;
+        'url' : function(v){
+            return url.test(v);
         },
+        
+        'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
 
         
-        isDragDrop: function(id) {
-            return ( this.getDDById(id) ) ? true : false;
+        'alpha' : function(v){
+            return alpha.test(v);
         },
-
         
-        getRelated: function(p_oDD, bTargetsOnly) {
-            var oDDs = [];
-            for (var i in p_oDD.groups) {
-                for (var j in this.ids[i]) {
-                    var dd = this.ids[i][j];
-                    if (! this.isTypeOfDD(dd)) {
-                        continue;
-                    }
-                    if (!bTargetsOnly || dd.isTarget) {
-                        oDDs[oDDs.length] = dd;
-                    }
-                }
-            }
+        'alphaText' : 'This field should only contain letters and _',
+        
+        'alphaMask' : /[a-z_]/i,
 
-            return oDDs;
+        
+        'alphanum' : function(v){
+            return alphanum.test(v);
         },
-
         
-        isLegalTarget: function (oDD, oTargetDD) {
-            var targets = this.getRelated(oDD, true);
-            for (var i=0, len=targets.length;i<len;++i) {
-                if (targets[i].id == oTargetDD.id) {
-                    return true;
-                }
-            }
+        'alphanumText' : 'This field should only contain letters, numbers and _',
+        
+        'alphanumMask' : /[a-z0-9_]/i
+    };
+})());
 
-            return false;
-        },
 
-        
-        isTypeOfDD: function (oDD) {
-            return (oDD && oDD.__ygDragDrop);
-        },
+Ext.define('Ext.layout.component.field.Text', {
+    extend: 'Ext.layout.component.field.Field',
+    alias: 'layout.textfield',
+    requires: ['Ext.util.TextMetrics'],
+
+    type: 'textfield',
+
+
+    
+    beforeLayout: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            lastValue = this.lastValue,
+            value = owner.getRawValue();
+        this.lastValue = value;
+        return me.callParent(arguments) || (owner.grow && value !== lastValue);
+    },
+
+
+    
+    sizeBodyContents: function(width, height) {
+        var size = this.adjustForGrow(width, height);
+        this.setElementSize(this.owner.inputEl, size[0], size[1]);
+    },
+
+
+    
+    adjustForGrow: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            inputEl, value, calcWidth,
+            result = [width, height];
+
+        if (owner.grow) {
+            inputEl = owner.inputEl;
+
+            
+            value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend;
+            calcWidth = inputEl.getTextWidth(value) + inputEl.getBorderWidth("lr") + inputEl.getPadding("lr");
+
+            
+            result[0] = Ext.Number.constrain(calcWidth, owner.growMin,
+                    Math.max(owner.growMin, Math.min(owner.growMax, Ext.isNumber(width) ? width : Infinity)));
+        }
+
+        return result;
+    }
+
+});
+
+
+Ext.define('Ext.layout.component.field.TextArea', {
+    extend: 'Ext.layout.component.field.Text',
+    alias: 'layout.textareafield',
+
+    type: 'textareafield',
+
+
+    
+    adjustForGrow: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            inputEl, value, max,
+            curWidth, curHeight, calcHeight,
+            result = [width, height];
 
-        
-        isHandle: function(sDDId, sHandleId) {
-            return ( this.handleIds[sDDId] &&
-                            this.handleIds[sDDId][sHandleId] );
-        },
+        if (owner.grow) {
+            inputEl = owner.inputEl;
+            curWidth = inputEl.getWidth(true); 
+            curHeight = inputEl.getHeight();
 
-        
-        getDDById: function(id) {
-            for (var i in this.ids) {
-                if (this.ids[i][id]) {
-                    return this.ids[i][id];
-                }
-            }
-            return null;
-        },
+            
+            value = inputEl.dom.value || '&#160;';
+            value += owner.growAppend;
 
-        
-        handleMouseDown: function(e, oDD) {
-            if(Ext.QuickTips){
-                Ext.QuickTips.disable();
-            }
-            if(this.dragCurrent){
-                
-                
-                this.handleMouseUp(e);
-            }
             
-            this.currentTarget = e.getTarget();
-            this.dragCurrent = oDD;
+            value = value.replace(/\n/g, '<br>');
 
-            var el = oDD.getEl();
+            
+            calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height +
+                         inputEl.getBorderWidth("tb") + inputEl.getPadding("tb");
 
             
-            this.startX = e.getPageX();
-            this.startY = e.getPageY();
+            max = owner.growMax;
+            if (Ext.isNumber(height)) {
+                max = Math.min(max, height);
+            }
+            result[1] = Ext.Number.constrain(calcHeight, owner.growMin, max);
+        }
 
-            this.deltaX = this.startX - el.offsetLeft;
-            this.deltaY = this.startY - el.offsetTop;
+        return result;
+    }
 
-            this.dragThreshMet = false;
+});
 
-            this.clickTimeout = setTimeout(
-                    function() {
-                        var DDM = Ext.dd.DDM;
-                        DDM.startDrag(DDM.startX, DDM.startY);
-                    },
-                    this.clickTimeThresh );
-        },
+Ext.define('Ext.layout.container.Anchor', {
 
-        
-        startDrag: function(x, y) {
-            clearTimeout(this.clickTimeout);
-            if (this.dragCurrent) {
-                this.dragCurrent.b4StartDrag(x, y);
-                this.dragCurrent.startDrag(x, y);
-            }
-            this.dragThreshMet = true;
-        },
+    
 
-        
-        handleMouseUp: function(e) {
+    alias: 'layout.anchor',
+    extend: 'Ext.layout.container.Container',
+    alternateClassName: 'Ext.layout.AnchorLayout',
 
-            if(Ext.QuickTips){
-                Ext.QuickTips.enable();
-            }
-            if (! this.dragCurrent) {
-                return;
-            }
+    
 
-            clearTimeout(this.clickTimeout);
+    
+    type: 'anchor',
 
-            if (this.dragThreshMet) {
-                this.fireEvents(e, true);
-            } else {
-            }
+    
+    defaultAnchor: '100%',
 
-            this.stopDrag(e);
+    parseAnchorRE: /^(r|right|b|bottom)$/i,
 
-            this.stopEvent(e);
-        },
+    
+    onLayout: function() {
+        this.callParent(arguments);
 
-        
-        stopEvent: function(e){
-            if(this.stopPropagation) {
-                e.stopPropagation();
-            }
+        var me = this,
+            size = me.getLayoutTargetSize(),
+            owner = me.owner,
+            target = me.getTarget(),
+            ownerWidth = size.width,
+            ownerHeight = size.height,
+            overflow = target.getStyle('overflow'),
+            components = me.getVisibleItems(owner),
+            len = components.length,
+            boxes = [],
+            box, newTargetSize, component, anchorSpec, calcWidth, calcHeight,
+            i, el, cleaner;
+
+        if (ownerWidth < 20 && ownerHeight < 20) {
+            return;
+        }
 
-            if (this.preventDefault) {
-                e.preventDefault();
-            }
-        },
+        
+        
+        
+        if (!me.clearEl) {
+            me.clearEl = target.createChild({
+                cls: Ext.baseCSSPrefix + 'clear',
+                role: 'presentation'
+            });
+        }
 
         
-        stopDrag: function(e) {
-            
-            if (this.dragCurrent) {
-                if (this.dragThreshMet) {
-                    this.dragCurrent.b4EndDrag(e);
-                    this.dragCurrent.endDrag(e);
+        if (!Ext.supports.RightMargin) {
+            cleaner = Ext.Element.getRightMarginFixCleaner(target);
+            target.addCls(Ext.baseCSSPrefix + 'inline-children');
+        }
+
+        for (i = 0; i < len; i++) {
+            component = components[i];
+            el = component.el;
+
+            anchorSpec = component.anchorSpec;
+            if (anchorSpec) {
+                if (anchorSpec.right) {
+                    calcWidth = me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component);
+                } else {
+                    calcWidth = undefined;
+                }
+                if (anchorSpec.bottom) {
+                    calcHeight = me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component);
+                } else {
+                    calcHeight = undefined;
                 }
 
-                this.dragCurrent.onMouseUp(e);
+                boxes.push({
+                    component: component,
+                    anchor: true,
+                    width: calcWidth || undefined,
+                    height: calcHeight || undefined
+                });
+            } else {
+                boxes.push({
+                    component: component,
+                    anchor: false
+                });
             }
-
-            this.dragCurrent = null;
-            this.dragOvers = {};
-        },
+        }
 
         
-        handleMouseMove: function(e) {
-            if (! this.dragCurrent) {
-                return true;
-            }
-            
+        if (!Ext.supports.RightMargin) {
+            target.removeCls(Ext.baseCSSPrefix + 'inline-children');
+            cleaner();
+        }
 
-            
-            if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
-                this.stopEvent(e);
-                return this.handleMouseUp(e);
-            }
+        for (i = 0; i < len; i++) {
+            box = boxes[i];
+            me.setItemSize(box.component, box.width, box.height);
+        }
 
-            if (!this.dragThreshMet) {
-                var diffX = Math.abs(this.startX - e.getPageX());
-                var diffY = Math.abs(this.startY - e.getPageY());
-                if (diffX > this.clickPixelThresh ||
-                            diffY > this.clickPixelThresh) {
-                    this.startDrag(this.startX, this.startY);
-                }
+        if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
+            newTargetSize = me.getLayoutTargetSize();
+            if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
+                me.adjustmentPass = true;
+                me.onLayout();
             }
+        }
 
-            if (this.dragThreshMet) {
-                this.dragCurrent.b4Drag(e);
-                this.dragCurrent.onDrag(e);
-                if(!this.dragCurrent.moveOnly){
-                    this.fireEvents(e, false);
+        delete me.adjustmentPass;
+    },
+
+    
+    parseAnchor: function(a, start, cstart) {
+        if (a && a != 'none') {
+            var ratio;
+            
+            if (this.parseAnchorRE.test(a)) {
+                var diff = cstart - start;
+                return function(v) {
+                    return v - diff;
+                };
+            }    
+            
+            else if (a.indexOf('%') != -1) {
+                ratio = parseFloat(a.replace('%', '')) * 0.01;
+                return function(v) {
+                    return Math.floor(v * ratio);
+                };
+            }    
+            
+            else {
+                a = parseInt(a, 10);
+                if (!isNaN(a)) {
+                    return function(v) {
+                        return v + a;
+                    };
                 }
             }
+        }
+        return null;
+    },
 
-            this.stopEvent(e);
+    
+    adjustWidthAnchor: function(value, comp) {
+        return value;
+    },
 
-            return true;
-        },
+    
+    adjustHeightAnchor: function(value, comp) {
+        return value;
+    },
 
-        
-        fireEvents: function(e, isDrop) {
-            var dc = this.dragCurrent;
+    configureItem: function(item) {
+        var me = this,
+            owner = me.owner,
+            anchor= item.anchor,
+            anchorsArray,
+            anchorSpec,
+            anchorWidth,
+            anchorHeight;
 
-            
-            
-            if (!dc || dc.isLocked()) {
-                return;
-            }
+        if (!item.anchor && item.items && !Ext.isNumber(item.width) && !(Ext.isIE6 && Ext.isStrict)) {
+            item.anchor = anchor = me.defaultAnchor;
+        }
 
-            var pt = e.getPoint();
+        
+        if (owner.anchorSize) {
+            if (typeof owner.anchorSize == 'number') {
+                anchorWidth = owner.anchorSize;
+            }
+            else {
+                anchorWidth = owner.anchorSize.width;
+                anchorHeight = owner.anchorSize.height;
+            }
+        }
+        else {
+            anchorWidth = owner.initialConfig.width;
+            anchorHeight = owner.initialConfig.height;
+        }
 
+        if (anchor) {
             
-            var oldOvers = [];
+            anchorsArray = anchor.split(' ');
+            item.anchorSpec = anchorSpec = {
+                right: me.parseAnchor(anchorsArray[0], item.initialConfig.width, anchorWidth),
+                bottom: me.parseAnchor(anchorsArray[1], item.initialConfig.height, anchorHeight)
+            };
 
-            var outEvts   = [];
-            var overEvts  = [];
-            var dropEvts  = [];
-            var enterEvts = [];
+            if (anchorSpec.right) {
+                item.layoutManagedWidth = 1;
+            } else {
+                item.layoutManagedWidth = 2;
+            }
 
-            
-            
-            for (var i in this.dragOvers) {
+            if (anchorSpec.bottom) {
+                item.layoutManagedHeight = 1;
+            } else {
+                item.layoutManagedHeight = 2;
+            }
+        } else {
+            item.layoutManagedWidth = 2;
+            item.layoutManagedHeight = 2;
+        }
+        this.callParent(arguments);
+    }
 
-                var ddo = this.dragOvers[i];
+});
 
-                if (! this.isTypeOfDD(ddo)) {
-                    continue;
-                }
+Ext.define('Ext.form.action.Load', {
+    extend:'Ext.form.action.Action',
+    requires: ['Ext.data.Connection'],
+    alternateClassName: 'Ext.form.Action.Load',
+    alias: 'formaction.load',
 
-                if (! this.isOverTarget(pt, ddo, this.mode)) {
-                    outEvts.push( ddo );
-                }
+    type: 'load',
 
-                oldOvers[i] = true;
-                delete this.dragOvers[i];
+    
+    run: function() {
+        Ext.Ajax.request(Ext.apply(
+            this.createCallback(),
+            {
+                method: this.getMethod(),
+                url: this.getUrl(),
+                headers: this.headers,
+                params: this.getParams()
             }
+        ));
+    },
 
-            for (var sGroup in dc.groups) {
+    
+    onSuccess: function(response){
+        var result = this.processResponse(response),
+            form = this.form;
+        if (result === true || !result.success || !result.data) {
+            this.failureType = Ext.form.action.Action.LOAD_FAILURE;
+            form.afterAction(this, false);
+            return;
+        }
+        form.clearInvalid();
+        form.setValues(result.data);
+        form.afterAction(this, true);
+    },
 
-                if ("string" != typeof sGroup) {
-                    continue;
-                }
+    
+    handleResponse: function(response) {
+        var reader = this.form.reader,
+            rs, data;
+        if (reader) {
+            rs = reader.read(response);
+            data = rs.records && rs.records[0] ? rs.records[0].data : null;
+            return {
+                success : rs.success,
+                data : data
+            };
+        }
+        return Ext.decode(response.responseText);
+    }
+});
 
-                for (i in this.ids[sGroup]) {
-                    var oDD = this.ids[sGroup][i];
-                    if (! this.isTypeOfDD(oDD)) {
-                        continue;
-                    }
 
-                    if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
-                        if (this.isOverTarget(pt, oDD, this.mode)) {
-                            
-                            if (isDrop) {
-                                dropEvts.push( oDD );
-                            
-                            } else {
 
-                                
-                                if (!oldOvers[oDD.id]) {
-                                    enterEvts.push( oDD );
-                                
-                                } else {
-                                    overEvts.push( oDD );
-                                }
+Ext.define('Ext.window.Window', {
+    extend: 'Ext.panel.Panel',
 
-                                this.dragOvers[oDD.id] = oDD;
-                            }
-                        }
-                    }
-                }
-            }
+    alternateClassName: 'Ext.Window',
 
-            if (this.mode) {
-                if (outEvts.length) {
-                    dc.b4DragOut(e, outEvts);
-                    dc.onDragOut(e, outEvts);
-                }
+    requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
 
-                if (enterEvts.length) {
-                    dc.onDragEnter(e, enterEvts);
-                }
+    alias: 'widget.window',
 
-                if (overEvts.length) {
-                    dc.b4DragOver(e, overEvts);
-                    dc.onDragOver(e, overEvts);
-                }
+    
 
-                if (dropEvts.length) {
-                    dc.b4DragDrop(e, dropEvts);
-                    dc.onDragDrop(e, dropEvts);
-                }
+    
 
-            } else {
-                
-                var len = 0;
-                for (i=0, len=outEvts.length; i<len; ++i) {
-                    dc.b4DragOut(e, outEvts[i].id);
-                    dc.onDragOut(e, outEvts[i].id);
-                }
+    
 
-                
-                for (i=0,len=enterEvts.length; i<len; ++i) {
-                    
-                    dc.onDragEnter(e, enterEvts[i].id);
-                }
+    
 
-                
-                for (i=0,len=overEvts.length; i<len; ++i) {
-                    dc.b4DragOver(e, overEvts[i].id);
-                    dc.onDragOver(e, overEvts[i].id);
-                }
+    
 
-                
-                for (i=0, len=dropEvts.length; i<len; ++i) {
-                    dc.b4DragDrop(e, dropEvts[i].id);
-                    dc.onDragDrop(e, dropEvts[i].id);
-                }
+    
 
-            }
+    
 
-            
-            if (isDrop && !dropEvts.length) {
-                dc.onInvalidDrop(e);
-            }
+    
 
-        },
+    
+    baseCls: Ext.baseCSSPrefix + 'window',
 
-        
-        getBestMatch: function(dds) {
-            var winner = null;
-            
-            
-               
-            
-            
+    
+    resizable: true,
 
-            var len = dds.length;
+    
+    draggable: true,
 
-            if (len == 1) {
-                winner = dds[0];
-            } else {
-                
-                for (var i=0; i<len; ++i) {
-                    var dd = dds[i];
-                    
-                    
-                    
-                    if (dd.cursorIsOver) {
-                        winner = dd;
-                        break;
-                    
-                    } else {
-                        if (!winner ||
-                            winner.overlap.getArea() < dd.overlap.getArea()) {
-                            winner = dd;
-                        }
-                    }
-                }
-            }
+    
+    constrain: false,
 
-            return winner;
-        },
+    
+    constrainHeader: false,
 
-        
-        refreshCache: function(groups) {
-            for (var sGroup in groups) {
-                if ("string" != typeof sGroup) {
-                    continue;
-                }
-                for (var i in this.ids[sGroup]) {
-                    var oDD = this.ids[sGroup][i];
+    
+    plain: false,
 
-                    if (this.isTypeOfDD(oDD)) {
-                    
-                        var loc = this.getLocation(oDD);
-                        if (loc) {
-                            this.locationCache[oDD.id] = loc;
-                        } else {
-                            delete this.locationCache[oDD.id];
-                            
-                            
-                            
-                        }
-                    }
-                }
-            }
-        },
+    
+    minimizable: false,
 
-        
-        verifyEl: function(el) {
-            if (el) {
-                var parent;
-                if(Ext.isIE){
-                    try{
-                        parent = el.offsetParent;
-                    }catch(e){}
-                }else{
-                    parent = el.offsetParent;
-                }
-                if (parent) {
-                    return true;
-                }
-            }
+    
+    maximizable: false,
 
-            return false;
-        },
+    
+    minHeight: 100,
 
-        
-        getLocation: function(oDD) {
-            if (! this.isTypeOfDD(oDD)) {
-                return null;
-            }
+    
+    minWidth: 200,
+
+    
+    expandOnShow: true,
 
-            var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
+    
+    collapsible: false,
 
-            try {
-                pos= Ext.lib.Dom.getXY(el);
-            } catch (e) { }
+    
+    closable: true,
 
-            if (!pos) {
-                return null;
-            }
+    
+    hidden: true,
 
-            x1 = pos[0];
-            x2 = x1 + el.offsetWidth;
-            y1 = pos[1];
-            y2 = y1 + el.offsetHeight;
+    
+    autoRender: true,
 
-            t = y1 - oDD.padding[0];
-            r = x2 + oDD.padding[1];
-            b = y2 + oDD.padding[2];
-            l = x1 - oDD.padding[3];
+    
+    hideMode: 'visibility',
 
-            return new Ext.lib.Region( t, r, b, l );
-        },
+    
+    floating: true,
 
-        
-        isOverTarget: function(pt, oTarget, intersect) {
-            
-            var loc = this.locationCache[oTarget.id];
-            if (!loc || !this.useCache) {
-                loc = this.getLocation(oTarget);
-                this.locationCache[oTarget.id] = loc;
+    ariaRole: 'alertdialog',
 
-            }
+    itemCls: 'x-window-item',
 
-            if (!loc) {
-                return false;
-            }
+    overlapHeader: true,
 
-            oTarget.cursorIsOver = loc.contains( pt );
+    ignoreHeaderBorderManagement: true,
 
+    
+    initComponent: function() {
+        var me = this;
+        me.callParent();
+        me.addEvents(
             
-            
-            
-            
-            
-            var dc = this.dragCurrent;
-            if (!dc || !dc.getTargetCoord ||
-                    (!intersect && !dc.constrainX && !dc.constrainY)) {
-                return oTarget.cursorIsOver;
-            }
 
-            oTarget.overlap = null;
+            
 
             
+            'resize',
+
             
+            'maximize',
+
             
+            'minimize',
+
             
-            var pos = dc.getTargetCoord(pt.x, pt.y);
+            'restore'
+        );
 
-            var el = dc.getDragEl();
-            var curRegion = new Ext.lib.Region( pos.y,
-                                                   pos.x + el.offsetWidth,
-                                                   pos.y + el.offsetHeight,
-                                                   pos.x );
+        if (me.plain) {
+            me.addClsWithUI('plain');
+        }
 
-            var overlap = curRegion.intersect(loc);
+        if (me.modal) {
+            me.ariaRole = 'dialog';
+        }
+    },
 
-            if (overlap) {
-                oTarget.overlap = overlap;
-                return (intersect) ? true : oTarget.cursorIsOver;
-            } else {
-                return false;
-            }
-        },
+    
+    
 
+    initStateEvents: function(){
+        var events = this.stateEvents;
         
-        _onUnload: function(e, me) {
-            Ext.dd.DragDropMgr.unregAll();
-        },
+        Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
+            if (Ext.Array.indexOf(events, event)) {
+                events.push(event);
+            }
+        });
+        this.callParent();
+    },
 
-        
-        unregAll: function() {
+    getState: function() {
+        var me = this,
+            state = me.callParent() || {},
+            maximized = !!me.maximized;
 
-            if (this.dragCurrent) {
-                this.stopDrag();
-                this.dragCurrent = null;
-            }
+        state.maximized = maximized;
+        Ext.apply(state, {
+            size: maximized ? me.restoreSize : me.getSize(),
+            pos: maximized ? me.restorePos : me.getPosition()
+        });
+        return state;
+    },
 
-            this._execOnAll("unreg", []);
+    applyState: function(state){
+        var me = this;
 
-            for (var i in this.elementCache) {
-                delete this.elementCache[i];
+        if (state) {
+            me.maximized = state.maximized;
+            if (me.maximized) {
+                me.hasSavedRestore = true;
+                me.restoreSize = state.size;
+                me.restorePos = state.pos;
+            } else {
+                Ext.apply(me, {
+                    width: state.size.width,
+                    height: state.size.height,
+                    x: state.pos[0],
+                    y: state.pos[1]
+                });
             }
+        }
+    },
 
-            this.elementCache = {};
-            this.ids = {};
-        },
+    
+    onMouseDown: function (e) {
+        var preventFocus;
+            
+        if (this.floating) {
+            if (Ext.fly(e.getTarget()).focusable()) {
+                preventFocus = true;
+            }
+            this.toFront(preventFocus);
+        }
+    },
 
-        
-        elementCache: {},
+    
+    onRender: function(ct, position) {
+        var me = this;
+        me.callParent(arguments);
+        me.focusEl = me.el;
 
         
-        getElWrapper: function(id) {
-            var oWrapper = this.elementCache[id];
-            if (!oWrapper || !oWrapper.el) {
-                oWrapper = this.elementCache[id] =
-                    new this.ElementWrapper(Ext.getDom(id));
-            }
-            return oWrapper;
-        },
+        if (me.maximizable) {
+            me.header.on({
+                dblclick: {
+                    fn: me.toggleMaximize,
+                    element: 'el',
+                    scope: me
+                }
+            });
+        }
+    },
 
-        
-        getElement: function(id) {
-            return Ext.getDom(id);
-        },
+    
+    afterRender: function() {
+        var me = this,
+            hidden = me.hidden,
+            keyMap;
 
+        me.hidden = false;
         
-        getCss: function(id) {
-            var el = Ext.getDom(id);
-            return (el) ? el.style : null;
-        },
+        me.callParent();
+        me.hidden = hidden;
 
         
-        ElementWrapper: function(el) {
-                
-                this.el = el || null;
-                
-                this.id = this.el && el.id;
-                
-                this.css = this.el && el.style;
-            },
+        me.proxy = me.getProxy();
 
         
-        getPosX: function(el) {
-            return Ext.lib.Dom.getX(el);
-        },
-
+        me.mon(me.el, 'mousedown', me.onMouseDown, me);
         
-        getPosY: function(el) {
-            return Ext.lib.Dom.getY(el);
-        },
+        
+        me.el.set({
+            tabIndex: -1
+        });
 
         
-        swapNode: function(n1, n2) {
-            if (n1.swapNode) {
-                n1.swapNode(n2);
-            } else {
-                var p = n2.parentNode;
-                var s = n2.nextSibling;
+        if (me.maximized) {
+            me.maximized = false;
+            me.maximize();
+        }
 
-                if (s == n1) {
-                    p.insertBefore(n1, n2);
-                } else if (n2 == n1.nextSibling) {
-                    p.insertBefore(n2, n1);
-                } else {
-                    n1.parentNode.replaceChild(n2, n1);
-                    p.insertBefore(n1, s);
-                }
-            }
-        },
+        if (me.closable) {
+            keyMap = me.getKeyMap();
+            keyMap.on(27, me.onEsc, me);
+
+            
+                keyMap.disable();
+            
+        }
+
+        if (!hidden) {
+            me.syncMonitorWindowResize();
+            me.doConstrain();
+        }
+    },
+
+    
+    initDraggable: function() {
+        var me = this,
+            ddConfig;
+
+        if (!me.header) {
+            me.updateHeader(true);
+        }
 
         
-        getScroll: function () {
-            var t, l, dde=document.documentElement, db=document.body;
-            if (dde && (dde.scrollTop || dde.scrollLeft)) {
-                t = dde.scrollTop;
-                l = dde.scrollLeft;
-            } else if (db) {
-                t = db.scrollTop;
-                l = db.scrollLeft;
-            } else {
+        if (me.header) {
+            ddConfig = Ext.applyIf({
+                el: me.el,
+                delegate: '#' + me.header.id
+            }, me.draggable);
 
+            
+            if (me.constrain || me.constrainHeader) {
+                ddConfig.constrain = me.constrain;
+                ddConfig.constrainDelegate = me.constrainHeader;
+                ddConfig.constrainTo = me.constrainTo || me.container;
             }
-            return { top: t, left: l };
-        },
 
-        
-        getStyle: function(el, styleProp) {
-            return Ext.fly(el).getStyle(styleProp);
-        },
+            
+            me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
+            me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
+        }
+    },
 
-        
-        getScrollTop: function () {
-            return this.getScroll().top;
-        },
+    
+    onEsc: function(k, e) {
+        e.stopEvent();
+        this[this.closeAction]();
+    },
 
-        
-        getScrollLeft: function () {
-            return this.getScroll().left;
-        },
+    
+    beforeDestroy: function() {
+        var me = this;
+        if (me.rendered) {
+            delete this.animateTarget;
+            me.hide();
+            Ext.destroy(
+                me.keyMap
+            );
+        }
+        me.callParent();
+    },
 
-        
-        moveToEl: function (moveEl, targetEl) {
-            var aCoord = Ext.lib.Dom.getXY(targetEl);
-            Ext.lib.Dom.setXY(moveEl, aCoord);
-        },
+    
+    addTools: function() {
+        var me = this;
 
         
-        numericSort: function(a, b) {
-            return (a - b);
-        },
+        me.callParent();
 
-        
-        _timeoutCount: 0,
+        if (me.minimizable) {
+            me.addTool({
+                type: 'minimize',
+                handler: Ext.Function.bind(me.minimize, me, [])
+            });
+        }
+        if (me.maximizable) {
+            me.addTool({
+                type: 'maximize',
+                handler: Ext.Function.bind(me.maximize, me, [])
+            });
+            me.addTool({
+                type: 'restore',
+                handler: Ext.Function.bind(me.restore, me, []),
+                hidden: true
+            });
+        }
+    },
 
-        
-        _addListeners: function() {
-            var DDM = Ext.dd.DDM;
-            if ( Ext.lib.Event && document ) {
-                DDM._onLoad();
-            } else {
-                if (DDM._timeoutCount > 2000) {
-                } else {
-                    setTimeout(DDM._addListeners, 10);
-                    if (document && document.body) {
-                        DDM._timeoutCount += 1;
-                    }
-                }
-            }
-        },
+    
+    getFocusEl: function() {
+        var me = this,
+            f = me.focusEl,
+            defaultComp = me.defaultButton || me.defaultFocus,
+            t = typeof db,
+            el,
+            ct;
 
-        
-        handleWasClicked: function(node, id) {
-            if (this.isHandle(id, node.id)) {
-                return true;
+        if (Ext.isDefined(defaultComp)) {
+            if (Ext.isNumber(defaultComp)) {
+                f = me.query('button')[defaultComp];
+            } else if (Ext.isString(defaultComp)) {
+                f = me.down('#' + defaultComp);
             } else {
-                
-                var p = node.parentNode;
-
-                while (p) {
-                    if (this.isHandle(id, p.id)) {
-                        return true;
-                    } else {
-                        p = p.parentNode;
-                    }
-                }
+                f = defaultComp;
             }
-
-            return false;
         }
+        return f || me.focusEl;
+    },
 
-    };
-
-}();
+    
+    beforeShow: function() {
+        this.callParent();
 
+        if (this.expandOnShow) {
+            this.expand(false);
+        }
+    },
 
-Ext.dd.DDM = Ext.dd.DragDropMgr;
-Ext.dd.DDM._addListeners();
+    
+    afterShow: function(animateTarget) {
+        var me = this,
+            animating = animateTarget || me.animateTarget;
 
-}
 
+        
+        
 
-Ext.dd.DD = function(id, sGroup, config) {
-    if (id) {
-        this.init(id, sGroup, config);
-    }
-};
+        
+        
+        me.callParent(arguments);
 
-Ext.extend(Ext.dd.DD, Ext.dd.DragDrop, {
+        if (me.maximized) {
+            me.fitContainer();
+        }
 
-    
-    scroll: true,
+        me.syncMonitorWindowResize();
+        if (!animating) {
+            me.doConstrain();
+        }
 
-    
-    autoOffset: function(iPageX, iPageY) {
-        var x = iPageX - this.startPageX;
-        var y = iPageY - this.startPageY;
-        this.setDelta(x, y);
+        if (me.keyMap) {
+            me.keyMap.enable();
+        }
     },
 
     
-    setDelta: function(iDeltaX, iDeltaY) {
-        this.deltaX = iDeltaX;
-        this.deltaY = iDeltaY;
+    doClose: function() {
+        var me = this;
+
+        
+        if (me.hidden) {
+            me.fireEvent('close', me);
+            if (me.closeAction == 'destroy') {
+                this.destroy();
+            }
+        } else {
+            
+            me.hide(me.animateTarget, me.doClose, me);
+        }
     },
 
     
-    setDragElPos: function(iPageX, iPageY) {
+    afterHide: function() {
+        var me = this;
+
         
+        me.syncMonitorWindowResize();
+
         
+        if (me.keyMap) {
+            me.keyMap.disable();
+        }
 
-        var el = this.getDragEl();
-        this.alignElWithMouse(el, iPageX, iPageY);
+        
+        me.callParent(arguments);
     },
 
     
-    alignElWithMouse: function(el, iPageX, iPageY) {
-        var oCoord = this.getTargetCoord(iPageX, iPageY);
-        var fly = el.dom ? el : Ext.fly(el, '_dd');
-        if (!this.deltaSetXY) {
-            var aCoord = [oCoord.x, oCoord.y];
-            fly.setXY(aCoord);
-            var newLeft = fly.getLeft(true);
-            var newTop  = fly.getTop(true);
-            this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
-        } else {
-            fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
+    onWindowResize: function() {
+        if (this.maximized) {
+            this.fitContainer();
         }
-
-        this.cachePosition(oCoord.x, oCoord.y);
-        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
-        return oCoord;
+        this.doConstrain();
     },
 
     
-    cachePosition: function(iPageX, iPageY) {
-        if (iPageX) {
-            this.lastPageX = iPageX;
-            this.lastPageY = iPageY;
-        } else {
-            var aCoord = Ext.lib.Dom.getXY(this.getEl());
-            this.lastPageX = aCoord[0];
-            this.lastPageY = aCoord[1];
-        }
+    minimize: function() {
+        this.fireEvent('minimize', this);
+        return this;
     },
 
-    
-    autoScroll: function(x, y, h, w) {
+    afterCollapse: function() {
+        var me = this;
 
-        if (this.scroll) {
-            
-            var clientH = Ext.lib.Dom.getViewHeight();
+        if (me.maximizable) {
+            me.tools.maximize.hide();
+            me.tools.restore.hide();
+        }
+        if (me.resizer) {
+            me.resizer.disable();
+        }
+        me.callParent(arguments);
+    },
 
-            
-            var clientW = Ext.lib.Dom.getViewWidth();
+    afterExpand: function() {
+        var me = this;
 
-            
-            var st = this.DDM.getScrollTop();
+        if (me.maximized) {
+            me.tools.restore.show();
+        } else if (me.maximizable) {
+            me.tools.maximize.show();
+        }
+        if (me.resizer) {
+            me.resizer.enable();
+        }
+        me.callParent(arguments);
+    },
 
-            
-            var sl = this.DDM.getScrollLeft();
+    
+    maximize: function() {
+        var me = this;
 
-            
-            var bot = h + y;
+        if (!me.maximized) {
+            me.expand(false);
+            if (!me.hasSavedRestore) {
+                me.restoreSize = me.getSize();
+                me.restorePos = me.getPosition(true);
+            }
+            if (me.maximizable) {
+                me.tools.maximize.hide();
+                me.tools.restore.show();
+            }
+            me.maximized = true;
+            me.el.disableShadow();
 
-            
-            var right = w + x;
+            if (me.dd) {
+                me.dd.disable();
+            }
+            if (me.collapseTool) {
+                me.collapseTool.hide();
+            }
+            me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
+            me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
 
-            
-            
-            
-            var toBot = (clientH + st - y - this.deltaY);
+            me.syncMonitorWindowResize();
+            me.setPosition(0, 0);
+            me.fitContainer();
+            me.fireEvent('maximize', me);
+        }
+        return me;
+    },
 
-            
-            var toRight = (clientW + sl - x - this.deltaX);
+    
+    restore: function() {
+        var me = this,
+            tools = me.tools;
 
+        if (me.maximized) {
+            delete me.hasSavedRestore;
+            me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
 
             
-            
-            var thresh = 40;
+            if (tools.restore) {
+                tools.restore.hide();
+            }
+            if (tools.maximize) {
+                tools.maximize.show();
+            }
+            if (me.collapseTool) {
+                me.collapseTool.show();
+            }
 
             
-            
-            
-            var scrAmt = (document.all) ? 80 : 30;
+            me.setPosition(me.restorePos);
+            me.setSize(me.restoreSize);
 
             
-            
-            if ( bot > clientH && toBot < thresh ) {
-                window.scrollTo(sl, st + scrAmt);
-            }
+            delete me.restorePos;
+            delete me.restoreSize;
+
+            me.maximized = false;
+
+            me.el.enableShadow(true);
 
             
-            
-            if ( y < st && st > 0 && y - st < thresh ) {
-                window.scrollTo(sl, st - scrAmt);
+            if (me.dd) {
+                me.dd.enable();
             }
 
+            me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
+
+            me.syncMonitorWindowResize();
+            me.doConstrain();
+            me.fireEvent('restore', me);
+        }
+        return me;
+    },
+
+    
+    syncMonitorWindowResize: function () {
+        var me = this,
+            currentlyMonitoring = me._monitoringResize,
             
+            yes = me.monitorResize || me.constrain || me.constrainHeader || me.maximized,
             
-            if ( right > clientW && toRight < thresh ) {
-                window.scrollTo(sl + scrAmt, st);
-            }
+            veto = me.hidden || me.destroying || me.isDestroyed;
 
+        if (yes && !veto) {
             
-            
-            if ( x < sl && sl > 0 && x - sl < thresh ) {
-                window.scrollTo(sl - scrAmt, st);
+            if (!currentlyMonitoring) {
+                
+                Ext.EventManager.onWindowResize(me.onWindowResize, me);
+                me._monitoringResize = true;
             }
+        } else if (currentlyMonitoring) {
+            
+            Ext.EventManager.removeResizeListener(me.onWindowResize, me);
+            me._monitoringResize = false;
         }
     },
 
     
-    getTargetCoord: function(iPageX, iPageY) {
-        var x = iPageX - this.deltaX;
-        var y = iPageY - this.deltaY;
-
-        if (this.constrainX) {
-            if (x < this.minX) { x = this.minX; }
-            if (x > this.maxX) { x = this.maxX; }
-        }
-
-        if (this.constrainY) {
-            if (y < this.minY) { y = this.minY; }
-            if (y > this.maxY) { y = this.maxY; }
-        }
+    toggleMaximize: function() {
+        return this[this.maximized ? 'restore': 'maximize']();
+    }
 
-        x = this.getTick(x, this.xTicks);
-        y = this.getTick(y, this.yTicks);
+    
+});
 
 
-        return {x:x, y:y};
+Ext.define('Ext.form.field.Base', {
+    extend: 'Ext.Component',
+    mixins: {
+        labelable: 'Ext.form.Labelable',
+        field: 'Ext.form.field.Field'
     },
+    alias: 'widget.field',
+    alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'],
+    requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
 
     
-    applyConfig: function() {
-        Ext.dd.DD.superclass.applyConfig.call(this);
-        this.scroll = (this.config.scroll !== false);
-    },
+    fieldSubTpl: [ 
+        '<input id="{id}" type="{type}" ',
+        '<tpl if="name">name="{name}" </tpl>',
+        '<tpl if="size">size="{size}" </tpl>',
+        '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+        'class="{fieldCls} {typeCls}" autocomplete="off" />',
+        {
+            compiled: true,
+            disableFormats: true
+        }
+    ],
 
     
-    b4MouseDown: function(e) {
-        
-        this.autoOffset(e.getPageX(),
-                            e.getPageY());
-    },
 
     
-    b4Drag: function(e) {
-        this.setDragElPos(e.getPageX(),
-                            e.getPageY());
-    },
+    inputType: 'text',
 
-    toString: function() {
-        return ("DD " + this.id);
-    }
+    
+
+    
+    invalidText : 'The value in this field is invalid',
 
     
+    fieldCls : Ext.baseCSSPrefix + 'form-field',
+
     
+
     
+    focusCls : Ext.baseCSSPrefix + 'form-focus',
+
     
+    dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
 
-});
+    
+    checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ?
+                        ['change', 'propertychange'] :
+                        ['change', 'input', 'textInput', 'keyup', 'dragdrop'],
 
-Ext.dd.DDProxy = function(id, sGroup, config) {
-    if (id) {
-        this.init(id, sGroup, config);
-        this.initFrame();
-    }
-};
+    
+    checkChangeBuffer: 50,
 
+    componentLayout: 'field',
 
-Ext.dd.DDProxy.dragElId = "ygddfdiv";
+    
+    readOnly : false,
 
-Ext.extend(Ext.dd.DDProxy, Ext.dd.DD, {
+    
+    readOnlyCls: Ext.baseCSSPrefix + 'form-readonly',
 
     
-    resizeFrame: true,
 
     
-    centerFrame: false,
+    validateOnBlur: true,
 
     
-    createFrame: function() {
-        var self = this;
-        var body = document.body;
+    hasFocus : false,
 
-        if (!body || !body.firstChild) {
-            setTimeout( function() { self.createFrame(); }, 50 );
-            return;
-        }
+    baseCls: Ext.baseCSSPrefix + 'field',
 
-        var div = this.getDragEl();
+    maskOnDisable: false,
 
-        if (!div) {
-            div    = document.createElement("div");
-            div.id = this.dragElId;
-            var s  = div.style;
+    
+    initComponent : function() {
+        var me = this;
 
-            s.position   = "absolute";
-            s.visibility = "hidden";
-            s.cursor     = "move";
-            s.border     = "2px solid #aaa";
-            s.zIndex     = 999;
+        me.callParent();
+
+        me.subTplData = me.subTplData || {};
 
+        me.addEvents(
             
+            'focus',
             
+            'blur',
             
-            body.insertBefore(div, body.firstChild);
+            'specialkey'
+        );
+
+        
+        me.initLabelable();
+        me.initField();
+
+        
+        if (!me.name) {
+            me.name = me.getInputId();
         }
     },
 
     
-    initFrame: function() {
-        this.createFrame();
-    },
-
-    applyConfig: function() {
-        Ext.dd.DDProxy.superclass.applyConfig.call(this);
-
-        this.resizeFrame = (this.config.resizeFrame !== false);
-        this.centerFrame = (this.config.centerFrame);
-        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
+    getInputId: function() {
+        return this.inputId || (this.inputId = Ext.id());
     },
 
     
-    showFrame: function(iPageX, iPageY) {
-        var el = this.getEl();
-        var dragEl = this.getDragEl();
-        var s = dragEl.style;
-
-        this._resizeProxy();
+    getSubTplData: function() {
+        var me = this,
+            type = me.inputType,
+            inputId = me.getInputId();
+
+        return Ext.applyIf(me.subTplData, {
+            id: inputId,
+            cmpId: me.id,
+            name: me.name || inputId,
+            type: type,
+            size: me.size || 20,
+            cls: me.cls,
+            fieldCls: me.fieldCls,
+            tabIdx: me.tabIndex,
+            typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
+        });
+    },
 
-        if (this.centerFrame) {
-            this.setDelta( Math.round(parseInt(s.width,  10)/2),
-                           Math.round(parseInt(s.height, 10)/2) );
+    afterRender: function() {
+        this.callParent();
+        
+        if (this.inputEl) {
+            this.inputEl.selectable();
         }
-
-        this.setDragElPos(iPageX, iPageY);
-
-        Ext.fly(dragEl).show();
     },
 
     
-    _resizeProxy: function() {
-        if (this.resizeFrame) {
-            var el = this.getEl();
-            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
-        }
+    getSubTplMarkup: function() {
+        return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
     },
 
-    
-    b4MouseDown: function(e) {
-        var x = e.getPageX();
-        var y = e.getPageY();
-        this.autoOffset(x, y);
-        this.setDragElPos(x, y);
+    initRenderTpl: function() {
+        var me = this;
+        if (!me.hasOwnProperty('renderTpl')) {
+            me.renderTpl = me.getTpl('labelableRenderTpl');
+        }
+        return me.callParent();
     },
 
-    
-    b4StartDrag: function(x, y) {
-        
-        this.showFrame(x, y);
+    initRenderData: function() {
+        return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
     },
 
     
-    b4EndDrag: function(e) {
-        Ext.fly(this.getDragEl()).hide();
+    setFieldStyle: function(style) {
+        var me = this,
+            inputEl = me.inputEl;
+        if (inputEl) {
+            inputEl.applyStyles(style);
+        }
+        me.fieldStyle = style;
     },
 
     
-    
-    
-    endDrag: function(e) {
+    onRender : function() {
+        var me = this,
+            fieldStyle = me.fieldStyle;
 
-        var lel = this.getEl();
-        var del = this.getDragEl();
+        me.onLabelableRender();
 
         
-        del.style.visibility = "";
+        me.addChildEls({ name: 'inputEl', id: me.getInputId() });
 
-        this.beforeMove();
-        
-        
-        lel.style.visibility = "hidden";
-        Ext.dd.DDM.moveToEl(lel, del);
-        del.style.visibility = "hidden";
-        lel.style.visibility = "";
+        me.callParent(arguments);
 
-        this.afterDrag();
-    },
+        
+        me.setRawValue(me.rawValue);
 
-    beforeMove : function(){
+        if (me.readOnly) {
+            me.setReadOnly(true);
+        }
+        if (me.disabled) {
+            me.disable();
+        }
+        if (fieldStyle) {
+            me.setFieldStyle(fieldStyle);
+        }
 
+        me.renderActiveError();
     },
 
-    afterDrag : function(){
+    initAria: function() {
+        var me = this;
+        me.callParent();
 
+        
+        me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
     },
 
-    toString: function() {
-        return ("DDProxy " + this.id);
-    }
-
-});
+    getFocusEl: function() {
+        return this.inputEl;
+    },
 
-Ext.dd.DDTarget = function(id, sGroup, config) {
-    if (id) {
-        this.initTarget(id, sGroup, config);
-    }
-};
+    isFileUpload: function() {
+        return this.inputType === 'file';
+    },
 
+    extractFileInput: function() {
+        var me = this,
+            fileInput = me.isFileUpload() ? me.inputEl.dom : null,
+            clone;
+        if (fileInput) {
+            clone = fileInput.cloneNode(true);
+            fileInput.parentNode.replaceChild(clone, fileInput);
+            me.inputEl = Ext.get(clone);
+        }
+        return fileInput;
+    },
 
-Ext.extend(Ext.dd.DDTarget, Ext.dd.DragDrop, {
-    
-    getDragEl: Ext.emptyFn,
-    
-    isValidHandleChild: Ext.emptyFn,
-    
-    startDrag: Ext.emptyFn,
-    
-    endDrag: Ext.emptyFn,
-    
-    onDrag: Ext.emptyFn,
-    
-    onDragDrop: Ext.emptyFn,
-    
-    onDragEnter: Ext.emptyFn,
-    
-    onDragOut: Ext.emptyFn,
-    
-    onDragOver: Ext.emptyFn,
-    
-    onInvalidDrop: Ext.emptyFn,
-    
-    onMouseDown: Ext.emptyFn,
-    
-    onMouseUp: Ext.emptyFn,
-    
-    setXConstraint: Ext.emptyFn,
-    
-    setYConstraint: Ext.emptyFn,
-    
-    resetConstraints: Ext.emptyFn,
-    
-    clearConstraints: Ext.emptyFn,
-    
-    clearTicks: Ext.emptyFn,
-    
-    setInitPosition: Ext.emptyFn,
-    
-    setDragElId: Ext.emptyFn,
-    
-    setHandleElId: Ext.emptyFn,
     
-    setOuterHandleElId: Ext.emptyFn,
+    getSubmitData: function() {
+        var me = this,
+            data = null,
+            val;
+        if (!me.disabled && me.submitValue && !me.isFileUpload()) {
+            val = me.getSubmitValue();
+            if (val !== null) {
+                data = {};
+                data[me.getName()] = val;
+            }
+        }
+        return data;
+    },
+
     
-    addInvalidHandleClass: Ext.emptyFn,
+    getSubmitValue: function() {
+        return this.processRawValue(this.getRawValue());
+    },
+
     
-    addInvalidHandleId: Ext.emptyFn,
+    getRawValue: function() {
+        var me = this,
+            v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, ''));
+        me.rawValue = v;
+        return v;
+    },
+
     
-    addInvalidHandleType: Ext.emptyFn,
+    setRawValue: function(value) {
+        var me = this;
+        value = Ext.value(value, '');
+        me.rawValue = value;
+
+        
+        if (me.inputEl) {
+            me.inputEl.dom.value = value;
+        }
+        return value;
+    },
+
     
-    removeInvalidHandleClass: Ext.emptyFn,
+    valueToRaw: function(value) {
+        return '' + Ext.value(value, '');
+    },
+
     
-    removeInvalidHandleId: Ext.emptyFn,
+    rawToValue: function(rawValue) {
+        return rawValue;
+    },
+
     
-    removeInvalidHandleType: Ext.emptyFn,
+    processRawValue: function(value) {
+        return value;
+    },
 
-    toString: function() {
-        return ("DDTarget " + this.id);
-    }
-});
-Ext.dd.DragTracker = Ext.extend(Ext.util.Observable,  {    
-       
-    active: false,
-       
-    tolerance: 5,
-       
-    autoStart: false,
     
-    constructor : function(config){
-        Ext.apply(this, config);
-           this.addEvents(
-               
-               'mousedown',
-               
-               'mouseup',
-               
-               'mousemove',
-               
-               'dragstart',
-               
-               'dragend',
-               
-               'drag'
-           );
-       
-           this.dragRegion = new Ext.lib.Region(0,0,0,0);
-       
-           if(this.el){
-               this.initEl(this.el);
-           }
-        Ext.dd.DragTracker.superclass.constructor.call(this, config);
-    },
-
-    initEl: function(el){
-        this.el = Ext.get(el);
-        el.on('mousedown', this.onMouseDown, this,
-                this.delegate ? {delegate: this.delegate} : undefined);
+    getValue: function() {
+        var me = this,
+            val = me.rawToValue(me.processRawValue(me.getRawValue()));
+        me.value = val;
+        return val;
     },
 
-    destroy : function(){
-        this.el.un('mousedown', this.onMouseDown, this);
-        delete this.el;
+    
+    setValue: function(value) {
+        var me = this;
+        me.setRawValue(me.valueToRaw(value));
+        return me.mixins.field.setValue.call(me, value);
     },
 
-    onMouseDown: function(e, target){
-        if(this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false){
-            this.startXY = this.lastXY = e.getXY();
-            this.dragTarget = this.delegate ? target : this.el.dom;
-            if(this.preventDefault !== false){
-                e.preventDefault();
-            }
-            var doc = Ext.getDoc();
-            doc.on('mouseup', this.onMouseUp, this);
-            doc.on('mousemove', this.onMouseMove, this);
-            doc.on('selectstart', this.stopSelect, this);
-            if(this.autoStart){
-                this.timer = this.triggerStart.defer(this.autoStart === true ? 1000 : this.autoStart, this);
-            }
+
+    
+    onDisable: function() {
+        var me = this,
+            inputEl = me.inputEl;
+        me.callParent();
+        if (inputEl) {
+            inputEl.dom.disabled = true;
         }
     },
 
-    onMouseMove: function(e, target){
-        
-        if(this.active && Ext.isIE && !e.browserEvent.button){
-            e.preventDefault();
-            this.onMouseUp(e);
-            return;
+    
+    onEnable: function() {
+        var me = this,
+            inputEl = me.inputEl;
+        me.callParent();
+        if (inputEl) {
+            inputEl.dom.disabled = false;
         }
+    },
 
-        e.preventDefault();
-        var xy = e.getXY(), s = this.startXY;
-        this.lastXY = xy;
-        if(!this.active){
-            if(Math.abs(s[0]-xy[0]) > this.tolerance || Math.abs(s[1]-xy[1]) > this.tolerance){
-                this.triggerStart();
-            }else{
-                return;
-            }
+    
+    setReadOnly: function(readOnly) {
+        var me = this,
+            inputEl = me.inputEl;
+        if (inputEl) {
+            inputEl.dom.readOnly = readOnly;
+            inputEl.dom.setAttribute('aria-readonly', readOnly);
         }
-        this.fireEvent('mousemove', this, e);
-        this.onDrag(e);
-        this.fireEvent('drag', this, e);
+        me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
+        me.readOnly = readOnly;
     },
 
-    onMouseUp: function(e) {
-        var doc = Ext.getDoc();
-        doc.un('mousemove', this.onMouseMove, this);
-        doc.un('mouseup', this.onMouseUp, this);
-        doc.un('selectstart', this.stopSelect, this);
-        e.preventDefault();
-        this.clearStart();
-        var wasActive = this.active;
-        this.active = false;
-        delete this.elRegion;
-        this.fireEvent('mouseup', this, e);
-        if(wasActive){
-            this.onEnd(e);
-            this.fireEvent('dragend', this, e);
+    
+    fireKey: function(e){
+        if(e.isSpecialKey()){
+            this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
         }
     },
 
-    triggerStart: function(isTimer) {
-        this.clearStart();
-        this.active = true;
-        this.onStart(this.startXY);
-        this.fireEvent('dragstart', this, this.startXY);
+    
+    initEvents : function(){
+        var me = this,
+            inputEl = me.inputEl,
+            onChangeTask,
+            onChangeEvent;
+        if (inputEl) {
+            me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey,  me);
+            me.mon(inputEl, 'focus', me.onFocus, me);
+
+            
+            
+            me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
+
+            
+            onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
+            me.onChangeEvent = onChangeEvent = function() {
+                onChangeTask.delay(me.checkChangeBuffer);
+            };
+            Ext.each(me.checkChangeEvents, function(eventName) {
+                if (eventName === 'propertychange') {
+                    me.usesPropertychange = true;
+                }
+                me.mon(inputEl, eventName, onChangeEvent);
+            }, me);
+        }
+        me.callParent();
     },
 
-    clearStart : function() {
-        if(this.timer){
-            clearTimeout(this.timer);
-            delete this.timer;
+    doComponentLayout: function() {
+        var me = this,
+            inputEl = me.inputEl,
+            usesPropertychange = me.usesPropertychange,
+            ename = 'propertychange',
+            onChangeEvent = me.onChangeEvent;
+
+        
+        
+        
+        if (usesPropertychange) {
+            me.mun(inputEl, ename, onChangeEvent);
+        }
+        me.callParent(arguments);
+        if (usesPropertychange) {
+            me.mon(inputEl, ename, onChangeEvent);
         }
     },
 
-    stopSelect : function(e) {
-        e.stopEvent();
-        return false;
+    
+    preFocus: Ext.emptyFn,
+
+    
+    onFocus: function() {
+        var me = this,
+            focusCls = me.focusCls,
+            inputEl = me.inputEl;
+        me.preFocus();
+        if (focusCls && inputEl) {
+            inputEl.addCls(focusCls);
+        }
+        if (!me.hasFocus) {
+            me.hasFocus = true;
+            me.componentLayout.onFocus();
+            me.fireEvent('focus', me);
+        }
     },
+
     
+    beforeBlur : Ext.emptyFn,
+
     
-    onBeforeStart : function(e) {
+    onBlur : function(){
+        var me = this,
+            focusCls = me.focusCls,
+            inputEl = me.inputEl;
+
+        if (me.destroying) {
+            return;
+        }
 
+        me.beforeBlur();
+        if (focusCls && inputEl) {
+            inputEl.removeCls(focusCls);
+        }
+        if (me.validateOnBlur) {
+            me.validate();
+        }
+        me.hasFocus = false;
+        me.fireEvent('blur', me);
+        me.postBlur();
     },
 
     
-    onStart : function(xy) {
+    postBlur : Ext.emptyFn,
 
-    },
 
     
-    onDrag : function(e) {
+    onDirtyChange: function(isDirty) {
+        this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
+    },
 
+
+    
+    isValid : function() {
+        var me = this;
+        return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
     },
 
+
     
-    onEnd : function(e) {
+    validateValue: function(value) {
+        var me = this,
+            errors = me.getErrors(value),
+            isValid = Ext.isEmpty(errors);
+        if (!me.preventMark) {
+            if (isValid) {
+                me.clearInvalid();
+            } else {
+                me.markInvalid(errors);
+            }
+        }
 
+        return isValid;
     },
 
     
-    getDragTarget : function(){
-        return this.dragTarget;
+    markInvalid : function(errors) {
+        
+        var me = this,
+            oldMsg = me.getActiveError();
+        me.setActiveErrors(Ext.Array.from(errors));
+        if (oldMsg !== me.getActiveError()) {
+            me.doComponentLayout();
+        }
     },
 
-    getDragCt : function(){
-        return this.el;
+    
+    clearInvalid : function() {
+        
+        var me = this,
+            hadError = me.hasActiveError();
+        me.unsetActiveError();
+        if (hadError) {
+            me.doComponentLayout();
+        }
     },
 
-    getXY : function(constrain){
-        return constrain ?
-               this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
+    
+    renderActiveError: function() {
+        var me = this,
+            hasError = me.hasActiveError();
+        if (me.inputEl) {
+            
+            me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field');
+        }
+        me.mixins.labelable.renderActiveError.call(me);
     },
 
-    getOffset : function(constrain){
-        var xy = this.getXY(constrain);
-        var s = this.startXY;
-        return [s[0]-xy[0], s[1]-xy[1]];
-    },
 
-    constrainModes: {
-        'point' : function(xy){
+    getActionEl: function() {
+        return this.inputEl || this.el;
+    }
 
-            if(!this.elRegion){
-                this.elRegion = this.getDragCt().getRegion();
-            }
+});
 
-            var dr = this.dragRegion;
 
-            dr.left = xy[0];
-            dr.top = xy[1];
-            dr.right = xy[0];
-            dr.bottom = xy[1];
+Ext.define('Ext.form.field.Text', {
+    extend:'Ext.form.field.Base',
+    alias: 'widget.textfield',
+    requires: ['Ext.form.field.VTypes', 'Ext.layout.component.field.Text'],
+    alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'],
 
-            dr.constrainTo(this.elRegion);
+    
 
-            return [dr.left, dr.top];
-        }
-    }
-});
-Ext.dd.ScrollManager = function(){
-    var ddm = Ext.dd.DragDropMgr;
-    var els = {};
-    var dragEl = null;
-    var proc = {};
     
-    var onStop = function(e){
-        dragEl = null;
-        clearProc();
-    };
+
     
-    var triggerRefresh = function(){
-        if(ddm.dragCurrent){
-             ddm.refreshCache(ddm.dragCurrent.groups);
-        }
-    };
+    size: 20,
+
     
-    var doScroll = function(){
-        if(ddm.dragCurrent){
-            var dds = Ext.dd.ScrollManager;
-            var inc = proc.el.ddScrollConfig ?
-                      proc.el.ddScrollConfig.increment : dds.increment;
-            if(!dds.animate){
-                if(proc.el.scroll(proc.dir, inc)){
-                    triggerRefresh();
-                }
-            }else{
-                proc.el.scroll(proc.dir, inc, true, dds.animDuration, triggerRefresh);
-            }
-        }
-    };
+
     
-    var clearProc = function(){
-        if(proc.id){
-            clearInterval(proc.id);
-        }
-        proc.id = 0;
-        proc.el = null;
-        proc.dir = "";
-    };
+    growMin : 30,
+
     
-    var startProc = function(el, dir){
-        clearProc();
-        proc.el = el;
-        proc.dir = dir;
-        var freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? 
-                el.ddScrollConfig.frequency : Ext.dd.ScrollManager.frequency;
-        proc.id = setInterval(doScroll, freq);
-    };
+    growMax : 800,
+
     
-    var onFire = function(e, isDrop){
-        if(isDrop || !ddm.dragCurrent){ return; }
-        var dds = Ext.dd.ScrollManager;
-        if(!dragEl || dragEl != ddm.dragCurrent){
-            dragEl = ddm.dragCurrent;
-            
-            dds.refreshCache();
-        }
-        
-        var xy = Ext.lib.Event.getXY(e);
-        var pt = new Ext.lib.Point(xy[0], xy[1]);
-        for(var id in els){
-            var el = els[id], r = el._region;
-            var c = el.ddScrollConfig ? el.ddScrollConfig : dds;
-            if(r && r.contains(pt) && el.isScrollable()){
-                if(r.bottom - pt.y <= c.vthresh){
-                    if(proc.el != el){
-                        startProc(el, "down");
-                    }
-                    return;
-                }else if(r.right - pt.x <= c.hthresh){
-                    if(proc.el != el){
-                        startProc(el, "left");
-                    }
-                    return;
-                }else if(pt.y - r.top <= c.vthresh){
-                    if(proc.el != el){
-                        startProc(el, "up");
-                    }
-                    return;
-                }else if(pt.x - r.left <= c.hthresh){
-                    if(proc.el != el){
-                        startProc(el, "right");
-                    }
-                    return;
-                }
-            }
-        }
-        clearProc();
-    };
+    growAppend: 'W',
+
     
-    ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
-    ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
+
     
-    return {
-        
-        register : function(el){
-            if(Ext.isArray(el)){
-                for(var i = 0, len = el.length; i < len; i++) {
-                       this.register(el[i]);
-                }
-            }else{
-                el = Ext.get(el);
-                els[el.id] = el;
-            }
-        },
-        
-        
-        unregister : function(el){
-            if(Ext.isArray(el)){
-                for(var i = 0, len = el.length; i < len; i++) {
-                       this.unregister(el[i]);
-                }
-            }else{
-                el = Ext.get(el);
-                delete els[el.id];
-            }
-        },
-        
-        
-        vthresh : 25,
-        
-        hthresh : 25,
 
-        
-        increment : 100,
-        
-        
-        frequency : 500,
-        
-        
-        animate: true,
-        
-        
-        animDuration: .4,
-        
-        
-        refreshCache : function(){
-            for(var id in els){
-                if(typeof els[id] == 'object'){ 
-                    els[id]._region = els[id].getRegion();
-                }
-            }
-        }
-    };
-}();
-Ext.dd.Registry = function(){
-    var elements = {}; 
-    var handles = {}; 
-    var autoIdSeed = 0;
+    
 
-    var getId = function(el, autogen){
-        if(typeof el == "string"){
-            return el;
-        }
-        var id = el.id;
-        if(!id && autogen !== false){
-            id = "extdd-" + (++autoIdSeed);
-            el.id = id;
-        }
-        return id;
-    };
     
-    return {
+    allowBlank : true,
+
     
-        register : function(el, data){
-            data = data || {};
-            if(typeof el == "string"){
-                el = document.getElementById(el);
-            }
-            data.ddel = el;
-            elements[getId(el)] = data;
-            if(data.isHandle !== false){
-                handles[data.ddel.id] = data;
-            }
-            if(data.handles){
-                var hs = data.handles;
-                for(var i = 0, len = hs.length; i < len; i++){
-                       handles[getId(hs[i])] = data;
-                }
-            }
-        },
+    minLength : 0,
 
     
-        unregister : function(el){
-            var id = getId(el, false);
-            var data = elements[id];
-            if(data){
-                delete elements[id];
-                if(data.handles){
-                    var hs = data.handles;
-                    for(var i = 0, len = hs.length; i < len; i++){
-                       delete handles[getId(hs[i], false)];
-                    }
-                }
-            }
-        },
+    maxLength : Number.MAX_VALUE,
+
+    
+
+    
+    minLengthText : 'The minimum length for this field is {0}',
+
+    
+    maxLengthText : 'The maximum length for this field is {0}',
 
     
-        getHandle : function(id){
-            if(typeof id != "string"){ 
-                id = id.id;
-            }
-            return handles[id];
-        },
 
     
-        getHandleFromEvent : function(e){
-            var t = Ext.lib.Event.getTarget(e);
-            return t ? handles[t.id] : null;
-        },
+    blankText : 'This field is required',
 
     
-        getTarget : function(id){
-            if(typeof id != "string"){ 
-                id = id.id;
-            }
-            return elements[id];
-        },
 
     
-        getTargetFromEvent : function(e){
-            var t = Ext.lib.Event.getTarget(e);
-            return t ? elements[t.id] || handles[t.id] : null;
-        }
-    };
-}();
-Ext.dd.StatusProxy = function(config){
-    Ext.apply(this, config);
-    this.id = this.id || Ext.id();
-    this.el = new Ext.Layer({
-        dh: {
-            id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
-                {tag: "div", cls: "x-dd-drop-icon"},
-                {tag: "div", cls: "x-dd-drag-ghost"}
-            ]
-        }, 
-        shadow: !config || config.shadow !== false
-    });
-    this.ghost = Ext.get(this.el.dom.childNodes[1]);
-    this.dropStatus = this.dropNotAllowed;
-};
 
-Ext.dd.StatusProxy.prototype = {
     
-    dropAllowed : "x-dd-drop-ok",
+    regexText : '',
+
     
-    dropNotAllowed : "x-dd-drop-nodrop",
 
     
-    setStatus : function(cssClass){
-        cssClass = cssClass || this.dropNotAllowed;
-        if(this.dropStatus != cssClass){
-            this.el.replaceClass(this.dropStatus, cssClass);
-            this.dropStatus = cssClass;
-        }
-    },
+    emptyCls : Ext.baseCSSPrefix + 'form-empty-field',
+
+    ariaRole: 'textbox',
 
     
-    reset : function(clearGhost){
-        this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
-        this.dropStatus = this.dropNotAllowed;
-        if(clearGhost){
-            this.ghost.update("");
-        }
+
+    componentLayout: 'textfield',
+
+    initComponent : function(){
+        this.callParent();
+        this.addEvents(
+            
+            'autosize',
+
+            
+            'keydown',
+            
+            'keyup',
+            
+            'keypress'
+        );
     },
 
     
-    update : function(html){
-        if(typeof html == "string"){
-            this.ghost.update(html);
-        }else{
-            this.ghost.update("");
-            html.style.margin = "0";
-            this.ghost.dom.appendChild(html);
+    initEvents : function(){
+        var me = this,
+            el = me.inputEl;
+
+        me.callParent();
+        if(me.selectOnFocus || me.emptyText){
+            me.mon(el, 'mousedown', me.onMouseDown, me);
         }
-        var el = this.ghost.dom.firstChild; 
-        if(el){
-            Ext.fly(el).setStyle('float', 'none');
+        if(me.maskRe || (me.vtype && me.disableKeyFilter !== true && (me.maskRe = Ext.form.field.VTypes[me.vtype+'Mask']))){
+            me.mon(el, 'keypress', me.filterKeys, me);
+        }
+
+        if (me.enableKeyEvents) {
+            me.mon(el, {
+                scope: me,
+                keyup: me.onKeyUp,
+                keydown: me.onKeyDown,
+                keypress: me.onKeyPress
+            });
         }
     },
 
     
-    getEl : function(){
-        return this.el;
+    isEqual: function(value1, value2) {
+        return this.isEqualAsString(value1, value2);
     },
 
     
-    getGhost : function(){
-        return this.ghost;
+    onChange: function() {
+        this.callParent();
+        this.autoSize();
     },
 
-    
-    hide : function(clear){
-        this.el.hide();
-        if(clear){
-            this.reset(true);
+    afterRender: function(){
+        var me = this;
+        if (me.enforceMaxLength) {
+            me.inputEl.dom.maxLength = me.maxLength;
         }
+        me.applyEmptyText();
+        me.autoSize();
+        me.callParent();
     },
 
-    
-    stop : function(){
-        if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
-            this.anim.stop();
+    onMouseDown: function(e){
+        var me = this;
+        if(!me.hasFocus){
+            me.mon(me.inputEl, 'mouseup', Ext.emptyFn, me, { single: true, preventDefault: true });
         }
     },
 
     
-    show : function(){
-        this.el.show();
-    },
+    processRawValue: function(value) {
+        var me = this,
+            stripRe = me.stripCharsRe,
+            newValue;
 
-    
-    sync : function(){
-        this.el.sync();
+        if (stripRe) {
+            newValue = value.replace(stripRe, '');
+            if (newValue !== value) {
+                me.setRawValue(newValue);
+                value = newValue;
+            }
+        }
+        return value;
     },
 
     
-    repair : function(xy, callback, scope){
-        this.callback = callback;
-        this.scope = scope;
-        if(xy && this.animRepair !== false){
-            this.el.addClass("x-dd-drag-repair");
-            this.el.hideUnders(true);
-            this.anim = this.el.shift({
-                duration: this.repairDuration || .5,
-                easing: 'easeOut',
-                xy: xy,
-                stopFx: true,
-                callback: this.afterRepair,
-                scope: this
-            });
-        }else{
-            this.afterRepair();
+    onDisable: function(){
+        this.callParent();
+        if (Ext.isIE) {
+            this.inputEl.dom.unselectable = 'on';
         }
     },
 
     
-    afterRepair : function(){
-        this.hide(true);
-        if(typeof this.callback == "function"){
-            this.callback.call(this.scope || this);
+    onEnable: function(){
+        this.callParent();
+        if (Ext.isIE) {
+            this.inputEl.dom.unselectable = '';
         }
-        this.callback = null;
-        this.scope = null;
     },
-    
-    destroy: function(){
-        Ext.destroy(this.ghost, this.el);    
-    }
-};
-Ext.dd.DragSource = function(el, config){
-    this.el = Ext.get(el);
-    if(!this.dragData){
-        this.dragData = {};
-    }
-    
-    Ext.apply(this, config);
-    
-    if(!this.proxy){
-        this.proxy = new Ext.dd.StatusProxy();
-    }
-    Ext.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
-          {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
-    
-    this.dragging = false;
-};
-
-Ext.extend(Ext.dd.DragSource, Ext.dd.DDProxy, {
-    
-    
-    dropAllowed : "x-dd-drop-ok",
-    
-    dropNotAllowed : "x-dd-drop-nodrop",
 
-    
-    getDragData : function(e){
-        return this.dragData;
+    onKeyDown: function(e) {
+        this.fireEvent('keydown', this, e);
     },
 
-    
-    onDragEnter : function(e, id){
-        var target = Ext.dd.DragDropMgr.getDDById(id);
-        this.cachedTarget = target;
-        if(this.beforeDragEnter(target, e, id) !== false){
-            if(target.isNotifyTarget){
-                var status = target.notifyEnter(this, e, this.dragData);
-                this.proxy.setStatus(status);
-            }else{
-                this.proxy.setStatus(this.dropAllowed);
-            }
-            
-            if(this.afterDragEnter){
-                
-                this.afterDragEnter(target, e, id);
-            }
-        }
+    onKeyUp: function(e) {
+        this.fireEvent('keyup', this, e);
     },
 
-    
-    beforeDragEnter : function(target, e, id){
-        return true;
+    onKeyPress: function(e) {
+        this.fireEvent('keypress', this, e);
     },
 
     
-    alignElWithMouse: function() {
-        Ext.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
-        this.proxy.sync();
+    reset : function(){
+        this.callParent();
+        this.applyEmptyText();
     },
 
-    
-    onDragOver : function(e, id){
-        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
-        if(this.beforeDragOver(target, e, id) !== false){
-            if(target.isNotifyTarget){
-                var status = target.notifyOver(this, e, this.dragData);
-                this.proxy.setStatus(status);
+    applyEmptyText : function(){
+        var me = this,
+            emptyText = me.emptyText,
+            isEmpty;
+
+        if (me.rendered && emptyText) {
+            isEmpty = me.getRawValue().length < 1 && !me.hasFocus;
+
+            if (Ext.supports.Placeholder) {
+                me.inputEl.dom.placeholder = emptyText;
+            } else if (isEmpty) {
+                me.setRawValue(emptyText);
             }
 
-            if(this.afterDragOver){
-                
-                this.afterDragOver(target, e, id);
+            
+            
+            if (isEmpty) {
+                me.inputEl.addCls(me.emptyCls);
             }
+
+            me.autoSize();
         }
     },
 
     
-    beforeDragOver : function(target, e, id){
-        return true;
+    preFocus : function(){
+        var me = this,
+            inputEl = me.inputEl,
+            emptyText = me.emptyText,
+            isEmpty;
+
+        if (emptyText && !Ext.supports.Placeholder && inputEl.dom.value === emptyText) {
+            me.setRawValue('');
+            isEmpty = true;
+            inputEl.removeCls(me.emptyCls);
+        } else if (Ext.supports.Placeholder) {
+            me.inputEl.removeCls(me.emptyCls);
+        }
+        if (me.selectOnFocus || isEmpty) {
+            inputEl.dom.select();
+        }
     },
 
-    
-    onDragOut : function(e, id){
-        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
-        if(this.beforeDragOut(target, e, id) !== false){
-            if(target.isNotifyTarget){
-                target.notifyOut(this, e, this.dragData);
-            }
-            this.proxy.reset();
-            if(this.afterDragOut){
-                
-                this.afterDragOut(target, e, id);
-            }
+    onFocus: function() {
+        var me = this;
+        me.callParent(arguments);
+        if (me.emptyText) {
+            me.autoSize();
         }
-        this.cachedTarget = null;
     },
 
     
-    beforeDragOut : function(target, e, id){
-        return true;
+    postBlur : function(){
+        this.applyEmptyText();
     },
+
     
-    
-    onDragDrop : function(e, id){
-        var target = this.cachedTarget || Ext.dd.DragDropMgr.getDDById(id);
-        if(this.beforeDragDrop(target, e, id) !== false){
-            if(target.isNotifyTarget){
-                if(target.notifyDrop(this, e, this.dragData)){ 
-                    this.onValidDrop(target, e, id);
-                }else{
-                    this.onInvalidDrop(target, e, id);
-                }
-            }else{
-                this.onValidDrop(target, e, id);
-            }
-            
-            if(this.afterDragDrop){
-                
-                this.afterDragDrop(target, e, id);
-            }
+    filterKeys : function(e){
+        
+        if (e.ctrlKey && !e.altKey) {
+            return;
         }
-        delete this.cachedTarget;
-    },
+        var key = e.getKey(),
+            charCode = String.fromCharCode(e.getCharCode());
 
-    
-    beforeDragDrop : function(target, e, id){
-        return true;
+        if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
+            return;
+        }
+
+        if(!Ext.isGecko && e.isSpecialKey() && !charCode){
+            return;
+        }
+        if(!this.maskRe.test(charCode)){
+            e.stopEvent();
+        }
     },
 
     
-    onValidDrop : function(target, e, id){
-        this.hideProxy();
-        if(this.afterValidDrop){
-            
-            this.afterValidDrop(target, e, id);
+    getRawValue: function() {
+        var me = this,
+            v = me.callParent();
+        if (v === me.emptyText) {
+            v = '';
         }
+        return v;
     },
 
     
-    getRepairXY : function(e, data){
-        return this.el.getXY();  
+    setValue: function(value) {
+        var me = this,
+            inputEl = me.inputEl;
+
+        if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
+            inputEl.removeCls(me.emptyCls);
+        }
+
+        me.callParent(arguments);
+
+        me.applyEmptyText();
+        return me;
     },
 
     
-    onInvalidDrop : function(target, e, id){
-        this.beforeInvalidDrop(target, e, id);
-        if(this.cachedTarget){
-            if(this.cachedTarget.isNotifyTarget){
-                this.cachedTarget.notifyOut(this, e, this.dragData);
+    getErrors: function(value) {
+        var me = this,
+            errors = me.callParent(arguments),
+            validator = me.validator,
+            emptyText = me.emptyText,
+            allowBlank = me.allowBlank,
+            vtype = me.vtype,
+            vtypes = Ext.form.field.VTypes,
+            regex = me.regex,
+            format = Ext.String.format,
+            msg;
+
+        value = value || me.processRawValue(me.getRawValue());
+
+        if (Ext.isFunction(validator)) {
+            msg = validator.call(me, value);
+            if (msg !== true) {
+                errors.push(msg);
             }
-            this.cacheTarget = null;
         }
-        this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
 
-        if(this.afterInvalidDrop){
+        if (value.length < 1 || value === emptyText) {
+            if (!allowBlank) {
+                errors.push(me.blankText);
+            }
             
-            this.afterInvalidDrop(e, id);
+            return errors;
         }
-    },
 
-    
-    afterRepair : function(){
-        if(Ext.enableFx){
-            this.el.highlight(this.hlColor || "c3daf9");
+        if (value.length < me.minLength) {
+            errors.push(format(me.minLengthText, me.minLength));
         }
-        this.dragging = false;
+
+        if (value.length > me.maxLength) {
+            errors.push(format(me.maxLengthText, me.maxLength));
+        }
+
+        if (vtype) {
+            if(!vtypes[vtype](value, me)){
+                errors.push(me.vtypeText || vtypes[vtype +'Text']);
+            }
+        }
+
+        if (regex && !regex.test(value)) {
+            errors.push(me.regexText || me.invalidText);
+        }
+
+        return errors;
     },
 
     
-    beforeInvalidDrop : function(target, e, id){
-        return true;
+    selectText : function(start, end){
+        var me = this,
+            v = me.getRawValue(),
+            doFocus = true,
+            el = me.inputEl.dom,
+            undef,
+            range;
+
+        if (v.length > 0) {
+            start = start === undef ? 0 : start;
+            end = end === undef ? v.length : end;
+            if (el.setSelectionRange) {
+                el.setSelectionRange(start, end);
+            }
+            else if(el.createTextRange) {
+                range = el.createTextRange();
+                range.moveStart('character', start);
+                range.moveEnd('character', end - v.length);
+                range.select();
+            }
+            doFocus = Ext.isGecko || Ext.isOpera;
+        }
+        if (doFocus) {
+            me.focus();
+        }
     },
 
     
-    handleMouseDown : function(e){
-        if(this.dragging) {
-            return;
+    autoSize: function() {
+        var me = this,
+            width;
+        if (me.grow && me.rendered) {
+            me.doComponentLayout();
+            width = me.inputEl.getWidth();
+            if (width !== me.lastInputWidth) {
+                me.fireEvent('autosize', width);
+                me.lastInputWidth = width;
+            }
         }
-        var data = this.getDragData(e);
-        if(data && this.onBeforeDrag(data, e) !== false){
-            this.dragData = data;
-            this.proxy.stop();
-            Ext.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
-        } 
     },
 
-    
-    onBeforeDrag : function(data, e){
-        return true;
+    initAria: function() {
+        this.callParent();
+        this.getActionEl().dom.setAttribute('aria-required', this.allowBlank === false);
     },
 
     
-    onStartDrag : Ext.emptyFn,
+    getBodyNaturalWidth: function() {
+        return Math.round(this.size * 6.5) + 20;
+    }
 
-    
-    startDrag : function(x, y){
-        this.proxy.reset();
-        this.dragging = true;
-        this.proxy.update("");
-        this.onInitDrag(x, y);
-        this.proxy.show();
-    },
+});
 
-    
-    onInitDrag : function(x, y){
-        var clone = this.el.dom.cloneNode(true);
-        clone.id = Ext.id(); 
-        this.proxy.update(clone);
-        this.onStartDrag(x, y);
-        return true;
-    },
 
-    
-    getProxy : function(){
-        return this.proxy;  
-    },
+Ext.define('Ext.form.field.TextArea', {
+    extend:'Ext.form.field.Text',
+    alias: ['widget.textareafield', 'widget.textarea'],
+    alternateClassName: 'Ext.form.TextArea',
+    requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
+
+    fieldSubTpl: [
+        '<textarea id="{id}" ',
+            '<tpl if="name">name="{name}" </tpl>',
+            '<tpl if="rows">rows="{rows}" </tpl>',
+            '<tpl if="cols">cols="{cols}" </tpl>',
+            '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+            'class="{fieldCls} {typeCls}" ',
+            'autocomplete="off">',
+        '</textarea>',
+        {
+            compiled: true,
+            disableFormats: true
+        }
+    ],
 
     
-    hideProxy : function(){
-        this.proxy.hide();  
-        this.proxy.reset(true);
-        this.dragging = false;
-    },
+    growMin: 60,
 
     
-    triggerCacheRefresh : function(){
-        Ext.dd.DDM.refreshCache(this.groups);
-    },
+    growMax: 1000,
 
     
-    b4EndDrag: function(e) {
-    },
+    growAppend: '\n-',
 
     
-    endDrag : function(e){
-        this.onEndDrag(this.dragData, e);
-    },
+    cols: 20,
 
     
-    onEndDrag : function(data, e){
-    },
-    
-    
-    autoOffset : function(x, y) {
-        this.setDelta(-12, -20);
-    },
-    
-    destroy: function(){
-        Ext.dd.DragSource.superclass.destroy.call(this);
-        Ext.destroy(this.proxy);
-    }
-});
-Ext.dd.DropTarget = Ext.extend(Ext.dd.DDTarget, {
+    rows: 4,
+
     
-    constructor : function(el, config){
-        this.el = Ext.get(el);
+    enterIsSpecial: false,
+
     
-        Ext.apply(this, config);
+    preventScrollbars: false,
+
     
-        if(this.containerScroll){
-            Ext.dd.ScrollManager.register(this.el);
-        }
+    componentLayout: 'textareafield',
+
     
-        Ext.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group, 
-              {isTarget: true});        
+    onRender: function(ct, position) {
+        var me = this;
+        Ext.applyIf(me.subTplData, {
+            cols: me.cols,
+            rows: me.rows
+        });
+
+        me.callParent(arguments);
     },
-    
-    
-    
-    
-    dropAllowed : "x-dd-drop-ok",
-    
-    dropNotAllowed : "x-dd-drop-nodrop",
 
     
-    isTarget : true,
+    afterRender: function(){
+        var me = this;
 
-    
-    isNotifyTarget : true,
+        me.callParent(arguments);
 
-    
-    notifyEnter : function(dd, e, data){
-        if(this.overClass){
-            this.el.addClass(this.overClass);
+        if (me.grow) {
+            if (me.preventScrollbars) {
+                me.inputEl.setStyle('overflow', 'hidden');
+            }
+            me.inputEl.setHeight(me.growMin);
         }
-        return this.dropAllowed;
     },
 
     
-    notifyOver : function(dd, e, data){
-        return this.dropAllowed;
+    fireKey: function(e) {
+        if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
+            this.fireEvent('specialkey', this, e);
+        }
     },
 
     
-    notifyOut : function(dd, e, data){
-        if(this.overClass){
-            this.el.removeClass(this.overClass);
+    autoSize: function() {
+        var me = this,
+            height;
+
+        if (me.grow && me.rendered) {
+            me.doComponentLayout();
+            height = me.inputEl.getHeight();
+            if (height !== me.lastInputHeight) {
+                me.fireEvent('autosize', height);
+                me.lastInputHeight = height;
+            }
         }
     },
 
     
-    notifyDrop : function(dd, e, data){
-        return false;
+    initAria: function() {
+        this.callParent(arguments);
+        this.getActionEl().dom.setAttribute('aria-multiline', true);
     },
+
     
-    destroy : function(){
-        Ext.dd.DropTarget.superclass.destroy.call(this);
-        if(this.containerScroll){
-            Ext.dd.ScrollManager.unregister(this.el);
-        }
+    getBodyNaturalWidth: function() {
+        return Math.round(this.cols * 6.5) + 20;
     }
+
 });
-Ext.dd.DragZone = Ext.extend(Ext.dd.DragSource, {
+
+
+
+Ext.define('Ext.window.MessageBox', {
+    extend: 'Ext.window.Window',
+
+    requires: [
+        'Ext.toolbar.Toolbar',
+        'Ext.form.field.Text',
+        'Ext.form.field.TextArea',
+        'Ext.button.Button',
+        'Ext.layout.container.Anchor',
+        'Ext.layout.container.HBox',
+        'Ext.ProgressBar'
+    ],
+
+    alias: 'widget.messagebox',
+
     
-    constructor : function(el, config){
-        Ext.dd.DragZone.superclass.constructor.call(this, el, config);
-        if(this.containerScroll){
-            Ext.dd.ScrollManager.register(this.el);
-        }
-    },
+    OK : 1,
     
+    YES : 2,
     
+    NO : 4,
     
+    CANCEL : 8,
     
-
+    OKCANCEL : 9,
     
-    getDragData : function(e){
-        return Ext.dd.Registry.getHandleFromEvent(e);
-    },
+    YESNO : 6,
     
+    YESNOCANCEL : 14,
     
-    onInitDrag : function(x, y){
-        this.proxy.update(this.dragData.ddel.cloneNode(true));
-        this.onStartDrag(x, y);
-        return true;
-    },
+    INFO : 'ext-mb-info',
     
+    WARNING : 'ext-mb-warning',
     
-    afterRepair : function(){
-        if(Ext.enableFx){
-            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
-        }
-        this.dragging = false;
-    },
+    QUESTION : 'ext-mb-question',
+    
+    ERROR : 'ext-mb-error',
 
     
-    getRepairXY : function(e){
-        return Ext.Element.fly(this.dragData.ddel).getXY();  
+    hideMode: 'offsets',
+    closeAction: 'hide',
+    resizable: false,
+    title: '&#160;',
+
+    width: 600,
+    height: 500,
+    minWidth: 250,
+    maxWidth: 600,
+    minHeight: 110,
+    maxHeight: 500,
+    constrain: true,
+
+    cls: Ext.baseCSSPrefix + 'message-box',
+
+    layout: {
+        type: 'anchor'
     },
-    
-    destroy : function(){
-        Ext.dd.DragZone.superclass.destroy.call(this);
-        if(this.containerScroll){
-            Ext.dd.ScrollManager.unregister(this.el);
-        }
-    }
-});
-Ext.dd.DropZone = function(el, config){
-    Ext.dd.DropZone.superclass.constructor.call(this, el, config);
-};
 
-Ext.extend(Ext.dd.DropZone, Ext.dd.DropTarget, {
     
-    getTargetFromEvent : function(e){
-        return Ext.dd.Registry.getTargetFromEvent(e);
+    defaultTextHeight : 75,
+    
+    minProgressWidth : 250,
+    
+    minPromptWidth: 250,
+    
+    buttonText: {
+        ok: 'OK',
+        yes: 'Yes',
+        no: 'No',
+        cancel: 'Cancel'
     },
 
-    
-    onNodeEnter : function(n, dd, e, data){
-        
+    buttonIds: [
+        'ok', 'yes', 'no', 'cancel'
+    ],
+
+    titleText: {
+        confirm: 'Confirm',
+        prompt: 'Prompt',
+        wait: 'Loading...',
+        alert: 'Attention'
     },
 
-    
-    onNodeOver : function(n, dd, e, data){
-        return this.dropAllowed;
+    iconHeight: 35,
+
+    makeButton: function(btnIdx) {
+        var btnId = this.buttonIds[btnIdx];
+        return Ext.create('Ext.button.Button', {
+            handler: this.btnCallback,
+            itemId: btnId,
+            scope: this,
+            text: this.buttonText[btnId],
+            minWidth: 75
+        });
     },
 
-    
-    onNodeOut : function(n, dd, e, data){
+    btnCallback: function(btn) {
+        var me = this,
+            value,
+            field;
+
+        if (me.cfg.prompt || me.cfg.multiline) {
+            if (me.cfg.multiline) {
+                field = me.textArea;
+            } else {
+                field = me.textField;
+            }
+            value = field.getValue();
+            field.reset();
+        }
+
         
+        btn.blur();
+        me.hide();
+        me.userCallback(btn.itemId, value, me.cfg);
     },
 
-    
-    onNodeDrop : function(n, dd, e, data){
-        return false;
+    hide: function() {
+        var me = this;
+        me.dd.endDrag();
+        me.progressBar.reset();
+        me.removeCls(me.cfg.cls);
+        me.callParent();
     },
 
-    
-    onContainerOver : function(dd, e, data){
-        return this.dropNotAllowed;
-    },
+    initComponent: function() {
+        var me = this,
+            i, button;
 
-    
-    onContainerDrop : function(dd, e, data){
-        return false;
-    },
+        me.title = '&#160;';
 
-    
-    notifyEnter : function(dd, e, data){
-        return this.dropNotAllowed;
+        me.topContainer = Ext.create('Ext.container.Container', {
+            anchor: '100%',
+            style: {
+                padding: '10px',
+                overflow: 'hidden'
+            },
+            items: [
+                me.iconComponent = Ext.create('Ext.Component', {
+                    cls: 'ext-mb-icon',
+                    width: 50,
+                    height: me.iconHeight,
+                    style: {
+                        'float': 'left'
+                    }
+                }),
+                me.promptContainer = Ext.create('Ext.container.Container', {
+                    layout: {
+                        type: 'anchor'
+                    },
+                    items: [
+                        me.msg = Ext.create('Ext.Component', {
+                            autoEl: { tag: 'span' },
+                            cls: 'ext-mb-text'
+                        }),
+                        me.textField = Ext.create('Ext.form.field.Text', {
+                            anchor: '100%',
+                            enableKeyEvents: true,
+                            listeners: {
+                                keydown: me.onPromptKey,
+                                scope: me
+                            }
+                        }),
+                        me.textArea = Ext.create('Ext.form.field.TextArea', {
+                            anchor: '100%',
+                            height: 75
+                        })
+                    ]
+                })
+            ]
+        });
+        me.progressBar = Ext.create('Ext.ProgressBar', {
+            anchor: '-10',
+            style: 'margin-left:10px'
+        });
+
+        me.items = [me.topContainer, me.progressBar];
+
+        
+        me.msgButtons = [];
+        for (i = 0; i < 4; i++) {
+            button = me.makeButton(i);
+            me.msgButtons[button.itemId] = button;
+            me.msgButtons.push(button);
+        }
+        me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
+            ui: 'footer',
+            dock: 'bottom',
+            layout: {
+                pack: 'center'
+            },
+            items: [
+                me.msgButtons[0],
+                me.msgButtons[1],
+                me.msgButtons[2],
+                me.msgButtons[3]
+            ]
+        });
+        me.dockedItems = [me.bottomTb];
+
+        me.callParent();
     },
 
-    
-    notifyOver : function(dd, e, data){
-        var n = this.getTargetFromEvent(e);
-        if(!n){ 
-            if(this.lastOverNode){
-                this.onNodeOut(this.lastOverNode, dd, e, data);
-                this.lastOverNode = null;
+    onPromptKey: function(textField, e) {
+        var me = this,
+            blur;
+
+        if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
+            if (me.msgButtons.ok.isVisible()) {
+                blur = true;
+                me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
+            } else if (me.msgButtons.yes.isVisible()) {
+                me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
+                blur = true;
             }
-            return this.onContainerOver(dd, e, data);
-        }
-        if(this.lastOverNode != n){
-            if(this.lastOverNode){
-                this.onNodeOut(this.lastOverNode, dd, e, data);
+
+            if (blur) {
+                me.textField.blur();
             }
-            this.onNodeEnter(n, dd, e, data);
-            this.lastOverNode = n;
         }
-        return this.onNodeOver(n, dd, e, data);
     },
 
-    
-    notifyOut : function(dd, e, data){
-        if(this.lastOverNode){
-            this.onNodeOut(this.lastOverNode, dd, e, data);
-            this.lastOverNode = null;
-        }
-    },
+    reconfigure: function(cfg) {
+        var me = this,
+            buttons = cfg.buttons || 0,
+            hideToolbar = true,
+            initialWidth = me.maxWidth,
+            i;
 
-    
-    notifyDrop : function(dd, e, data){
-        if(this.lastOverNode){
-            this.onNodeOut(this.lastOverNode, dd, e, data);
-            this.lastOverNode = null;
+        cfg = cfg || {};
+        me.cfg = cfg;
+        if (cfg.width) {
+            initialWidth = cfg.width;
         }
-        var n = this.getTargetFromEvent(e);
-        return n ?
-            this.onNodeDrop(n, dd, e, data) :
-            this.onContainerDrop(dd, e, data);
-    },
 
-    
-    triggerCacheRefresh : function(){
-        Ext.dd.DDM.refreshCache(this.groups);
-    }  
-});
-Ext.Element.addMethods({
-    
-    initDD : function(group, config, overrides){
-        var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);
-        return Ext.apply(dd, overrides);
-    },
+        
+        delete me.defaultFocus;
 
-    
-    initDDProxy : function(group, config, overrides){
-        var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);
-        return Ext.apply(dd, overrides);
-    },
+        
+        me.animateTarget = cfg.animateTarget || undefined;
 
-    
-    initDDTarget : function(group, config, overrides){
-        var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);
-        return Ext.apply(dd, overrides);
-    }
-});
+        
+        me.modal = cfg.modal !== false;
+
+        
+        if (cfg.title) {
+            me.setTitle(cfg.title||'&#160;');
+        }
 
-Ext.data.Api = (function() {
+        if (!me.rendered) {
+            me.width = initialWidth;
+            me.render(Ext.getBody());
+        } else {
+            me.setSize(initialWidth, me.maxHeight);
+        }
+        me.setPosition(-10000, -10000);
 
-    
-    
-    
-    
-    var validActions = {};
+        
+        me.closable = cfg.closable && !cfg.wait;
+        me.header.child('[type=close]').setVisible(cfg.closable !== false);
 
-    return {
         
-        actions : {
-            create  : 'create',
-            read    : 'read',
-            update  : 'update',
-            destroy : 'destroy'
-        },
+        if (!cfg.title && !me.closable) {
+            me.header.hide();
+        } else {
+            me.header.show();
+        }
 
         
-        restActions : {
-            create  : 'POST',
-            read    : 'GET',
-            update  : 'PUT',
-            destroy : 'DELETE'
-        },
+        me.liveDrag = !cfg.proxyDrag;
 
         
-        isAction : function(action) {
-            return (Ext.data.Api.actions[action]) ? true : false;
-        },
+        me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
+
+        
+        me.setIcon(cfg.icon);
 
         
-        getVerb : function(name) {
-            if (validActions[name]) {
-                return validActions[name];  
-            }
-            for (var verb in this.actions) {
-                if (this.actions[verb] === name) {
-                    validActions[name] = verb;
-                    break;
-                }
-            }
-            return (validActions[name] !== undefined) ? validActions[name] : null;
-        },
+        if (cfg.msg) {
+            me.msg.update(cfg.msg);
+            me.msg.show();
+        } else {
+            me.msg.hide();
+        }
 
         
-        isValid : function(api){
-            var invalid = [];
-            var crud = this.actions; 
-            for (var action in api) {
-                if (!(action in crud)) {
-                    invalid.push(action);
-                }
+        if (cfg.prompt || cfg.multiline) {
+            me.multiline = cfg.multiline;
+            if (cfg.multiline) {
+                me.textArea.setValue(cfg.value);
+                me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
+                me.textArea.show();
+                me.textField.hide();
+                me.defaultFocus = me.textArea;
+            } else {
+                me.textField.setValue(cfg.value);
+                me.textArea.hide();
+                me.textField.show();
+                me.defaultFocus = me.textField;
             }
-            return (!invalid.length) ? true : invalid;
-        },
+        } else {
+            me.textArea.hide();
+            me.textField.hide();
+        }
 
         
-        hasUniqueUrl : function(proxy, verb) {
-            var url = (proxy.api[verb]) ? proxy.api[verb].url : null;
-            var unique = true;
-            for (var action in proxy.api) {
-                if ((unique = (action === verb) ? true : (proxy.api[action].url != url) ? true : false) === false) {
-                    break;
-                }
+        if (cfg.progress || cfg.wait) {
+            me.progressBar.show();
+            me.updateProgress(0, cfg.progressText);
+            if(cfg.wait === true){
+                me.progressBar.wait(cfg.waitConfig);
             }
-            return unique;
-        },
+        } else {
+            me.progressBar.hide();
+        }
 
         
-        prepare : function(proxy) {
-            if (!proxy.api) {
-                proxy.api = {}; 
-            }
-            for (var verb in this.actions) {
-                var action = this.actions[verb];
-                proxy.api[action] = proxy.api[action] || proxy.url || proxy.directFn;
-                if (typeof(proxy.api[action]) == 'string') {
-                    proxy.api[action] = {
-                        url: proxy.api[action],
-                        method: (proxy.restful === true) ? Ext.data.Api.restActions[action] : undefined
-                    };
+        for (i = 0; i < 4; i++) {
+            if (buttons & Math.pow(2, i)) {
+
+                
+                if (!me.defaultFocus) {
+                    me.defaultFocus = me.msgButtons[i];
                 }
+                me.msgButtons[i].show();
+                hideToolbar = false;
+            } else {
+                me.msgButtons[i].hide();
             }
-        },
+        }
 
         
-        restify : function(proxy) {
-            proxy.restful = true;
-            for (var verb in this.restActions) {
-                proxy.api[this.actions[verb]].method ||
-                    (proxy.api[this.actions[verb]].method = this.restActions[verb]);
-            }
-            
-            
-            proxy.onWrite = proxy.onWrite.createInterceptor(function(action, o, response, rs) {
-                var reader = o.reader;
-                var res = new Ext.data.Response({
-                    action: action,
-                    raw: response
-                });
+        if (hideToolbar) {
+            me.bottomTb.hide();
+        } else {
+            me.bottomTb.show();
+        }
+    },
 
-                switch (response.status) {
-                    case 200:   
-                        return true;
-                        break;
-                    case 201:   
-                        if (Ext.isEmpty(res.raw.responseText)) {
-                          res.success = true;
-                        } else {
-                          
-                          return true;
-                        }
-                        break;
-                    case 204:  
-                        res.success = true;
-                        res.data = null;
-                        break;
-                    default:
-                        return true;
-                        break;
-                }
-                if (res.success === true) {
-                    this.fireEvent("write", this, action, res.data, res, rs, o.request.arg);
-                } else {
-                    this.fireEvent('exception', this, 'remote', action, o, res, rs);
-                }
-                o.request.callback.call(o.request.scope, res.data, res, res.success);
+    
+    show: function(cfg) {
+        var me = this;
 
-                return false;   
-            }, proxy);
+        me.reconfigure(cfg);
+        me.addCls(cfg.cls);
+        if (cfg.animateTarget) {
+            me.doAutoSize(true);
+            me.callParent();
+        } else {
+            me.callParent();
+            me.doAutoSize(true);
         }
-    };
-})();
+        return me;
+    },
 
+    afterShow: function(){
+        if (this.animateTarget) {
+            this.center();
+        }
+        this.callParent(arguments);
+    },
 
-Ext.data.Response = function(params, response) {
-    Ext.apply(this, params, {
-        raw: response
-    });
-};
-Ext.data.Response.prototype = {
-    message : null,
-    success : false,
-    status : null,
-    root : null,
-    raw : null,
+    doAutoSize: function(center) {
+        var me = this,
+            icon = me.iconComponent,
+            iconHeight = me.iconHeight;
 
-    getMessage : function() {
-        return this.message;
-    },
-    getSuccess : function() {
-        return this.success;
-    },
-    getStatus : function() {
-        return this.status;
-    },
-    getRoot : function() {
-        return this.root;
-    },
-    getRawResponse : function() {
-        return this.raw;
-    }
-};
+        if (!Ext.isDefined(me.frameWidth)) {
+            me.frameWidth = me.el.getWidth() - me.body.getWidth();
+        }
 
+        
+        icon.setHeight(iconHeight);
 
-Ext.data.Api.Error = Ext.extend(Ext.Error, {
-    constructor : function(message, arg) {
-        this.arg = arg;
-        Ext.Error.call(this, message);
-    },
-    name: 'Ext.data.Api'
-});
-Ext.apply(Ext.data.Api.Error.prototype, {
-    lang: {
-        'action-url-undefined': 'No fallback url defined for this action.  When defining a DataProxy api, please be sure to define an url for each CRUD action in Ext.data.Api.actions or define a default url in addition to your api-configuration.',
-        'invalid': 'received an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions defined in Ext.data.Api.actions',
-        'invalid-url': 'Invalid url.  Please review your proxy configuration.',
-        'execute': 'Attempted to execute an unknown action.  Valid API actions are defined in Ext.data.Api.actions"'
-    }
-});
+        
+        me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
 
+        
+        
+        me.topContainer.doLayout();
+        if (Ext.isIE6 || Ext.isIEQuirks) {
+            
+            
+            
+            me.textField.setCalculatedSize(9);
+            me.textArea.setCalculatedSize(9);
+        }
+        var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25, 
+            height = (me.header.rendered ? me.header.getHeight() : 0) +
+            Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
+            me.progressBar.getHeight() +
+            (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;
 
+        
+        icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
+        me.setSize(width + me.frameWidth, height + me.frameWidth);
+        if (center) {
+            me.center();
+        }
+        return me;
+    },
 
+    updateText: function(text) {
+        this.msg.update(text);
+        return this.doAutoSize(true);
+    },
 
-Ext.data.SortTypes = {
     
-    none : function(s){
-        return s;
+    setIcon : function(icon) {
+        var me = this;
+        me.iconComponent.removeCls(me.iconCls);
+        if (icon) {
+            me.iconComponent.show();
+            me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
+            me.iconComponent.addCls(me.iconCls = icon);
+        } else {
+            me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
+            me.iconComponent.hide();
+        }
+        return me;
     },
+
     
-    
-    stripTagsRE : /<\/?[^>]+>/gi,
-    
-    
-    asText : function(s){
-        return String(s).replace(this.stripTagsRE, "");
+    updateProgress : function(value, progressText, msg){
+        this.progressBar.updateProgress(value, progressText);
+        if (msg){
+            this.updateText(msg);
+        }
+        return this;
     },
-    
-    
-    asUCText : function(s){
-        return String(s).toUpperCase().replace(this.stripTagsRE, "");
+
+    onEsc: function() {
+        if (this.closable !== false) {
+            this.callParent(arguments);
+        }
     },
+
     
-    
-    asUCString : function(s) {
-       return String(s).toUpperCase();
+    confirm: function(cfg, msg, fn, scope) {
+        if (Ext.isString(cfg)) {
+            cfg = {
+                title: cfg,
+                icon: 'ext-mb-question',
+                msg: msg,
+                buttons: this.YESNO,
+                callback: fn,
+                scope: scope
+            };
+        }
+        return this.show(cfg);
     },
+
     
-    
-    asDate : function(s) {
-        if(!s){
-            return 0;
-        }
-        if(Ext.isDate(s)){
-            return s.getTime();
+    prompt : function(cfg, msg, fn, scope, multiline, value){
+        if (Ext.isString(cfg)) {
+            cfg = {
+                prompt: true,
+                title: cfg,
+                minWidth: this.minPromptWidth,
+                msg: msg,
+                buttons: this.OKCANCEL,
+                callback: fn,
+                scope: scope,
+                multiline: multiline,
+                value: value
+            };
         }
-       return Date.parse(String(s));
+        return this.show(cfg);
     },
+
     
-    
-    asFloat : function(s) {
-       var val = parseFloat(String(s).replace(/,/g, ""));
-       return isNaN(val) ? 0 : val;
+    wait : function(cfg, title, config){
+        if (Ext.isString(cfg)) {
+            cfg = {
+                title : title,
+                msg : cfg,
+                closable: false,
+                wait: true,
+                modal: true,
+                minWidth: this.minProgressWidth,
+                waitConfig: config
+            };
+        }
+        return this.show(cfg);
     },
+
     
+    alert: function(cfg, msg, fn, scope) {
+        if (Ext.isString(cfg)) {
+            cfg = {
+                title : cfg,
+                msg : msg,
+                buttons: this.OK,
+                fn: fn,
+                scope : scope,
+                minWidth: this.minWidth
+            };
+        }
+        return this.show(cfg);
+    },
+
     
-    asInt : function(s) {
-        var val = parseInt(String(s).replace(/,/g, ""), 10);
-        return isNaN(val) ? 0 : val;
+    progress : function(cfg, msg, progressText){
+        if (Ext.isString(cfg)) {
+            cfg = {
+                title: cfg,
+                msg: msg,
+                progress: true,
+                progressText: progressText
+            };
+        }
+        return this.show(cfg);
     }
-};
-Ext.data.Record = function(data, id){
+}, function() {
     
-    this.id = (id || id === 0) ? id : Ext.data.Record.id(this);
-    this.data = data || {};
-};
+    Ext.MessageBox = Ext.Msg = new this();
+});
 
+Ext.define('Ext.form.Basic', {
+    extend: 'Ext.util.Observable',
+    alternateClassName: 'Ext.form.BasicForm',
+    requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
+               'Ext.window.MessageBox', 'Ext.data.Errors', 'Ext.util.DelayedTask'],
 
-Ext.data.Record.create = function(o){
-    var f = Ext.extend(Ext.data.Record, {});
-    var p = f.prototype;
-    p.fields = new Ext.util.MixedCollection(false, function(field){
-        return field.name;
-    });
-    for(var i = 0, len = o.length; i < len; i++){
-        p.fields.add(new Ext.data.Field(o[i]));
-    }
-    f.getField = function(name){
-        return p.fields.get(name);
-    };
-    return f;
-};
+    
+    constructor: function(owner, config) {
+        var me = this,
+            onItemAddOrRemove = me.onItemAddOrRemove;
+
+        
+        me.owner = owner;
+
+        
+        me.mon(owner, {
+            add: onItemAddOrRemove,
+            remove: onItemAddOrRemove,
+            scope: me
+        });
 
-Ext.data.Record.PREFIX = 'ext-record';
-Ext.data.Record.AUTO_ID = 1;
-Ext.data.Record.EDIT = 'edit';
-Ext.data.Record.REJECT = 'reject';
-Ext.data.Record.COMMIT = 'commit';
+        Ext.apply(me, config);
 
+        
+        if (Ext.isString(me.paramOrder)) {
+            me.paramOrder = me.paramOrder.split(/[\s,|]/);
+        }
 
+        me.checkValidityTask = Ext.create('Ext.util.DelayedTask', me.checkValidity, me);
 
-Ext.data.Record.id = function(rec) {
-    rec.phantom = true;
-    return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');
-};
+        me.addEvents(
+            
+            'beforeaction',
+            
+            'actionfailed',
+            
+            'actioncomplete',
+            
+            'validitychange',
+            
+            'dirtychange'
+        );
+        me.callParent();
+    },
 
-Ext.data.Record.prototype = {
     
+    initialize: function(){
+        this.initialized = true;
+        this.onValidityChange(!this.hasInvalidField());
+    },
+
     
+
     
+
     
+
     
+
     
-    dirty : false,
-    editing : false,
-    error : null,
+
     
-    modified : null,
+    timeout: 30,
+
     
-    phantom : false,
 
     
-    join : function(store){
-        
-        this.store = store;
+
+    
+    paramsAsHash: false,
+
+    
+    waitTitle: 'Please Wait...',
+
+    
+    trackResetOnLoad: false,
+
+    
+
+    
+
+
+    
+    wasDirty: false,
+
+
+    
+    destroy: function() {
+        this.clearListeners();
+        this.checkValidityTask.cancel();
     },
 
     
-    set : function(name, value){
-        var encode = Ext.isPrimitive(value) ? String : Ext.encode;
-        if(encode(this.data[name]) == encode(value)) {
-            return;
-        }        
-        this.dirty = true;
-        if(!this.modified){
-            this.modified = {};
+    onItemAddOrRemove: function(parent, child) {
+        var me = this,
+            isAdding = !!child.ownerCt,
+            isContainer = child.isContainer;
+
+        function handleField(field) {
+            
+            me[isAdding ? 'mon' : 'mun'](field, {
+                validitychange: me.checkValidity,
+                dirtychange: me.checkDirty,
+                scope: me,
+                buffer: 100 
+            });
+            
+            delete me._fields;
         }
-        if(this.modified[name] === undefined){
-            this.modified[name] = this.data[name];
+
+        if (child.isFormField) {
+            handleField(child);
+        } else if (isContainer) {
+            
+            if (child.isDestroyed) {
+                
+                
+                delete me._fields;
+            } else {
+                Ext.Array.forEach(child.query('[isFormField]'), handleField);
+            }
         }
-        this.data[name] = value;
-        if(!this.editing){
-            this.afterEdit();
+
+        
+        delete this._boundItems;
+
+        
+        
+        if (me.initialized) {
+            me.checkValidityTask.delay(10);
         }
     },
 
     
-    afterEdit : function(){
-        if (this.store != undefined && typeof this.store.afterEdit == "function") {
-            this.store.afterEdit(this);
+    getFields: function() {
+        var fields = this._fields;
+        if (!fields) {
+            fields = this._fields = Ext.create('Ext.util.MixedCollection');
+            fields.addAll(this.owner.query('[isFormField]'));
         }
+        return fields;
     },
 
     
-    afterReject : function(){
-        if(this.store){
-            this.store.afterReject(this);
+    getBoundItems: function() {
+        var boundItems = this._boundItems;
+        
+        if (!boundItems || boundItems.getCount() === 0) {
+            boundItems = this._boundItems = Ext.create('Ext.util.MixedCollection');
+            boundItems.addAll(this.owner.query('[formBind]'));
         }
+        
+        return boundItems;
     },
 
     
-    afterCommit : function(){
-        if(this.store){
-            this.store.afterCommit(this);
-        }
+    hasInvalidField: function() {
+        return !!this.getFields().findBy(function(field) {
+            var preventMark = field.preventMark,
+                isValid;
+            field.preventMark = true;
+            isValid = field.isValid();
+            field.preventMark = preventMark;
+            return !isValid;
+        });
     },
 
     
-    get : function(name){
-        return this.data[name];
+    isValid: function() {
+        var me = this,
+            invalid;
+        me.batchLayouts(function() {
+            invalid = me.getFields().filterBy(function(field) {
+                return !field.validate();
+            });
+        });
+        return invalid.length < 1;
     },
 
     
-    beginEdit : function(){
-        this.editing = true;
-        this.modified = this.modified || {};
+    checkValidity: function() {
+        var me = this,
+            valid = !me.hasInvalidField();
+        if (valid !== me.wasValid) {
+            me.onValidityChange(valid);
+            me.fireEvent('validitychange', me, valid);
+            me.wasValid = valid;
+        }
     },
 
     
-    cancelEdit : function(){
-        this.editing = false;
-        delete this.modified;
+    onValidityChange: function(valid) {
+        var boundItems = this.getBoundItems();
+        if (boundItems) {
+            boundItems.each(function(cmp) {
+                if (cmp.disabled === valid) {
+                    cmp.setDisabled(!valid);
+                }
+            });
+        }
     },
 
     
-    endEdit : function(){
-        this.editing = false;
-        if(this.dirty){
-            this.afterEdit();
-        }
+    isDirty: function() {
+        return !!this.getFields().findBy(function(f) {
+            return f.isDirty();
+        });
     },
 
     
-    reject : function(silent){
-        var m = this.modified;
-        for(var n in m){
-            if(typeof m[n] != "function"){
-                this.data[n] = m[n];
-            }
-        }
-        this.dirty = false;
-        delete this.modified;
-        this.editing = false;
-        if(silent !== true){
-            this.afterReject();
+    checkDirty: function() {
+        var dirty = this.isDirty();
+        if (dirty !== this.wasDirty) {
+            this.fireEvent('dirtychange', this, dirty);
+            this.wasDirty = dirty;
         }
     },
 
     
-    commit : function(silent){
-        this.dirty = false;
-        delete this.modified;
-        this.editing = false;
-        if(silent !== true){
-            this.afterCommit();
-        }
+    hasUpload: function() {
+        return !!this.getFields().findBy(function(f) {
+            return f.isFileUpload();
+        });
     },
 
     
-    getChanges : function(){
-        var m = this.modified, cs = {};
-        for(var n in m){
-            if(m.hasOwnProperty(n)){
-                cs[n] = this.data[n];
-            }
+    doAction: function(action, options) {
+        if (Ext.isString(action)) {
+            action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this}));
+        }
+        if (this.fireEvent('beforeaction', this, action) !== false) {
+            this.beforeAction(action);
+            Ext.defer(action.run, 100, action);
         }
-        return cs;
+        return this;
     },
 
     
-    hasError : function(){
-        return this.error !== null;
+    submit: function(options) {
+        return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
     },
 
     
-    clearError : function(){
-        this.error = null;
+    load: function(options) {
+        return this.doAction(this.api ? 'directload' : 'load', options);
     },
 
     
-    copy : function(newId) {
-        return new this.constructor(Ext.apply({}, this.data), newId || this.id);
+    updateRecord: function(record) {
+        var fields = record.fields,
+            values = this.getFieldValues(),
+            name,
+            obj = {};
+
+        fields.each(function(f) {
+            name = f.name;
+            if (name in values) {
+                obj[name] = values[name];
+            }
+        });
+
+        record.beginEdit();
+        record.set(obj);
+        record.endEdit();
+
+        return this;
     },
 
     
-    isModified : function(fieldName){
-        return !!(this.modified && this.modified.hasOwnProperty(fieldName));
+    loadRecord: function(record) {
+        this._record = record;
+        return this.setValues(record.data);
     },
 
     
-    isValid : function() {
-        return this.fields.find(function(f) {
-            return (f.allowBlank === false && Ext.isEmpty(this.data[f.name])) ? true : false;
-        },this) ? false : true;
+    getRecord: function() {
+        return this._record;
     },
 
     
-    markDirty : function(){
-        this.dirty = true;
-        if(!this.modified){
-            this.modified = {};
-        }
-        this.fields.each(function(f) {
-            this.modified[f.name] = this.data[f.name];
-        },this);
-    }
-};
+    beforeAction: function(action) {
+        var waitMsg = action.waitMsg,
+            maskCls = Ext.baseCSSPrefix + 'mask-loading',
+            waitMsgTarget;
 
-Ext.StoreMgr = Ext.apply(new Ext.util.MixedCollection(), {
-    
+        
+        this.getFields().each(function(f) {
+            if (f.isFormField && f.syncValue) {
+                f.syncValue();
+            }
+        });
 
-    
-    register : function(){
-        for(var i = 0, s; (s = arguments[i]); i++){
-            this.add(s);
+        if (waitMsg) {
+            waitMsgTarget = this.waitMsgTarget;
+            if (waitMsgTarget === true) {
+                this.owner.el.mask(waitMsg, maskCls);
+            } else if (waitMsgTarget) {
+                waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
+                waitMsgTarget.mask(waitMsg, maskCls);
+            } else {
+                Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
+            }
         }
     },
 
     
-    unregister : function(){
-        for(var i = 0, s; (s = arguments[i]); i++){
-            this.remove(this.lookup(s));
+    afterAction: function(action, success) {
+        if (action.waitMsg) {
+            var MessageBox = Ext.MessageBox,
+                waitMsgTarget = this.waitMsgTarget;
+            if (waitMsgTarget === true) {
+                this.owner.el.unmask();
+            } else if (waitMsgTarget) {
+                waitMsgTarget.unmask();
+            } else {
+                MessageBox.updateProgress(1);
+                MessageBox.hide();
+            }
+        }
+        if (success) {
+            if (action.reset) {
+                this.reset();
+            }
+            Ext.callback(action.success, action.scope || action, [this, action]);
+            this.fireEvent('actioncomplete', this, action);
+        } else {
+            Ext.callback(action.failure, action.scope || action, [this, action]);
+            this.fireEvent('actionfailed', this, action);
         }
     },
 
+
     
-    lookup : function(id){
-        if(Ext.isArray(id)){
-            var fields = ['field1'], expand = !Ext.isArray(id[0]);
-            if(!expand){
-                for(var i = 2, len = id[0].length; i <= len; ++i){
-                    fields.push('field' + i);
-                }
+    findField: function(id) {
+        return this.getFields().findBy(function(f) {
+            return f.id === id || f.getName() === id;
+        });
+    },
+
+
+    
+    markInvalid: function(errors) {
+        var me = this;
+
+        function mark(fieldId, msg) {
+            var field = me.findField(fieldId);
+            if (field) {
+                field.markInvalid(msg);
             }
-            return new Ext.data.ArrayStore({
-                fields: fields,
-                data: id,
-                expandData: expand,
-                autoDestroy: true,
-                autoCreated: true
+        }
 
+        if (Ext.isArray(errors)) {
+            Ext.each(errors, function(err) {
+                mark(err.id, err.msg);
             });
         }
-        return Ext.isObject(id) ? (id.events ? id : Ext.create(id, 'store')) : this.get(id);
+        else if (errors instanceof Ext.data.Errors) {
+            errors.each(function(err) {
+                mark(err.field, err.message);
+            });
+        }
+        else {
+            Ext.iterate(errors, mark);
+        }
+        return this;
     },
 
     
-    getKey : function(o){
-         return o.storeId;
-    }
-});
-Ext.data.Store = Ext.extend(Ext.util.Observable, {
-    
-    
-    
-    
-    
-    
-    
-    writer : undefined,
-    
-    
-    
-    remoteSort : false,
+    setValues: function(values) {
+        var me = this;
 
-    
-    autoDestroy : false,
+        function setVal(fieldId, val) {
+            var field = me.findField(fieldId);
+            if (field) {
+                field.setValue(val);
+                if (me.trackResetOnLoad) {
+                    field.resetOriginalValue();
+                }
+            }
+        }
 
-    
-    pruneModifiedRecords : false,
+        if (Ext.isArray(values)) {
+            
+            Ext.each(values, function(val) {
+                setVal(val.id, val.value);
+            });
+        } else {
+            
+            Ext.iterate(values, setVal);
+        }
+        return this;
+    },
 
     
-    lastOptions : null,
+    getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
+        var values = {};
 
-    
-    autoSave : true,
+        this.getFields().each(function(field) {
+            if (!dirtyOnly || field.isDirty()) {
+                var data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
+                if (Ext.isObject(data)) {
+                    Ext.iterate(data, function(name, val) {
+                        if (includeEmptyText && val === '') {
+                            val = field.emptyText || '';
+                        }
+                        if (name in values) {
+                            var bucket = values[name],
+                                isArray = Ext.isArray;
+                            if (!isArray(bucket)) {
+                                bucket = values[name] = [bucket];
+                            }
+                            if (isArray(val)) {
+                                values[name] = bucket.concat(val);
+                            } else {
+                                bucket.push(val);
+                            }
+                        } else {
+                            values[name] = val;
+                        }
+                    });
+                }
+            }
+        });
 
-    
-    batch : true,
+        if (asString) {
+            values = Ext.Object.toQueryString(values);
+        }
+        return values;
+    },
 
     
-    restful: false,
+    getFieldValues: function(dirtyOnly) {
+        return this.getValues(false, dirtyOnly, false, true);
+    },
 
     
-    paramNames : undefined,
+    clearInvalid: function() {
+        var me = this;
+        me.batchLayouts(function() {
+            me.getFields().each(function(f) {
+                f.clearInvalid();
+            });
+        });
+        return me;
+    },
 
     
-    defaultParamNames : {
-        start : 'start',
-        limit : 'limit',
-        sort : 'sort',
-        dir : 'dir'
+    reset: function() {
+        var me = this;
+        me.batchLayouts(function() {
+            me.getFields().each(function(f) {
+                f.reset();
+            });
+        });
+        return me;
     },
 
     
-    isDestroyed: false,
+    applyToFields: function(obj) {
+        this.getFields().each(function(f) {
+            Ext.apply(f, obj);
+        });
+        return this;
+    },
 
     
-    hasMultiSort: false,
+    applyIfToFields: function(obj) {
+        this.getFields().each(function(f) {
+            Ext.applyIf(f, obj);
+        });
+        return this;
+    },
 
     
-    batchKey : '_ext_batch_',
-
-    constructor : function(config){
-        this.data = new Ext.util.MixedCollection(false);
-        this.data.getKey = function(o){
-            return o.id;
-        };
-
+    batchLayouts: function(fn) {
+        var me = this,
+            suspended = new Ext.util.HashMap();
 
         
-        this.removed = [];
+        me.getFields().each(function(field) {
+            var ownerCt = field.ownerCt;
+            if (!suspended.contains(ownerCt)) {
+                suspended.add(ownerCt);
+                ownerCt.oldSuspendLayout = ownerCt.suspendLayout;
+                ownerCt.suspendLayout = true;
+            }
+        });
 
-        if(config && config.data){
-            this.inlineData = config.data;
-            delete config.data;
-        }
+        
+        fn();
 
-        Ext.apply(this, config);
+        
+        suspended.each(function(id, ct) {
+            ct.suspendLayout = ct.oldSuspendLayout;
+            delete ct.oldSuspendLayout;
+        });
 
         
-        this.baseParams = Ext.isObject(this.baseParams) ? this.baseParams : {};
+        me.owner.doComponentLayout();
+    }
+});
 
-        this.paramNames = Ext.applyIf(this.paramNames || {}, this.defaultParamNames);
 
-        if((this.url || this.api) && !this.proxy){
-            this.proxy = new Ext.data.HttpProxy({url: this.url, api: this.api});
-        }
-        
-        if (this.restful === true && this.proxy) {
-            
-            
-            this.batch = false;
-            Ext.data.Api.restify(this.proxy);
-        }
+Ext.define('Ext.form.FieldAncestor', {
 
-        if(this.reader){ 
-            if(!this.recordType){
-                this.recordType = this.reader.recordType;
-            }
-            if(this.reader.onMetaChange){
-                this.reader.onMetaChange = this.reader.onMetaChange.createSequence(this.onMetaChange, this);
-            }
-            if (this.writer) { 
-                if (this.writer instanceof(Ext.data.DataWriter) === false) {    
-                    this.writer = this.buildWriter(this.writer);
-                }
-                this.writer.meta = this.reader.meta;
-                this.pruneModifiedRecords = true;
-            }
-        }
+    
 
-        
 
-        if(this.recordType){
-            
-            this.fields = this.recordType.prototype.fields;
-        }
-        this.modified = [];
+    
+    initFieldAncestor: function() {
+        var me = this,
+            onSubtreeChange = me.onFieldAncestorSubtreeChange;
 
-        this.addEvents(
-            
-            'datachanged',
-            
-            'metachange',
-            
-            'add',
-            
-            'remove',
+        me.addEvents(
             
-            'update',
-            
-            'clear',
-            
-            'exception',
-            
-            'beforeload',
-            
-            'load',
-            
-            'loadexception',
-            
-            'beforewrite',
-            
-            'write',
-            
-            'beforesave',
-            
-            'save'
+            'fieldvaliditychange',
 
+            
+            'fielderrorchange'
         );
 
-        if(this.proxy){
-            
-            this.relayEvents(this.proxy,  ['loadexception', 'exception']);
-        }
         
-        if (this.writer) {
-            this.on({
-                scope: this,
-                add: this.createRecords,
-                remove: this.destroyRecord,
-                update: this.updateRecord,
-                clear: this.onClear
-            });
+        me.on('add', onSubtreeChange, me);
+        me.on('remove', onSubtreeChange, me);
+
+        me.initFieldDefaults();
+    },
+
+    
+    initFieldDefaults: function() {
+        if (!this.fieldDefaults) {
+            this.fieldDefaults = {};
         }
+    },
 
-        this.sortToggle = {};
-        if(this.sortField){
-            this.setDefaultSort(this.sortField, this.sortDir);
-        }else if(this.sortInfo){
-            this.setDefaultSort(this.sortInfo.field, this.sortInfo.direction);
+    
+    onFieldAncestorSubtreeChange: function(parent, child) {
+        var me = this,
+            isAdding = !!child.ownerCt;
+
+        function handleCmp(cmp) {
+            var isLabelable = cmp.isFieldLabelable,
+                isField = cmp.isFormField;
+            if (isLabelable || isField) {
+                if (isLabelable) {
+                    me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
+                }
+                if (isField) {
+                    me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
+                }
+            }
+            else if (cmp.isContainer) {
+                Ext.Array.forEach(cmp.getRefItems(), handleCmp);
+            }
         }
+        handleCmp(child);
+    },
 
-        Ext.data.Store.superclass.constructor.call(this);
+    
+    onLabelableAdded: function(labelable) {
+        var me = this;
 
-        if(this.id){
-            this.storeId = this.id;
-            delete this.id;
-        }
-        if(this.storeId){
-            Ext.StoreMgr.register(this);
-        }
-        if(this.inlineData){
-            this.loadData(this.inlineData);
-            delete this.inlineData;
-        }else if(this.autoLoad){
-            this.load.defer(10, this, [
-                typeof this.autoLoad == 'object' ?
-                    this.autoLoad : undefined]);
-        }
         
-        this.batchCounter = 0;
-        this.batches = {};
+        me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
+
+        labelable.setFieldDefaults(me.fieldDefaults);
     },
 
     
-    buildWriter : function(config) {
-        var klass = undefined,
-            type = (config.format || 'json').toLowerCase();
-        switch (type) {
-            case 'json':
-                klass = Ext.data.JsonWriter;
-                break;
-            case 'xml':
-                klass = Ext.data.XmlWriter;
-                break;
-            default:
-                klass = Ext.data.JsonWriter;
-        }
-        return new klass(config);
+    onFieldAdded: function(field) {
+        var me = this;
+        me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
     },
 
     
-    destroy : function(){
-        if(!this.isDestroyed){
-            if(this.storeId){
-                Ext.StoreMgr.unregister(this);
-            }
-            this.clearData();
-            this.data = null;
-            Ext.destroy(this.proxy);
-            this.reader = this.writer = null;
-            this.purgeListeners();
-            this.isDestroyed = true;
-        }
+    onLabelableRemoved: function(labelable) {
+        var me = this;
+        me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
     },
 
     
-    add : function(records){
-        records = [].concat(records);
-        if(records.length < 1){
-            return;
-        }
-        for(var i = 0, len = records.length; i < len; i++){
-            records[i].join(this);
-        }
-        var index = this.data.length;
-        this.data.addAll(records);
-        if(this.snapshot){
-            this.snapshot.addAll(records);
-        }
-        this.fireEvent('add', this, records, index);
+    onFieldRemoved: function(field) {
+        var me = this;
+        me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
     },
 
     
-    addSorted : function(record){
-        var index = this.findInsertIndex(record);
-        this.insert(index, record);
+    handleFieldValidityChange: function(field, isValid) {
+        var me = this;
+        me.fireEvent('fieldvaliditychange', me, field, isValid);
+        me.onFieldValidityChange();
     },
 
     
-    remove : function(record){
-        if(Ext.isArray(record)){
-            Ext.each(record, function(r){
-                this.remove(r);
-            }, this);
-            return;
-        }
-        var index = this.data.indexOf(record);
-        if(index > -1){
-            record.join(null);
-            this.data.removeAt(index);
+    handleFieldErrorChange: function(labelable, activeError) {
+        var me = this;
+        me.fireEvent('fielderrorchange', me, labelable, activeError);
+        me.onFieldErrorChange();
+    },
+
+    
+    onFieldValidityChange: Ext.emptyFn,
+
+    
+    onFieldErrorChange: Ext.emptyFn
+
+});
+
+Ext.define('Ext.layout.container.CheckboxGroup', {
+    extend: 'Ext.layout.container.Container',
+    alias: ['layout.checkboxgroup'],
+
+
+    onLayout: function() {
+        var numCols = this.getColCount(),
+            shadowCt = this.getShadowCt(),
+            owner = this.owner,
+            items = owner.items,
+            shadowItems = shadowCt.items,
+            numItems = items.length,
+            colIndex = 0,
+            i, numRows;
+
+        
+        
+        
+        
+
+        shadowItems.each(function(col) {
+            col.items.clear();
+        });
+
+        
+        
+        while (shadowItems.length > numCols) {
+            shadowCt.remove(shadowItems.last());
         }
-        if(this.pruneModifiedRecords){
-            this.modified.remove(record);
+        while (shadowItems.length < numCols) {
+            shadowCt.add({
+                xtype: 'container',
+                cls: owner.groupCls,
+                flex: 1
+            });
         }
-        if(this.snapshot){
-            this.snapshot.remove(record);
+
+        if (owner.vertical) {
+            numRows = Math.ceil(numItems / numCols);
+            for (i = 0; i < numItems; i++) {
+                if (i > 0 && i % numRows === 0) {
+                    colIndex++;
+                }
+                shadowItems.getAt(colIndex).items.add(items.getAt(i));
+            }
+        } else {
+            for (i = 0; i < numItems; i++) {
+                colIndex = i % numCols;
+                shadowItems.getAt(colIndex).items.add(items.getAt(i));
+            }
         }
-        if(index > -1){
-            this.fireEvent('remove', this, record, index);
+
+        if (!shadowCt.rendered) {
+            shadowCt.render(this.getRenderTarget());
+        } else {
+            
+            
+            shadowItems.each(function(col) {
+                var layout = col.getLayout();
+                layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
+            });
         }
+
+        shadowCt.doComponentLayout();
     },
 
+
     
-    removeAt : function(index){
-        this.remove(this.getAt(index));
-    },
+    renderItems: Ext.emptyFn,
+
 
     
-    removeAll : function(silent){
-        var items = [];
-        this.each(function(rec){
-            items.push(rec);
-        });
-        this.clearData();
-        if(this.snapshot){
-            this.snapshot.clear();
-        }
-        if(this.pruneModifiedRecords){
-            this.modified = [];
-        }
-        if (silent !== true) {  
-            this.fireEvent('clear', this, items);
+    getShadowCt: function() {
+        var me = this,
+            shadowCt = me.shadowCt,
+            owner, items, item, columns, columnsIsArray, numCols, i;
+
+        if (!shadowCt) {
+            
+            owner = me.owner;
+            columns = owner.columns;
+            columnsIsArray = Ext.isArray(columns);
+            numCols = me.getColCount();
+            items = [];
+            for(i = 0; i < numCols; i++) {
+                item = {
+                    xtype: 'container',
+                    cls: owner.groupCls
+                };
+                if (columnsIsArray) {
+                    
+                    
+                    if (columns[i] < 1) {
+                        item.flex = columns[i];
+                    } else {
+                        item.width = columns[i];
+                    }
+                }
+                else {
+                    
+                    item.flex = 1;
+                }
+                items.push(item);
+            }
+
+            
+            shadowCt = me.shadowCt = Ext.createWidget('container', {
+                layout: 'hbox',
+                items: items,
+                ownerCt: owner
+            });
         }
+        
+        return shadowCt;
     },
 
-    
-    onClear: function(store, records){
-        Ext.each(records, function(rec, index){
-            this.destroyRecord(this, rec, index);
-        }, this);
-    },
 
     
-    insert : function(index, records){
-        records = [].concat(records);
-        for(var i = 0, len = records.length; i < len; i++){
-            this.data.insert(index, records[i]);
-            records[i].join(this);
-        }
-        if(this.snapshot){
-            this.snapshot.addAll(records);
-        }
-        this.fireEvent('add', this, records, index);
-    },
+    getColCount: function() {
+        var owner = this.owner,
+            colsCfg = owner.columns;
+        return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
+    }
 
-    
-    indexOf : function(record){
-        return this.data.indexOf(record);
+});
+
+
+Ext.define('Ext.form.FieldContainer', {
+    extend: 'Ext.container.Container',
+    mixins: {
+        labelable: 'Ext.form.Labelable',
+        fieldAncestor: 'Ext.form.FieldAncestor'
     },
+    alias: 'widget.fieldcontainer',
+
+    componentLayout: 'field',
 
     
-    indexOfId : function(id){
-        return this.data.indexOfKey(id);
-    },
+    combineLabels: false,
 
     
-    getById : function(id){
-        return (this.snapshot || this.data).key(id);
-    },
+    labelConnector: ', ',
 
     
-    getAt : function(index){
-        return this.data.itemAt(index);
+    combineErrors: false,
+
+    maskOnDisable: false,
+
+    initComponent: function() {
+        var me = this,
+            onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
+
+        
+        me.initLabelable();
+        me.initFieldAncestor();
+
+        me.callParent();
     },
 
     
-    getRange : function(start, end){
-        return this.data.getRange(start, end);
+    onLabelableAdded: function(labelable) {
+        var me = this;
+        me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
+        me.updateLabel();
     },
 
     
-    storeOptions : function(o){
-        o = Ext.apply({}, o);
-        delete o.callback;
-        delete o.scope;
-        this.lastOptions = o;
+    onLabelableRemoved: function(labelable) {
+        var me = this;
+        me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
+        me.updateLabel();
     },
 
-    
-    clearData: function(){
-        this.data.each(function(rec) {
-            rec.join(null);
-        });
-        this.data.clear();
+    onRender: function() {
+        var me = this;
+
+        me.onLabelableRender();
+
+        me.callParent(arguments);
     },
 
-    
-    load : function(options) {
-        options = Ext.apply({}, options);
-        this.storeOptions(options);
-        if(this.sortInfo && this.remoteSort){
-            var pn = this.paramNames;
-            options.params = Ext.apply({}, options.params);
-            options.params[pn.sort] = this.sortInfo.field;
-            options.params[pn.dir] = this.sortInfo.direction;
-        }
-        try {
-            return this.execute('read', null, options); 
-        } catch(e) {
-            this.handleException(e);
-            return false;
+    initRenderTpl: function() {
+        var me = this;
+        if (!me.hasOwnProperty('renderTpl')) {
+            me.renderTpl = me.getTpl('labelableRenderTpl');
         }
+        return me.callParent();
     },
 
-    
-    updateRecord : function(store, record, action) {
-        if (action == Ext.data.Record.EDIT && this.autoSave === true && (!record.phantom || (record.phantom && record.isValid()))) {
-            this.save();
-        }
+    initRenderData: function() {
+        return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
     },
 
     
-    createRecords : function(store, rs, index) {
-        for (var i = 0, len = rs.length; i < len; i++) {
-            if (rs[i].phantom && rs[i].isValid()) {
-                rs[i].markDirty();  
-                this.modified.push(rs[i]);  
-            }
-        }
-        if (this.autoSave === true) {
-            this.save();
+    getFieldLabel: function() {
+        var label = this.fieldLabel || '';
+        if (!label && this.combineLabels) {
+            label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
+                return field.getFieldLabel();
+            }).join(this.labelConnector);
         }
+        return label;
     },
 
     
-    destroyRecord : function(store, record, index) {
-        if (this.modified.indexOf(record) != -1) {  
-            this.modified.remove(record);
-        }
-        if (!record.phantom) {
-            this.removed.push(record);
-
-            
-            
-            
-            record.lastIndex = index;
-
-            if (this.autoSave === true) {
-                this.save();
-            }
+    updateLabel: function() {
+        var me = this,
+            label = me.labelEl;
+        if (label) {
+            label.update(me.getFieldLabel());
         }
     },
 
+
     
-    execute : function(action, rs, options,  batch) {
-        
-        if (!Ext.data.Api.isAction(action)) {
-            throw new Ext.data.Api.Error('execute', action);
-        }
-        
-        options = Ext.applyIf(options||{}, {
-            params: {}
-        });
-        if(batch !== undefined){
-            this.addToBatch(batch);
-        }
-        
-        
-        var doRequest = true;
+    onFieldErrorChange: function(field, activeError) {
+        if (this.combineErrors) {
+            var me = this,
+                oldError = me.getActiveError(),
+                invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
+                    return field.hasActiveError();
+                }),
+                newErrors = me.getCombinedErrors(invalidFields);
 
-        if (action === 'read') {
-            doRequest = this.fireEvent('beforeload', this, options);
-            Ext.applyIf(options.params, this.baseParams);
-        }
-        else {
-            
-            
-            if (this.writer.listful === true && this.restful !== true) {
-                rs = (Ext.isArray(rs)) ? rs : [rs];
-            }
-            
-            else if (Ext.isArray(rs) && rs.length == 1) {
-                rs = rs.shift();
-            }
-            
-            if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
-                this.writer.apply(options.params, this.baseParams, action, rs);
+            if (newErrors) {
+                me.setActiveErrors(newErrors);
+            } else {
+                me.unsetActiveError();
             }
-        }
-        if (doRequest !== false) {
-            
-            if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
-                options.params.xaction = action;    
+
+            if (oldError !== me.getActiveError()) {
+                me.doComponentLayout();
             }
-            
-            
-            
-            
-            
-            this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
         }
-        return doRequest;
     },
 
     
-    save : function() {
-        if (!this.writer) {
-            throw new Ext.data.Store.Error('writer-undefined');
-        }
+    getCombinedErrors: function(invalidFields) {
+        var forEach = Ext.Array.forEach,
+            errors = [];
+        forEach(invalidFields, function(field) {
+            forEach(field.getActiveErrors(), function(error) {
+                var label = field.getFieldLabel();
+                errors.push((label ? label + ': ' : '') + error);
+            });
+        });
+        return errors;
+    },
 
-        var queue = [],
-            len,
-            trans,
-            batch,
-            data = {};
-        
-        if(this.removed.length){
-            queue.push(['destroy', this.removed]);
-        }
+    getTargetEl: function() {
+        return this.bodyEl || this.callParent();
+    }
+});
 
-        
-        var rs = [].concat(this.getModifiedRecords());
-        if(rs.length){
-            
-            var phantoms = [];
-            for(var i = rs.length-1; i >= 0; i--){
-                if(rs[i].phantom === true){
-                    var rec = rs.splice(i, 1).shift();
-                    if(rec.isValid()){
-                        phantoms.push(rec);
-                    }
-                }else if(!rs[i].isValid()){ 
-                    rs.splice(i,1);
-                }
-            }
-            
-            if(phantoms.length){
-                queue.push(['create', phantoms]);
-            }
 
-            
-            if(rs.length){
-                queue.push(['update', rs]);
-            }
-        }
-        len = queue.length;
-        if(len){
-            batch = ++this.batchCounter;
-            for(var i = 0; i < len; ++i){
-                trans = queue[i];
-                data[trans[0]] = trans[1];
-            }
-            if(this.fireEvent('beforesave', this, data) !== false){
-                for(var i = 0; i < len; ++i){
-                    trans = queue[i];
-                    this.doTransaction(trans[0], trans[1], batch);
-                }
-                return batch;
-            }
-        }
-        return -1;
+Ext.define('Ext.form.CheckboxGroup', {
+    extend:'Ext.form.FieldContainer',
+    mixins: {
+        field: 'Ext.form.field.Field'
     },
+    alias: 'widget.checkboxgroup',
+    requires: ['Ext.layout.container.CheckboxGroup', 'Ext.form.field.Base'],
 
     
-    doTransaction : function(action, rs, batch) {
-        function transaction(records) {
-            try{
-                this.execute(action, records, undefined, batch);
-            }catch (e){
-                this.handleException(e);
-            }
-        }
-        if(this.batch === false){
-            for(var i = 0, len = rs.length; i < len; i++){
-                transaction.call(this, rs[i]);
-            }
-        }else{
-            transaction.call(this, rs);
-        }
-    },
 
     
-    addToBatch : function(batch){
-        var b = this.batches,
-            key = this.batchKey + batch,
-            o = b[key];
 
-        if(!o){
-            b[key] = o = {
-                id: batch,
-                count: 0,
-                data: {}
-            };
-        }
-        ++o.count;
-    },
+    
+    columns : 'auto',
 
-    removeFromBatch : function(batch, action, data){
-        var b = this.batches,
-            key = this.batchKey + batch,
-            o = b[key],
-            data,
-            arr;
+    
+    vertical : false,
 
+    
+    allowBlank : true,
 
-        if(o){
-            arr = o.data[action] || [];
-            o.data[action] = arr.concat(data);
-            if(o.count === 1){
-                data = o.data;
-                delete b[key];
-                this.fireEvent('save', this, batch, data);
-            }else{
-                --o.count;
-            }
-        }
-    },
+    
+    blankText : "You must select at least one item in this group",
 
     
+    defaultType : 'checkboxfield',
+
     
-    createCallback : function(action, rs, batch) {
-        var actions = Ext.data.Api.actions;
-        return (action == 'read') ? this.loadRecords : function(data, response, success) {
-            
-            this['on' + Ext.util.Format.capitalize(action) + 'Records'](success, rs, [].concat(data));
-            
-            if (success === true) {
-                this.fireEvent('write', this, action, data, response, rs);
-            }
-            this.removeFromBatch(batch, action, data);
-        };
-    },
+    groupCls : Ext.baseCSSPrefix + 'form-check-group',
 
     
+    fieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
+
     
+    layout: 'checkboxgroup',
+
+    initComponent: function() {
+        var me = this;
+        me.callParent();
+        me.initField();
+    },
+
     
-    clearModified : function(rs) {
-        if (Ext.isArray(rs)) {
-            for (var n=rs.length-1;n>=0;n--) {
-                this.modified.splice(this.modified.indexOf(rs[n]), 1);
-            }
-        } else {
-            this.modified.splice(this.modified.indexOf(rs), 1);
+    initValue: function() {
+        var me = this,
+            valueCfg = me.value;
+        me.originalValue = me.lastValue = valueCfg || me.getValue();
+        if (valueCfg) {
+            me.setValue(valueCfg);
         }
     },
 
     
-    reMap : function(record) {
-        if (Ext.isArray(record)) {
-            for (var i = 0, len = record.length; i < len; i++) {
-                this.reMap(record[i]);
-            }
-        } else {
-            delete this.data.map[record._phid];
-            this.data.map[record.id] = record;
-            var index = this.data.keys.indexOf(record._phid);
-            this.data.keys.splice(index, 1, record.id);
-            delete record._phid;
+    onFieldAdded: function(field) {
+        var me = this;
+        if (field.isCheckbox) {
+            me.mon(field, 'change', me.checkChange, me);
         }
+        me.callParent(arguments);
     },
 
-    
-    onCreateRecords : function(success, rs, data) {
-        if (success === true) {
-            try {
-                this.reader.realize(rs, data);
-                this.reMap(rs);
-            }
-            catch (e) {
-                this.handleException(e);
-                if (Ext.isArray(rs)) {
-                    
-                    this.onCreateRecords(success, rs, data);
-                }
-            }
+    onFieldRemoved: function(field) {
+        var me = this;
+        if (field.isCheckbox) {
+            me.mun(field, 'change', me.checkChange, me);
         }
+        me.callParent(arguments);
     },
 
     
-    onUpdateRecords : function(success, rs, data) {
-        if (success === true) {
-            try {
-                this.reader.update(rs, data);
-            } catch (e) {
-                this.handleException(e);
-                if (Ext.isArray(rs)) {
-                    
-                    this.onUpdateRecords(success, rs, data);
-                }
-            }
-        }
+    isEqual: function(value1, value2) {
+        var toQueryString = Ext.Object.toQueryString;
+        return toQueryString(value1) === toQueryString(value2);
     },
 
     
-    onDestroyRecords : function(success, rs, data) {
-        
-        rs = (rs instanceof Ext.data.Record) ? [rs] : [].concat(rs);
-        for (var i=0,len=rs.length;i<len;i++) {
-            this.removed.splice(this.removed.indexOf(rs[i]), 1);
-        }
-        if (success === false) {
-            
-            
-            for (i=rs.length-1;i>=0;i--) {
-                this.insert(rs[i].lastIndex, rs[i]);    
-            }
+    getErrors: function() {
+        var errors = [];
+        if (!this.allowBlank && Ext.isEmpty(this.getChecked())) {
+            errors.push(this.blankText);
         }
+        return errors;
     },
 
     
-    handleException : function(e) {
-        
-        Ext.handleError(e);
+    getBoxes: function() {
+        return this.query('[isCheckbox]');
     },
 
     
-    reload : function(options){
-        this.load(Ext.applyIf(options||{}, this.lastOptions));
+    eachBox: function(fn, scope) {
+        Ext.Array.forEach(this.getBoxes(), fn, scope || this);
     },
 
     
+    getChecked: function() {
+        return Ext.Array.filter(this.getBoxes(), function(cb) {
+            return cb.getValue();
+        });
+    },
+
     
-    loadRecords : function(o, options, success){
-        if (this.isDestroyed === true) {
-            return;
-        }
-        if(!o || success === false){
-            if(success !== false){
-                this.fireEvent('load', this, [], options);
-            }
-            if(options.callback){
-                options.callback.call(options.scope || this, [], options, false, o);
-            }
-            return;
-        }
-        var r = o.records, t = o.totalRecords || r.length;
-        if(!options || options.add !== true){
-            if(this.pruneModifiedRecords){
-                this.modified = [];
-            }
-            for(var i = 0, len = r.length; i < len; i++){
-                r[i].join(this);
-            }
-            if(this.snapshot){
-                this.data = this.snapshot;
-                delete this.snapshot;
-            }
-            this.clearData();
-            this.data.addAll(r);
-            this.totalLength = t;
-            this.applySort();
-            this.fireEvent('datachanged', this);
-        }else{
-            this.totalLength = Math.max(t, this.data.length+r.length);
-            this.add(r);
-        }
-        this.fireEvent('load', this, r, options);
-        if(options.callback){
-            options.callback.call(options.scope || this, r, options, true);
-        }
+    isDirty: function(){
+        return Ext.Array.some(this.getBoxes(), function(cb) {
+            return cb.isDirty();
+        });
+    },
+
+    
+    setReadOnly: function(readOnly) {
+        this.eachBox(function(cb) {
+            cb.setReadOnly(readOnly);
+        });
+        this.readOnly = readOnly;
     },
 
     
-    loadData : function(o, append){
-        var r = this.reader.readRecords(o);
-        this.loadRecords(r, {add: append}, true);
+    reset: function() {
+        var me = this,
+            hadError = me.hasActiveError(),
+            preventMark = me.preventMark;
+        me.preventMark = true;
+        me.batchChanges(function() {
+            me.eachBox(function(cb) {
+                cb.reset();
+            });
+        });
+        me.preventMark = preventMark;
+        me.unsetActiveError();
+        if (hadError) {
+            me.doComponentLayout();
+        }
     },
 
     
-    getCount : function(){
-        return this.data.length || 0;
+    resetOriginalValue: function() {
+        
+        
+        Ext.defer(function() {
+            this.callParent();
+        }, 1, this);
     },
 
+
     
-    getTotalCount : function(){
-        return this.totalLength || 0;
+    setValue: function(value) {
+        var me = this;
+        me.batchChanges(function() {
+            me.eachBox(function(cb) {
+                var name = cb.getName(),
+                    cbValue = false;
+                if (value && name in value) {
+                    if (Ext.isArray(value[name])) {
+                        cbValue = Ext.Array.contains(value[name], cb.inputValue);
+                    } else {
+                        
+                        cbValue = value[name];
+                    }
+                }
+                cb.setValue(cbValue);
+            });
+        });
+        return me;
     },
 
+
     
-    getSortState : function(){
-        return this.sortInfo;
+    getValue: function() {
+        var values = {};
+        this.eachBox(function(cb) {
+            var name = cb.getName(),
+                inputValue = cb.inputValue,
+                bucket;
+            if (cb.getValue()) {
+                if (name in values) {
+                    bucket = values[name];
+                    if (!Ext.isArray(bucket)) {
+                        bucket = values[name] = [bucket];
+                    }
+                    bucket.push(inputValue);
+                } else {
+                    values[name] = inputValue;
+                }
+            }
+        });
+        return values;
     },
 
     
-    applySort : function(){
-        if ((this.sortInfo || this.multiSortInfo) && !this.remoteSort) {
-            this.sortData();
-        }
+    getSubmitData: function() {
+        return null;
     },
 
     
-    sortData : function() {
-        var sortInfo  = this.hasMultiSort ? this.multiSortInfo : this.sortInfo,
-            direction = sortInfo.direction || "ASC",
-            sorters   = sortInfo.sorters,
-            sortFns   = [];
+    getModelData: function() {
+        return null;
+    },
 
-        
-        if (!this.hasMultiSort) {
-            sorters = [{direction: direction, field: sortInfo.field}];
-        }
+    validate: function() {
+        var me = this,
+            errors = me.getErrors(),
+            isValid = Ext.isEmpty(errors),
+            wasValid = !me.hasActiveError();
 
-        
-        for (var i=0, j = sorters.length; i < j; i++) {
-            sortFns.push(this.createSortFunction(sorters[i].field, sorters[i].direction));
+        if (isValid) {
+            me.unsetActiveError();
+        } else {
+            me.setActiveError(errors);
         }
-        
-        if (sortFns.length == 0) {
-            return;
+        if (isValid !== wasValid) {
+            me.fireEvent('validitychange', me, isValid);
+            me.doComponentLayout();
         }
 
-        
-        
-        var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
-
-        
-        var fn = function(r1, r2) {
-          var result = sortFns[0].call(this, r1, r2);
-
-          
-          if (sortFns.length > 1) {
-              for (var i=1, j = sortFns.length; i < j; i++) {
-                  result = result || sortFns[i].call(this, r1, r2);
-              }
-          }
+        return isValid;
+    }
 
-          return directionModifier * result;
-        };
+}, function() {
 
-        
-        this.data.sort(direction, fn);
-        if (this.snapshot && this.snapshot != this.data) {
-            this.snapshot.sort(direction, fn);
-        }
-    },
+    this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid']);
 
-    
-    createSortFunction: function(field, direction) {
-        direction = direction || "ASC";
-        var directionModifier = direction.toUpperCase() == "DESC" ? -1 : 1;
+});
 
-        var sortType = this.fields.get(field).sortType;
 
-        
-        
-        return function(r1, r2) {
-            var v1 = sortType(r1.data[field]),
-                v2 = sortType(r2.data[field]);
 
-            return directionModifier * (v1 > v2 ? 1 : (v1 < v2 ? -1 : 0));
-        };
-    },
+Ext.define('Ext.form.CheckboxManager', {
+    extend: 'Ext.util.MixedCollection',
+    singleton: true,
 
-    
-    setDefaultSort : function(field, dir) {
-        dir = dir ? dir.toUpperCase() : 'ASC';
-        this.sortInfo = {field: field, direction: dir};
-        this.sortToggle[field] = dir;
+    getByName: function(name) {
+        return this.filterBy(function(item) {
+            return item.name == name;
+        });
     },
 
-    
-    sort : function(fieldName, dir) {
-        if (Ext.isArray(arguments[0])) {
-            return this.multiSort.call(this, fieldName, dir);
-        } else {
-            return this.singleSort(fieldName, dir);
-        }
+    getWithValue: function(name, value) {
+        return this.filterBy(function(item) {
+            return item.name == name && item.inputValue == value;
+        });
     },
 
-    
-    singleSort: function(fieldName, dir) {
-        var field = this.fields.get(fieldName);
-        if (!field) return false;
-
-        var name       = field.name,
-            sortInfo   = this.sortInfo || null,
-            sortToggle = this.sortToggle ? this.sortToggle[name] : null;
+    getChecked: function(name) {
+        return this.filterBy(function(item) {
+            return item.name == name && item.checked;
+        });
+    }
+});
 
-        if (!dir) {
-            if (sortInfo && sortInfo.field == name) { 
-                dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
-            } else {
-                dir = field.sortDir;
-            }
-        }
 
-        this.sortToggle[name] = dir;
-        this.sortInfo = {field: name, direction: dir};
-        this.hasMultiSort = false;
+Ext.define('Ext.form.FieldSet', {
+    extend: 'Ext.container.Container',
+    alias: 'widget.fieldset',
+    uses: ['Ext.form.field.Checkbox', 'Ext.panel.Tool', 'Ext.layout.container.Anchor', 'Ext.layout.component.FieldSet'],
 
-        if (this.remoteSort) {
-            if (!this.load(this.lastOptions)) {
-                if (sortToggle) {
-                    this.sortToggle[name] = sortToggle;
-                }
-                if (sortInfo) {
-                    this.sortInfo = sortInfo;
-                }
-            }
-        } else {
-            this.applySort();
-            this.fireEvent('datachanged', this);
-        }
-    },
+    
 
     
-    multiSort: function(sorters, direction) {
-        this.hasMultiSort = true;
-        direction = direction || "ASC";
 
-        
-        if (this.multiSortInfo && direction == this.multiSortInfo.direction) {
-            direction = direction.toggle("ASC", "DESC");
-        }
+    
 
-        
-        this.multiSortInfo = {
-            sorters  : sorters,
-            direction: direction
-        };
-        
-        if (this.remoteSort) {
-            this.singleSort(sorters[0].field, sorters[0].direction);
+    
 
-        } else {
-            this.applySort();
-            this.fireEvent('datachanged', this);
-        }
-    },
+    
+    collapsed: false,
 
     
-    each : function(fn, scope){
-        this.data.each(fn, scope);
-    },
 
     
-    getModifiedRecords : function(){
-        return this.modified;
-    },
+    baseCls: Ext.baseCSSPrefix + 'fieldset',
 
     
-    sum : function(property, start, end){
-        var rs = this.data.items, v = 0;
-        start = start || 0;
-        end = (end || end === 0) ? end : rs.length-1;
+    layout: 'anchor',
 
-        for(var i = start; i <= end; i++){
-            v += (rs[i].data[property] || 0);
-        }
-        return v;
-    },
+    componentLayout: 'fieldset',
 
     
-    createFilterFn : function(property, value, anyMatch, caseSensitive, exactMatch){
-        if(Ext.isEmpty(value, false)){
-            return false;
-        }
-        value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
-        return function(r) {
-            return value.test(r.data[property]);
-        };
+    ariaRole: '',
+
+    renderTpl: ['<div id="{id}-body" class="{baseCls}-body"></div>'],
+
+    maskOnDisable: false,
+
+    getElConfig: function(){
+        return {tag: 'fieldset', id: this.id};
     },
 
-    
-    createMultipleFilterFn: function(filters) {
-        return function(record) {
-            var isMatch = true;
+    initComponent: function() {
+        var me = this,
+            baseCls = me.baseCls;
 
-            for (var i=0, j = filters.length; i < j; i++) {
-                var filter = filters[i],
-                    fn     = filter.fn,
-                    scope  = filter.scope;
+        me.callParent();
 
-                isMatch = isMatch && fn.call(scope, record);
-            }
+        
+        me.initLegend();
 
-            return isMatch;
-        };
+        
+        me.addChildEls('body');
+
+        if (me.collapsed) {
+            me.addCls(baseCls + '-collapsed');
+            me.collapse();
+        }
     },
 
     
-    filter : function(property, value, anyMatch, caseSensitive, exactMatch){
+    onRender: function(container, position) {
+        this.callParent(arguments);
         
-        if (Ext.isObject(property)) {
-            property = [property];
-        }
-
-        if (Ext.isArray(property)) {
-            var filters = [];
+        this.initLegend();
+    },
 
-            
-            for (var i=0, j = property.length; i < j; i++) {
-                var filter = property[i],
-                    func   = filter.fn,
-                    scope  = filter.scope || this;
+    
+    initLegend: function() {
+        var me = this,
+            legendItems,
+            legend = me.legend;
 
-                
-                if (!Ext.isFunction(func)) {
-                    func = this.createFilterFn(filter.property, filter.value, filter.anyMatch, filter.caseSensitive, filter.exactMatch);
-                }
+        
+        if (!legend && (me.title || me.checkboxToggle || me.collapsible)) {
+            legendItems = [];
 
-                filters.push({fn: func, scope: scope});
+            
+            if (me.checkboxToggle) {
+                legendItems.push(me.createCheckboxCmp());
+            }
+            
+            else if (me.collapsible) {
+                legendItems.push(me.createToggleCmp());
             }
 
-            var fn = this.createMultipleFilterFn(filters);
-        } else {
             
-            var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
+            legendItems.push(me.createTitleCmp());
+
+            legend = me.legend = Ext.create('Ext.container.Container', {
+                baseCls: me.baseCls + '-header',
+                ariaRole: '',
+                ownerCt: this,
+                getElConfig: function(){
+                    var result = {
+                        tag: 'legend',
+                        cls: this.baseCls
+                    };
+
+                    
+                    
+                    
+                    
+                    if (!Ext.isGecko3) {
+                        result.children = [{
+                            cls: Ext.baseCSSPrefix + 'clear'
+                        }];
+                    }
+                    return result;
+                },
+                items: legendItems
+            });
         }
 
-        return fn ? this.filterBy(fn) : this.clearFilter();
+        
+        if (legend && !legend.rendered && me.rendered) {
+            me.legend.render(me.el, me.body); 
+        }
     },
 
     
-    filterBy : function(fn, scope){
-        this.snapshot = this.snapshot || this.data;
-        this.data = this.queryBy(fn, scope||this);
-        this.fireEvent('datachanged', this);
+    createTitleCmp: function() {
+        var me = this;
+        me.titleCmp = Ext.create('Ext.Component', {
+            html: me.title,
+            getElConfig: function() {
+                return {
+                    tag: Ext.isGecko3 ? 'span' : 'div',
+                    cls: me.titleCmp.cls,
+                    id: me.titleCmp.id
+                };
+            },
+            cls: me.baseCls + '-header-text'
+        });
+        return me.titleCmp;
     },
 
     
-    clearFilter : function(suppressEvent){
-        if(this.isFiltered()){
-            this.data = this.snapshot;
-            delete this.snapshot;
-            if(suppressEvent !== true){
-                this.fireEvent('datachanged', this);
-            }
-        }
-    },
 
     
-    isFiltered : function(){
-        return !!this.snapshot && this.snapshot != this.data;
+    createCheckboxCmp: function() {
+        var me = this,
+            suffix = '-checkbox';
+
+        me.checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
+            getElConfig: function() {
+                return {
+                    tag: Ext.isGecko3 ? 'span' : 'div',
+                    id: me.checkboxCmp.id,
+                    cls: me.checkboxCmp.cls
+                };
+            },
+            name: me.checkboxName || me.id + suffix,
+            cls: me.baseCls + '-header' + suffix,
+            checked: !me.collapsed,
+            listeners: {
+                change: me.onCheckChange,
+                scope: me
+            }
+        });
+        return me.checkboxCmp;
     },
 
     
-    query : function(property, value, anyMatch, caseSensitive){
-        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
-        return fn ? this.queryBy(fn) : this.data.clone();
-    },
 
     
-    queryBy : function(fn, scope){
-        var data = this.snapshot || this.data;
-        return data.filterBy(fn, scope||this);
+    createToggleCmp: function() {
+        var me = this;
+        me.toggleCmp = Ext.create('Ext.panel.Tool', {
+            getElConfig: function() {
+                return {
+                    tag: Ext.isGecko3 ? 'span' : 'div',
+                    id: me.toggleCmp.id,
+                    cls: me.toggleCmp.cls
+                };
+            },
+            type: 'toggle',
+            handler: me.toggle,
+            scope: me
+        });
+        return me.toggleCmp;
     },
 
     
-    find : function(property, value, start, anyMatch, caseSensitive){
-        var fn = this.createFilterFn(property, value, anyMatch, caseSensitive);
-        return fn ? this.data.findIndexBy(fn, null, start) : -1;
+    setTitle: function(title) {
+        var me = this;
+        me.title = title;
+        me.initLegend();
+        me.titleCmp.update(title);
+        return me;
     },
 
-    
-    findExact: function(property, value, start){
-        return this.data.findIndexBy(function(rec){
-            return rec.get(property) === value;
-        }, this, start);
+    getTargetEl : function() {
+        return this.body || this.frameBody || this.el;
     },
 
-    
-    findBy : function(fn, scope, start){
-        return this.data.findIndexBy(fn, scope, start);
+    getContentTarget: function() {
+        return this.body;
     },
 
     
-    collect : function(dataIndex, allowNull, bypassFilter){
-        var d = (bypassFilter === true && this.snapshot) ?
-                this.snapshot.items : this.data.items;
-        var v, sv, r = [], l = {};
-        for(var i = 0, len = d.length; i < len; i++){
-            v = d[i].data[dataIndex];
-            sv = String(v);
-            if((allowNull || !Ext.isEmpty(v)) && !l[sv]){
-                l[sv] = true;
-                r[r.length] = v;
+    getRefItems: function(deep) {
+        var refItems = this.callParent(arguments),
+            legend = this.legend;
+
+        
+        if (legend) {
+            refItems.unshift(legend);
+            if (deep) {
+                refItems.unshift.apply(refItems, legend.getRefItems(true));
             }
         }
-        return r;
+        return refItems;
     },
 
     
-    afterEdit : function(record){
-        if(this.modified.indexOf(record) == -1){
-            this.modified.push(record);
-        }
-        this.fireEvent('update', this, record, Ext.data.Record.EDIT);
+    expand : function(){
+        return this.setExpanded(true);
     },
 
     
-    afterReject : function(record){
-        this.modified.remove(record);
-        this.fireEvent('update', this, record, Ext.data.Record.REJECT);
+    collapse : function() {
+        return this.setExpanded(false);
     },
 
     
-    afterCommit : function(record){
-        this.modified.remove(record);
-        this.fireEvent('update', this, record, Ext.data.Record.COMMIT);
-    },
+    setExpanded: function(expanded) {
+        var me = this,
+            checkboxCmp = me.checkboxCmp;
 
-    
-    commitChanges : function(){
-        var m = this.modified.slice(0);
-        this.modified = [];
-        for(var i = 0, len = m.length; i < len; i++){
-            m[i].commit();
+        expanded = !!expanded;
+
+        if (checkboxCmp) {
+            checkboxCmp.setValue(expanded);
         }
-    },
 
-    
-    rejectChanges : function(){
-        var m = this.modified.slice(0);
-        this.modified = [];
-        for(var i = 0, len = m.length; i < len; i++){
-            m[i].reject();
+        if (expanded) {
+            me.removeCls(me.baseCls + '-collapsed');
+        } else {
+            me.addCls(me.baseCls + '-collapsed');
         }
-        var m = this.removed.slice(0).reverse();
-        this.removed = [];
-        for(var i = 0, len = m.length; i < len; i++){
-            this.insert(m[i].lastIndex||0, m[i]);
-            m[i].reject();
+        me.collapsed = !expanded;
+        if (expanded) {
+            
+            me.getComponentLayout().childrenChanged = true;
         }
+        me.doComponentLayout();
+        return me;
     },
 
     
-    onMetaChange : function(meta){
-        this.recordType = this.reader.recordType;
-        this.fields = this.recordType.prototype.fields;
-        delete this.snapshot;
-        if(this.reader.meta.sortInfo){
-            this.sortInfo = this.reader.meta.sortInfo;
-        }else if(this.sortInfo  && !this.fields.get(this.sortInfo.field)){
-            delete this.sortInfo;
-        }
-        if(this.writer){
-            this.writer.meta = this.reader.meta;
-        }
-        this.modified = [];
-        this.fireEvent('metachange', this, this.reader.meta);
+    toggle: function() {
+        this.setExpanded(!!this.collapsed);
     },
 
     
-    findInsertIndex : function(record){
-        this.suspendEvents();
-        var data = this.data.clone();
-        this.data.add(record);
-        this.applySort();
-        var index = this.data.indexOf(record);
-        this.data = data;
-        this.resumeEvents();
-        return index;
+    onCheckChange: function(cmp, checked) {
+        this.setExpanded(checked);
     },
 
-    
-    setBaseParam : function (name, value){
-        this.baseParams = this.baseParams || {};
-        this.baseParams[name] = value;
+    beforeDestroy : function() {
+        var legend = this.legend;
+        if (legend) {
+            legend.destroy();
+        }
+        this.callParent();
     }
 });
 
-Ext.reg('store', Ext.data.Store);
 
+Ext.define('Ext.form.Label', {
+    extend:'Ext.Component',
+    alias: 'widget.label',
+    requires: ['Ext.util.Format'],
 
-Ext.data.Store.Error = Ext.extend(Ext.Error, {
-    name: 'Ext.data.Store'
-});
-Ext.apply(Ext.data.Store.Error.prototype, {
-    lang: {
-        'writer-undefined' : 'Attempted to execute a write-action without a DataWriter installed.'
-    }
-});
+    
+    
+    
+    
+    maskOnDisable: false,
+    getElConfig: function(){
+        var me = this;
+        return {
+            tag: 'label', 
+            id: me.id, 
+            htmlFor: me.forId || '',
+            html: me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '') 
+        };
+    },
 
-Ext.data.Field = Ext.extend(Object, {
     
-    constructor : function(config){
-        if(Ext.isString(config)){
-            config = {name: config};
-        }
-        Ext.apply(this, config);
+    setText : function(text, encode){
+        var me = this;
         
-        var types = Ext.data.Types,
-            st = this.sortType,
-            t;
-
-        if(this.type){
-            if(Ext.isString(this.type)){
-                this.type = Ext.data.Types[this.type.toUpperCase()] || types.AUTO;
-            }
-        }else{
-            this.type = types.AUTO;
+        encode = encode !== false;
+        if(encode) {
+            me.text = text;
+            delete me.html;
+        } else {
+            me.html = text;
+            delete me.text;
         }
-
         
-        if(Ext.isString(st)){
-            this.sortType = Ext.data.SortTypes[st];
-        }else if(Ext.isEmpty(st)){
-            this.sortType = this.type.sortType;
+        if(me.rendered){
+            me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text;
         }
+        return this;
+    }
+});
 
-        if(!this.convert){
-            this.convert = this.type.convert;
-        }
+
+
+Ext.define('Ext.form.Panel', {
+    extend:'Ext.panel.Panel',
+    mixins: {
+        fieldAncestor: 'Ext.form.FieldAncestor'
     },
-    
-    
-    
-    
-    
-    dateFormat: null,
-    
-    defaultValue: "",
-    
-    mapping: null,
-    
-    sortType : null,
-    
-    sortDir : "ASC",
-    
-    allowBlank : true
-});
+    alias: 'widget.form',
+    alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
+    requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'],
 
-Ext.data.DataReader = function(meta, recordType){
-    
-    this.meta = meta;
     
-    this.recordType = Ext.isArray(recordType) ?
-        Ext.data.Record.create(recordType) : recordType;
 
     
-    if (this.recordType){
-        this.buildExtractors();
-    }
-};
 
-Ext.data.DataReader.prototype = {
-    
-    
-    getTotal: Ext.emptyFn,
-    
-    getRoot: Ext.emptyFn,
-    
-    getMessage: Ext.emptyFn,
-    
-    getSuccess: Ext.emptyFn,
-    
-    getId: Ext.emptyFn,
     
-    buildExtractors : Ext.emptyFn,
-    
-    extractValues : Ext.emptyFn,
+    layout: 'anchor',
 
-    
-    realize: function(rs, data){
-        if (Ext.isArray(rs)) {
-            for (var i = rs.length - 1; i >= 0; i--) {
-                
-                if (Ext.isArray(data)) {
-                    this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());
-                }
-                else {
-                    
-                    
-                    this.realize(rs.splice(i,1).shift(), data);
-                }
-            }
-        }
-        else {
-            
-            if (Ext.isArray(data) && data.length == 1) {
-                data = data.shift();
-            }
-            if (!this.isData(data)) {
-                
-                
-                throw new Ext.data.DataReader.Error('realize', rs);
-            }
-            rs.phantom = false; 
-            rs._phid = rs.id;  
-            rs.id = this.getId(data);
-            rs.data = data;
+    ariaRole: 'form',
 
-            rs.commit();
-        }
-    },
+    initComponent: function() {
+        var me = this;
 
-    
-    update : function(rs, data) {
-        if (Ext.isArray(rs)) {
-            for (var i=rs.length-1; i >= 0; i--) {
-                if (Ext.isArray(data)) {
-                    this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());
-                }
-                else {
-                    
-                    
-                    this.update(rs.splice(i,1).shift(), data);
-                }
-            }
-        }
-        else {
-            
-            if (Ext.isArray(data) && data.length == 1) {
-                data = data.shift();
-            }
-            if (this.isData(data)) {
-                rs.data = Ext.apply(rs.data, data);
-            }
-            rs.commit();
+        if (me.frame) {
+            me.border = false;
         }
-    },
 
-    
-    extractData : function(root, returnRecords) {
-        
-        var rawName = (this instanceof Ext.data.JsonReader) ? 'json' : 'node';
+        me.initFieldAncestor();
+        me.callParent();
 
-        var rs = [];
+        me.relayEvents(me.form, [
+            'beforeaction',
+            'actionfailed',
+            'actioncomplete',
+            'validitychange',
+            'dirtychange'
+        ]);
 
         
-        
-        if (this.isData(root) && !(this instanceof Ext.data.XmlReader)) {
-            root = [root];
+        if (me.pollForChanges) {
+            me.startPolling(me.pollInterval || 500);
         }
-        var f       = this.recordType.prototype.fields,
-            fi      = f.items,
-            fl      = f.length,
-            rs      = [];
-        if (returnRecords === true) {
-            var Record = this.recordType;
-            for (var i = 0; i < root.length; i++) {
-                var n = root[i];
-                var record = new Record(this.extractValues(n, fi, fl), this.getId(n));
-                record[rawName] = n;    
-                rs.push(record);
-            }
-        }
-        else {
-            for (var i = 0; i < root.length; i++) {
-                var data = this.extractValues(root[i], fi, fl);
-                data[this.meta.idProperty] = this.getId(root[i]);
-                rs.push(data);
-            }
-        }
-        return rs;
+    },
+
+    initItems: function() {
+        
+        var me = this;
+
+        me.form = me.createForm();
+        me.callParent();
+        me.form.initialize();
     },
 
     
-    isData : function(data) {
-        return (data && Ext.isObject(data) && !Ext.isEmpty(this.getId(data))) ? true : false;
+    createForm: function() {
+        return Ext.create('Ext.form.Basic', this, Ext.applyIf({listeners: {}}, this.initialConfig));
     },
 
     
-    onMetaChange : function(meta){
-        delete this.ef;
-        this.meta = meta;
-        this.recordType = Ext.data.Record.create(meta.fields);
-        this.buildExtractors();
-    }
-};
+    getForm: function() {
+        return this.form;
+    },
 
+    
+    loadRecord: function(record) {
+        return this.getForm().loadRecord(record);
+    },
 
-Ext.data.DataReader.Error = Ext.extend(Ext.Error, {
-    constructor : function(message, arg) {
-        this.arg = arg;
-        Ext.Error.call(this, message);
+    
+    getRecord: function() {
+        return this.getForm().getRecord();
     },
-    name: 'Ext.data.DataReader'
-});
-Ext.apply(Ext.data.DataReader.Error.prototype, {
-    lang : {
-        'update': "#update received invalid data from server.  Please see docs for DataReader#update and review your DataReader configuration.",
-        'realize': "#realize was called with invalid remote-data.  Please see the docs for DataReader#realize and review your DataReader configuration.",
-        'invalid-response': "#readResponse received an invalid response from the server."
-    }
-});
 
-Ext.data.DataWriter = function(config){
-    Ext.apply(this, config);
-};
-Ext.data.DataWriter.prototype = {
+    
+    getValues: function() {
+        return this.getForm().getValues();
+    },
 
-    
-    writeAllFields : false,
-    
-    listful : false,    
+    beforeDestroy: function() {
+        this.stopPolling();
+        this.form.destroy();
+        this.callParent();
+    },
 
     
-    apply : function(params, baseParams, action, rs) {
-        var data    = [],
-        renderer    = action + 'Record';
-        
-        if (Ext.isArray(rs)) {
-            Ext.each(rs, function(rec){
-                data.push(this[renderer](rec));
-            }, this);
-        }
-        else if (rs instanceof Ext.data.Record) {
-            data = this[renderer](rs);
-        }
-        this.render(params, baseParams, data);
+    load: function(options) {
+        this.form.load(options);
     },
 
     
-    render : Ext.emptyFn,
+    submit: function(options) {
+        this.form.submit(options);
+    },
 
     
-    updateRecord : Ext.emptyFn,
+    disable: function(silent) {
+        this.callParent(arguments);
+        this.form.getFields().each(function(field) {
+            field.disable();
+        });
+    },
 
     
-    createRecord : Ext.emptyFn,
+    enable: function(silent) {
+        this.callParent(arguments);
+        this.form.getFields().each(function(field) {
+            field.enable();
+        });
+    },
 
     
-    destroyRecord : Ext.emptyFn,
+    startPolling: function(interval) {
+        this.stopPolling();
+        var task = Ext.create('Ext.util.TaskRunner', interval);
+        task.start({
+            interval: 0,
+            run: this.checkChange,
+            scope: this
+        });
+        this.pollTask = task;
+    },
 
     
-    toHash : function(rec, config) {
-        var map = rec.fields.map,
-            data = {},
-            raw = (this.writeAllFields === false && rec.phantom === false) ? rec.getChanges() : rec.data,
-            m;
-        Ext.iterate(raw, function(prop, value){
-            if((m = map[prop])){
-                data[m.mapping ? m.mapping : m.name] = value;
-            }
-        });
-        
-        
-        
-        if (rec.phantom) {
-            if (rec.fields.containsKey(this.meta.idProperty) && Ext.isEmpty(rec.data[this.meta.idProperty])) {
-                delete data[this.meta.idProperty];
-            }
-        } else {
-            data[this.meta.idProperty] = rec.id
+    stopPolling: function() {
+        var task = this.pollTask;
+        if (task) {
+            task.stopAll();
+            delete this.pollTask;
         }
-        return data;
     },
 
     
-    toArray : function(data) {
-        var fields = [];
-        Ext.iterate(data, function(k, v) {fields.push({name: k, value: v});},this);
-        return fields;
+    checkChange: function() {
+        this.form.getFields().each(function(field) {
+            field.checkChange();
+        });
     }
-};
-Ext.data.DataProxy = function(conn){
-    
-    
-    conn = conn || {};
+});
+
+
+Ext.define('Ext.form.RadioGroup', {
+    extend: 'Ext.form.CheckboxGroup',
+    alias: 'widget.radiogroup',
 
     
     
+    allowBlank : true,
     
-
-    this.api     = conn.api;
-    this.url     = conn.url;
-    this.restful = conn.restful;
-    this.listeners = conn.listeners;
+    blankText : 'You must select one item in this group',
 
     
-    this.prettyUrls = conn.prettyUrls;
+    defaultType : 'radiofield',
 
     
+    groupCls : Ext.baseCSSPrefix + 'form-radio-group',
 
-    this.addEvents(
-        
-        'exception',
-        
-        'beforeload',
-        
-        'load',
-        
-        'loadexception',
-        
-        'beforewrite',
-        
-        'write'
-    );
-    Ext.data.DataProxy.superclass.constructor.call(this);
+    getBoxes: function() {
+        return this.query('[isRadio]');
+    },
 
     
-    try {
-        Ext.data.Api.prepare(this);
-    } catch (e) {
-        if (e instanceof Ext.data.Api.Error) {
-            e.toConsole();
+    setValue: function(value) {
+        var me = this;
+        if (Ext.isObject(value)) {
+            Ext.Object.each(value, function(name, cbValue) {
+                var radios = Ext.form.RadioManager.getWithValue(name, cbValue);
+                radios.each(function(cb) {
+                    cb.setValue(true);
+                });
+            });
         }
+        return me;
     }
-    
-    Ext.data.DataProxy.relayEvents(this, ['beforewrite', 'write', 'exception']);
-};
+});
 
-Ext.extend(Ext.data.DataProxy, Ext.util.Observable, {
-    
-    restful: false,
 
-    
-    setApi : function() {
-        if (arguments.length == 1) {
-            var valid = Ext.data.Api.isValid(arguments[0]);
-            if (valid === true) {
-                this.api = arguments[0];
-            }
-            else {
-                throw new Ext.data.Api.Error('invalid', valid);
-            }
-        }
-        else if (arguments.length == 2) {
-            if (!Ext.data.Api.isAction(arguments[0])) {
-                throw new Ext.data.Api.Error('invalid', arguments[0]);
-            }
-            this.api[arguments[0]] = arguments[1];
-        }
-        Ext.data.Api.prepare(this);
-    },
+Ext.define('Ext.form.RadioManager', {
+    extend: 'Ext.util.MixedCollection',
+    singleton: true,
 
-    
-    isApiAction : function(action) {
-        return (this.api[action]) ? true : false;
+    getByName: function(name) {
+        return this.filterBy(function(item) {
+            return item.name == name;
+        });
     },
 
-    
-    request : function(action, rs, params, reader, callback, scope, options) {
-        if (!this.api[action] && !this.load) {
-            throw new Ext.data.DataProxy.Error('action-undefined', action);
-        }
-        params = params || {};
-        if ((action === Ext.data.Api.actions.read) ? this.fireEvent("beforeload", this, params) : this.fireEvent("beforewrite", this, action, rs, params) !== false) {
-            this.doRequest.apply(this, arguments);
-        }
-        else {
-            callback.call(scope || this, null, options, false);
-        }
+    getWithValue: function(name, value) {
+        return this.filterBy(function(item) {
+            return item.name == name && item.inputValue == value;
+        });
     },
 
+    getChecked: function(name) {
+        return this.findBy(function(item) {
+            return item.name == name && item.checked;
+        });
+    }
+});
+
 
-    
-    load : null,
+Ext.define('Ext.form.action.DirectLoad', {
+    extend:'Ext.form.action.Load',
+    requires: ['Ext.direct.Manager'],
+    alternateClassName: 'Ext.form.Action.DirectLoad',
+    alias: 'formaction.directload',
 
-    
-    doRequest : function(action, rs, params, reader, callback, scope, options) {
-        
-        
-        
-        this.load(params, reader, callback, scope, options);
+    type: 'directload',
+
+    run: function() {
+        this.form.api.load.apply(window, this.getArgs());
     },
 
     
-    onRead : Ext.emptyFn,
-    
-    onWrite : Ext.emptyFn,
-    
-    buildUrl : function(action, record) {
-        record = record || null;
+    getArgs: function() {
+        var me = this,
+            args = [],
+            form = me.form,
+            paramOrder = form.paramOrder,
+            params = me.getParams(),
+            i, len;
 
         
-        
-        
-        var url = (this.conn && this.conn.url) ? this.conn.url : (this.api[action]) ? this.api[action].url : this.url;
-        if (!url) {
-            throw new Ext.data.Api.Error('invalid-url', action);
+        if (paramOrder) {
+            for (i = 0, len = paramOrder.length; i < len; i++) {
+                args.push(params[paramOrder[i]]);
+            }
         }
-
         
-        
-        
-        
-        
-        
-        var provides = null;
-        var m = url.match(/(.*)(\.json|\.xml|\.html)$/);
-        if (m) {
-            provides = m[2];    
-            url      = m[1];    
+        else if (form.paramsAsHash) {
+            args.push(params);
         }
+
         
-        if ((this.restful === true || this.prettyUrls === true) && record instanceof Ext.data.Record && !record.phantom) {
-            url += '/' + record.id;
-        }
-        return (provides === null) ? url : url + provides;
+        args.push(me.onSuccess, me);
+
+        return args;
     },
 
     
-    destroy: function(){
-        this.purgeListeners();
+    
+    
+    processResponse: function(result) {
+        return (this.result = result);
+    },
+
+    onSuccess: function(result, trans) {
+        if (trans.type == Ext.direct.Manager.self.exceptions.SERVER) {
+            result = {};
+        }
+        this.callParent([result]);
     }
 });
 
 
 
-Ext.apply(Ext.data.DataProxy, Ext.util.Observable.prototype);
-Ext.util.Observable.call(Ext.data.DataProxy);
 
+Ext.define('Ext.form.action.DirectSubmit', {
+    extend:'Ext.form.action.Submit',
+    requires: ['Ext.direct.Manager'],
+    alternateClassName: 'Ext.form.Action.DirectSubmit',
+    alias: 'formaction.directsubmit',
+
+    type: 'directsubmit',
+
+    doSubmit: function() {
+        var me = this,
+            callback = Ext.Function.bind(me.onSuccess, me),
+            formEl = me.buildForm();
+        me.form.api.submit(formEl, callback, me);
+        Ext.removeNode(formEl);
+    },
 
-Ext.data.DataProxy.Error = Ext.extend(Ext.Error, {
-    constructor : function(message, arg) {
-        this.arg = arg;
-        Ext.Error.call(this, message);
+    
+    
+    
+    processResponse: function(result) {
+        return (this.result = result);
     },
-    name: 'Ext.data.DataProxy'
-});
-Ext.apply(Ext.data.DataProxy.Error.prototype, {
-    lang: {
-        'action-undefined': "DataProxy attempted to execute an API-action but found an undefined url / function.  Please review your Proxy url/api-configuration.",
-        'api-invalid': 'Recieved an invalid API-configuration.  Please ensure your proxy API-configuration contains only the actions from Ext.data.Api.actions.'
+
+    onSuccess: function(response, trans) {
+        if (trans.type === Ext.direct.Manager.self.exceptions.SERVER) {
+            response = {};
+        }
+        this.callParent([response]);
     }
 });
 
 
+Ext.define('Ext.form.action.StandardSubmit', {
+    extend:'Ext.form.action.Submit',
+    alias: 'formaction.standardsubmit',
 
-Ext.data.Request = function(params) {
-    Ext.apply(this, params);
-};
-Ext.data.Request.prototype = {
-    
-    action : undefined,
-    
-    rs : undefined,
-    
-    params: undefined,
-    
-    callback : Ext.emptyFn,
-    
-    scope : undefined,
     
-    reader : undefined
-};
 
-Ext.data.Response = function(params) {
-    Ext.apply(this, params);
-};
-Ext.data.Response.prototype = {
-    
-    action: undefined,
-    
-    success : undefined,
-    
-    message : undefined,
-    
-    data: undefined,
-    
-    raw: undefined,
     
-    records: undefined
-};
+    doSubmit: function() {
+        var form = this.buildForm();
+        form.submit();
+        Ext.removeNode(form);
+    }
 
-Ext.data.ScriptTagProxy = function(config){
-    Ext.apply(this, config);
+});
 
-    Ext.data.ScriptTagProxy.superclass.constructor.call(this, config);
 
-    this.head = document.getElementsByTagName("head")[0];
+Ext.define('Ext.form.field.Checkbox', {
+    extend: 'Ext.form.field.Base',
+    alias: ['widget.checkboxfield', 'widget.checkbox'],
+    alternateClassName: 'Ext.form.Checkbox',
+    requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
 
     
-};
+    fieldSubTpl: [
+        '<tpl if="boxLabel && boxLabelAlign == \'before\'">',
+            '<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
+        '</tpl>',
+        
+        
+        
+        '<input type="button" id="{id}" ',
+            '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+            'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
+        '<tpl if="boxLabel && boxLabelAlign == \'after\'">',
+            '<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
+        '</tpl>',
+        {
+            disableFormats: true,
+            compiled: true
+        }
+    ],
 
-Ext.data.ScriptTagProxy.TRANS_ID = 1000;
+    isCheckbox: true,
 
-Ext.extend(Ext.data.ScriptTagProxy, Ext.data.DataProxy, {
-    
-    
-    timeout : 30000,
     
-    callbackParam : "callback",
+    focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
+
     
-    nocache : true,
 
     
-    doRequest : function(action, rs, params, reader, callback, scope, arg) {
-        var p = Ext.urlEncode(Ext.apply(params, this.extraParams));
+    fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
 
-        var url = this.buildUrl(action, rs);
-        if (!url) {
-            throw new Ext.data.Api.Error('invalid-url', url);
-        }
-        url = Ext.urlAppend(url, p);
+    
+    checked: false,
 
-        if(this.nocache){
-            url = Ext.urlAppend(url, '_dc=' + (new Date().getTime()));
-        }
-        var transId = ++Ext.data.ScriptTagProxy.TRANS_ID;
-        var trans = {
-            id : transId,
-            action: action,
-            cb : "stcCallback"+transId,
-            scriptId : "stcScript"+transId,
-            params : params,
-            arg : arg,
-            url : url,
-            callback : callback,
-            scope : scope,
-            reader : reader
-        };
-        window[trans.cb] = this.createCallback(action, rs, trans);
-        url += String.format("&{0}={1}", this.callbackParam, trans.cb);
-        if(this.autoAbort !== false){
-            this.abort();
-        }
+    
+    checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
 
-        trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
+    
 
-        var script = document.createElement("script");
-        script.setAttribute("src", url);
-        script.setAttribute("type", "text/javascript");
-        script.setAttribute("id", trans.scriptId);
-        this.head.appendChild(script);
+    
+    boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
 
-        this.trans = trans;
-    },
+    
+    boxLabelAlign: 'after',
 
     
-    createCallback : function(action, rs, trans) {
-        var self = this;
-        return function(res) {
-            self.trans = false;
-            self.destroyTrans(trans, true);
-            if (action === Ext.data.Api.actions.read) {
-                self.onRead.call(self, action, trans, res);
-            } else {
-                self.onWrite.call(self, action, trans, res, rs);
-            }
-        };
-    },
+    inputValue: 'on',
+
     
-    onRead : function(action, trans, res) {
-        var result;
-        try {
-            result = trans.reader.readRecords(res);
-        }catch(e){
-            
-            this.fireEvent("loadexception", this, trans, res, e);
 
-            this.fireEvent('exception', this, 'response', action, trans, res, e);
-            trans.callback.call(trans.scope||window, null, trans.arg, false);
-            return;
-        }
-        if (result.success === false) {
-            
-            this.fireEvent('loadexception', this, trans, res);
+    
 
-            this.fireEvent('exception', this, 'remote', action, trans, res, null);
-        } else {
-            this.fireEvent("load", this, res, trans.arg);
-        }
-        trans.callback.call(trans.scope||window, result, trans.arg, result.success);
-    },
     
-    onWrite : function(action, trans, response, rs) {
-        var reader = trans.reader;
-        try {
-            
-            var res = reader.readResponse(action, response);
-        } catch (e) {
-            this.fireEvent('exception', this, 'response', action, trans, res, e);
-            trans.callback.call(trans.scope||window, null, res, false);
-            return;
-        }
-        if(!res.success === true){
-            this.fireEvent('exception', this, 'remote', action, trans, res, rs);
-            trans.callback.call(trans.scope||window, null, res, false);
-            return;
-        }
-        this.fireEvent("write", this, action, res.data, res, rs, trans.arg );
-        trans.callback.call(trans.scope||window, res.data, res, true);
-    },
 
     
-    isLoading : function(){
-        return this.trans ? true : false;
-    },
+    checkChangeEvents: [],
+    inputType: 'checkbox',
+    ariaRole: 'checkbox',
 
     
-    abort : function(){
-        if(this.isLoading()){
-            this.destroyTrans(this.trans);
-        }
+    onRe: /^on$/i,
+
+    initComponent: function(){
+        this.callParent(arguments);
+        this.getManager().add(this);
     },
 
-    
-    destroyTrans : function(trans, isLoaded){
-        this.head.removeChild(document.getElementById(trans.scriptId));
-        clearTimeout(trans.timeoutId);
-        if(isLoaded){
-            window[trans.cb] = undefined;
-            try{
-                delete window[trans.cb];
-            }catch(e){}
-        }else{
-            
-            window[trans.cb] = function(){
-                window[trans.cb] = undefined;
-                try{
-                    delete window[trans.cb];
-                }catch(e){}
-            };
-        }
+    initValue: function() {
+        var me = this,
+            checked = !!me.checked;
+
+        
+        me.originalValue = me.lastValue = checked;
+
+        
+        me.setValue(checked);
     },
 
     
-    handleFailure : function(trans){
-        this.trans = false;
-        this.destroyTrans(trans, false);
-        if (trans.action === Ext.data.Api.actions.read) {
-            
-            this.fireEvent("loadexception", this, null, trans.arg);
-        }
+    onRender : function(ct, position) {
+        var me = this;
+
+        
+        me.addChildEls('boxLabelEl');
 
-        this.fireEvent('exception', this, 'response', trans.action, {
-            response: null,
-            options: trans.arg
+        Ext.applyIf(me.subTplData, {
+            boxLabel: me.boxLabel,
+            boxLabelCls: me.boxLabelCls,
+            boxLabelAlign: me.boxLabelAlign
         });
-        trans.callback.call(trans.scope||window, null, trans.arg, false);
+
+        me.callParent(arguments);
     },
 
-    
-    destroy: function(){
-        this.abort();
-        Ext.data.ScriptTagProxy.superclass.destroy.call(this);
-    }
-});
-Ext.data.HttpProxy = function(conn){
-    Ext.data.HttpProxy.superclass.constructor.call(this, conn);
+    initEvents: function() {
+        var me = this;
+        me.callParent();
+        me.mon(me.inputEl, 'click', me.onBoxClick, me);
+    },
 
     
-    this.conn = conn;
+    onBoxClick: function(e) {
+        var me = this;
+        if (!me.disabled && !me.readOnly) {
+            this.setValue(!this.checked);
+        }
+    },
 
     
-    
-    
-    
-    this.conn.url = null;
-
-    this.useAjax = !conn || !conn.events;
+    getRawValue: function() {
+        return this.checked;
+    },
 
     
-    var actions = Ext.data.Api.actions;
-    this.activeRequest = {};
-    for (var verb in actions) {
-        this.activeRequest[actions[verb]] = undefined;
-    }
-};
+    getValue: function() {
+        return this.checked;
+    },
 
-Ext.extend(Ext.data.HttpProxy, Ext.data.DataProxy, {
     
-    getConnection : function() {
-        return this.useAjax ? Ext.Ajax : this.conn;
+    getSubmitValue: function() {
+        var unchecked = this.uncheckedValue,
+            uncheckedVal = Ext.isDefined(unchecked) ? unchecked : null;
+        return this.checked ? this.inputValue : uncheckedVal;
     },
 
     
-    setUrl : function(url, makePermanent) {
-        this.conn.url = url;
-        if (makePermanent === true) {
-            this.url = url;
-            this.api = null;
-            Ext.data.Api.prepare(this);
+    setRawValue: function(value) {
+        var me = this,
+            inputEl = me.inputEl,
+            inputValue = me.inputValue,
+            checked = (value === true || value === 'true' || value === '1' || value === 1 ||
+                (((Ext.isString(value) || Ext.isNumber(value)) && inputValue) ? value == inputValue : me.onRe.test(value)));
+
+        if (inputEl) {
+            inputEl.dom.setAttribute('aria-checked', checked);
+            me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
         }
+
+        me.checked = me.rawValue = checked;
+        return checked;
     },
 
     
-    doRequest : function(action, rs, params, reader, cb, scope, arg) {
-        var  o = {
-            method: (this.api[action]) ? this.api[action]['method'] : undefined,
-            request: {
-                callback : cb,
-                scope : scope,
-                arg : arg
-            },
-            reader: reader,
-            callback : this.createCallback(action, rs),
-            scope: this
-        };
+    setValue: function(checked) {
+        var me = this;
 
         
         
-        if (params.jsonData) {
-            o.jsonData = params.jsonData;
-        } else if (params.xmlData) {
-            o.xmlData = params.xmlData;
-        } else {
-            o.params = params || {};
-        }
         
         
-        
-        this.conn.url = this.buildUrl(action, rs);
-
-        if(this.useAjax){
+        if (Ext.isArray(checked)) {
+            me.getManager().getByName(me.name).each(function(cb) {
+                cb.setValue(Ext.Array.contains(checked, cb.inputValue));
+            });
+        } else {
+            me.callParent(arguments);
+        }
 
-            Ext.applyIf(o, this.conn);
+        return me;
+    },
 
-            
-            if (this.activeRequest[action]) {
-                
-                
-                
-                
-                
-            }
-            this.activeRequest[action] = Ext.Ajax.request(o);
-        }else{
-            this.conn.request(o);
-        }
+    
+    valueToRaw: function(value) {
         
-        this.conn.url = null;
+        return value;
     },
 
     
-    createCallback : function(action, rs) {
-        return function(o, success, response) {
-            this.activeRequest[action] = undefined;
-            if (!success) {
-                if (action === Ext.data.Api.actions.read) {
-                    
-                    
-                    this.fireEvent('loadexception', this, o, response);
-                }
-                this.fireEvent('exception', this, 'response', action, o, response);
-                o.request.callback.call(o.request.scope, null, o.request.arg, false);
-                return;
-            }
-            if (action === Ext.data.Api.actions.read) {
-                this.onRead(action, o, response);
-            } else {
-                this.onWrite(action, o, response, rs);
-            }
-        };
+    onChange: function(newVal, oldVal) {
+        var me = this,
+            handler = me.handler;
+        if (handler) {
+            handler.call(me.scope || me, me, newVal);
+        }
+        me.callParent(arguments);
     },
 
     
-    onRead : function(action, o, response) {
-        var result;
-        try {
-            result = o.reader.read(response);
-        }catch(e){
-            
-            
-            this.fireEvent('loadexception', this, o, response, e);
+    beforeDestroy: function(){
+        this.callParent();
+        this.getManager().removeAtKey(this.id);
+    },
 
-            this.fireEvent('exception', this, 'response', action, o, response, e);
-            o.request.callback.call(o.request.scope, null, o.request.arg, false);
-            return;
-        }
-        if (result.success === false) {
-            
-            
-            this.fireEvent('loadexception', this, o, response);
+    
+    getManager: function() {
+        return Ext.form.CheckboxManager;
+    },
 
+    onEnable: function() {
+        var me = this,
+            inputEl = me.inputEl;
+        me.callParent();
+        if (inputEl) {
             
-            var res = o.reader.readResponse(action, response);
-            this.fireEvent('exception', this, 'remote', action, o, res, null);
-        }
-        else {
-            this.fireEvent('load', this, o, o.request.arg);
+            inputEl.dom.disabled = me.readOnly;
         }
-        
-        
-        
-        o.request.callback.call(o.request.scope, result, o.request.arg, result.success);
     },
-    
-    onWrite : function(action, o, response, rs) {
-        var reader = o.reader;
-        var res;
-        try {
-            res = reader.readResponse(action, response);
-        } catch (e) {
-            this.fireEvent('exception', this, 'response', action, o, response, e);
-            o.request.callback.call(o.request.scope, null, o.request.arg, false);
-            return;
-        }
-        if (res.success === true) {
-            this.fireEvent('write', this, action, res.data, res, rs, o.request.arg);
-        } else {
-            this.fireEvent('exception', this, 'remote', action, o, res, rs);
+
+    setReadOnly: function(readOnly) {
+        var me = this,
+            inputEl = me.inputEl;
+        if (inputEl) {
+            
+            inputEl.dom.disabled = readOnly || me.disabled;
         }
-        
-        
-        
-        o.request.callback.call(o.request.scope, res.data, res, res.success);
+        me.readOnly = readOnly;
     },
 
     
-    destroy: function(){
-        if(!this.useAjax){
-            this.conn.abort();
-        }else if(this.activeRequest){
-            var actions = Ext.data.Api.actions;
-            for (var verb in actions) {
-                if(this.activeRequest[actions[verb]]){
-                    Ext.Ajax.abort(this.activeRequest[actions[verb]]);
-                }
-            }
-        }
-        Ext.data.HttpProxy.superclass.destroy.call(this);
+    
+    getBodyNaturalWidth: function() {
+        var me = this,
+            bodyEl = me.bodyEl,
+            ws = 'white-space',
+            width;
+        bodyEl.setStyle(ws, 'nowrap');
+        width = bodyEl.getWidth();
+        bodyEl.setStyle(ws, '');
+        return width;
     }
+
 });
-Ext.data.MemoryProxy = function(data){
+
+
+
+Ext.define('Ext.layout.component.field.Trigger', {
+
     
-    var api = {};
-    api[Ext.data.Api.actions.read] = true;
-    Ext.data.MemoryProxy.superclass.constructor.call(this, {
-        api: api
-    });
-    this.data = data;
-};
 
-Ext.extend(Ext.data.MemoryProxy, Ext.data.DataProxy, {
+    alias: ['layout.triggerfield'],
+
+    extend: 'Ext.layout.component.field.Field',
+
     
 
-       
-    doRequest : function(action, rs, params, reader, callback, scope, arg) {
+    type: 'triggerfield',
+
+    sizeBodyContents: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            inputEl = owner.inputEl,
+            triggerWrap = owner.triggerWrap,
+            triggerWidth = owner.getTriggerWidth();
+
         
-        params = params || {};
-        var result;
-        try {
-            result = reader.readRecords(this.data);
-        }catch(e){
+        
+        if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
             
-            this.fireEvent("loadexception", this, null, arg, e);
-
-            this.fireEvent('exception', this, 'response', action, arg, null, e);
-            callback.call(scope, null, arg, false);
-            return;
+            
+            me.setElementSize(inputEl, Ext.isNumber(width) ? width - triggerWidth : width);
+    
+            
+            triggerWrap.setWidth(triggerWidth);
         }
-        callback.call(scope, result, arg, true);
     }
 });
-Ext.data.Types = new function(){
-    var st = Ext.data.SortTypes;
-    Ext.apply(this, {
-        
-        stripRe: /[\$,%]/g,
-        
-        
-        AUTO: {
-            convert: function(v){ return v; },
-            sortType: st.none,
-            type: 'auto'
-        },
 
-        
-        STRING: {
-            convert: function(v){ return (v === undefined || v === null) ? '' : String(v); },
-            sortType: st.asUCString,
-            type: 'string'
-        },
+Ext.define('Ext.view.View', {
+    extend: 'Ext.view.AbstractView',
+    alternateClassName: 'Ext.DataView',
+    alias: 'widget.dataview',
 
-        
-        INT: {
-            convert: function(v){
-                return v !== undefined && v !== null && v !== '' ?
-                    parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : 0;
-            },
-            sortType: st.none,
-            type: 'int'
-        },
-        
-        
-        FLOAT: {
-            convert: function(v){
-                return v !== undefined && v !== null && v !== '' ?
-                    parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : 0;
-            },
-            sortType: st.none,
-            type: 'float'
-        },
-        
-        
-        BOOL: {
-            convert: function(v){ return v === true || v === 'true' || v == 1; },
-            sortType: st.none,
-            type: 'bool'
-        },
-        
-        
-        DATE: {
-            convert: function(v){
-                var df = this.dateFormat;
-                if(!v){
-                    return null;
-                }
-                if(Ext.isDate(v)){
-                    return v;
-                }
-                if(df){
-                    if(df == 'timestamp'){
-                        return new Date(v*1000);
-                    }
-                    if(df == 'time'){
-                        return new Date(parseInt(v, 10));
-                    }
-                    return Date.parseDate(v, df);
-                }
-                var parsed = Date.parse(v);
-                return parsed ? new Date(parsed) : null;
-            },
-            sortType: st.asDate,
-            type: 'date'
+    inheritableStatics: {
+        EventMap: {
+            mousedown: 'MouseDown',
+            mouseup: 'MouseUp',
+            click: 'Click',
+            dblclick: 'DblClick',
+            contextmenu: 'ContextMenu',
+            mouseover: 'MouseOver',
+            mouseout: 'MouseOut',
+            mouseenter: 'MouseEnter',
+            mouseleave: 'MouseLeave',
+            keydown: 'KeyDown',
+            focus: 'Focus'
         }
-    });
-    
-    Ext.apply(this, {
-        
-        BOOLEAN: this.BOOL,
-        
-        INTEGER: this.INT,
-        
-        NUMBER: this.FLOAT    
-    });
-};
-Ext.data.JsonWriter = Ext.extend(Ext.data.DataWriter, {
-    
-    encode : true,
-    
-    encodeDelete: false,
-    
-    constructor : function(config){
-        Ext.data.JsonWriter.superclass.constructor.call(this, config);    
     },
 
-    
-    render : function(params, baseParams, data) {
-        if (this.encode === true) {
+    addCmpEvents: function() {
+        this.addEvents(
             
-            Ext.apply(params, baseParams);
-            params[this.meta.root] = Ext.encode(data);
-        } else {
+            'beforeitemmousedown',
             
-            var jdata = Ext.apply({}, baseParams);
-            jdata[this.meta.root] = data;
-            params.jsonData = jdata;
-        }
-    },
-    
-    createRecord : function(rec) {
-       return this.toHash(rec);
-    },
-    
-    updateRecord : function(rec) {
-        return this.toHash(rec);
+            'beforeitemmouseup',
+            
+            'beforeitemmouseenter',
+            
+            'beforeitemmouseleave',
+            
+            'beforeitemclick',
+            
+            'beforeitemdblclick',
+            
+            'beforeitemcontextmenu',
+            
+            'beforeitemkeydown',
+            
+            'itemmousedown',
+            
+            'itemmouseup',
+            
+            'itemmouseenter',
+            
+            'itemmouseleave',
+            
+            'itemclick',
+            
+            'itemdblclick',
+            
+            'itemcontextmenu',
+            
+            'itemkeydown',
+            
+            'beforecontainermousedown',
+            
+            'beforecontainermouseup',
+            
+            'beforecontainermouseover',
+            
+            'beforecontainermouseout',
+            
+            'beforecontainerclick',
+            
+            'beforecontainerdblclick',
+            
+            'beforecontainercontextmenu',
+            
+            'beforecontainerkeydown',
+            
+            'containermouseup',
+            
+            'containermouseover',
+            
+            'containermouseout',
+            
+            'containerclick',
+            
+            'containerdblclick',
+            
+            'containercontextmenu',
+            
+            'containerkeydown',
 
+            
+            'selectionchange',
+            
+            'beforeselect'
+        );
     },
     
-    destroyRecord : function(rec){
-        if(this.encodeDelete){
-            var data = {};
-            data[this.meta.idProperty] = rec.id;
-            return data;
-        }else{
-            return rec.id;
+    afterRender: function(){
+        var me = this,
+            listeners;
+
+        me.callParent();
+
+        listeners = {
+            scope: me,
+            
+            freezeEvent: true,
+            click: me.handleEvent,
+            mousedown: me.handleEvent,
+            mouseup: me.handleEvent,
+            dblclick: me.handleEvent,
+            contextmenu: me.handleEvent,
+            mouseover: me.handleEvent,
+            mouseout: me.handleEvent,
+            keydown: me.handleEvent
+        };
+
+        me.mon(me.getTargetEl(), listeners);
+
+        if (me.store) {
+            me.bindStore(me.store, true);
         }
-    }
-});
-Ext.data.JsonReader = function(meta, recordType){
-    meta = meta || {};
-    
-    
-    
-    
-    Ext.applyIf(meta, {
-        idProperty: 'id',
-        successProperty: 'success',
-        totalProperty: 'total'
-    });
+    },
 
-    Ext.data.JsonReader.superclass.constructor.call(this, meta, recordType || meta.fields);
-};
-Ext.extend(Ext.data.JsonReader, Ext.data.DataReader, {
-    
-    
-    read : function(response){
-        var json = response.responseText;
-        var o = Ext.decode(json);
-        if(!o) {
-            throw {message: 'JsonReader.read: Json object not found'};
+    handleEvent: function(e) {
+        if (this.processUIEvent(e) !== false) {
+            this.processSpecialEvent(e);
         }
-        return this.readRecords(o);
     },
 
     
+    processItemEvent: Ext.emptyFn,
+    processContainerEvent: Ext.emptyFn,
+    processSpecialEvent: Ext.emptyFn,
+
     
-    readResponse : function(action, response) {
-        var o = (response.responseText !== undefined) ? Ext.decode(response.responseText) : response;
-        if(!o) {
-            throw new Ext.data.JsonReader.Error('response');
+    stillOverItem: function (event, overItem) {
+        var nowOver;
+
+        
+        
+        
+        
+        
+        
+        if (overItem && typeof(overItem.offsetParent) === "object") {
+            
+            
+            nowOver = (event.type == 'mouseout') ? event.getRelatedTarget() : event.getTarget();
+            return Ext.fly(overItem).contains(nowOver);
         }
 
-        var root = this.getRoot(o);
-        if (action === Ext.data.Api.actions.create) {
-            var def = Ext.isDefined(root);
-            if (def && Ext.isEmpty(root)) {
-                throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
+        return false;
+    },
+
+    processUIEvent: function(e) {
+        var me = this,
+            item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
+            map = this.statics().EventMap,
+            index, record,
+            type = e.type,
+            overItem = me.mouseOverItem,
+            newType;
+
+        if (!item) {
+            if (type == 'mouseover' && me.stillOverItem(e, overItem)) {
+                item = overItem;
             }
-            else if (!def) {
-                throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
+
+            
+            if (type == 'keydown') {
+                record = me.getSelectionModel().getLastSelected();
+                if (record) {
+                    item = me.getNode(record);
+                }
             }
         }
 
-        
-        var res = new Ext.data.Response({
-            action: action,
-            success: this.getSuccess(o),
-            data: (root) ? this.extractData(root, false) : [],
-            message: this.getMessage(o),
-            raw: o
-        });
+        if (item) {
+            index = me.indexOf(item);
+            if (!record) {
+                record = me.getRecord(item);
+            }
 
-        
-        if (Ext.isEmpty(res.success)) {
-            throw new Ext.data.JsonReader.Error('successProperty-response', this.meta.successProperty);
-        }
-        return res;
-    },
+            if (me.processItemEvent(record, item, index, e) === false) {
+                return false;
+            }
 
-    
-    readRecords : function(o){
-        
-        this.jsonData = o;
-        if(o.metaData){
-            this.onMetaChange(o.metaData);
-        }
-        var s = this.meta, Record = this.recordType,
-            f = Record.prototype.fields, fi = f.items, fl = f.length, v;
+            newType = me.isNewItemEvent(item, e);
+            if (newType === false) {
+                return false;
+            }
 
-        var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
-        if(s.totalProperty){
-            v = parseInt(this.getTotal(o), 10);
-            if(!isNaN(v)){
-                totalRecords = v;
+            if (
+                (me['onBeforeItem' + map[newType]](record, item, index, e) === false) ||
+                (me.fireEvent('beforeitem' + newType, me, record, item, index, e) === false) ||
+                (me['onItem' + map[newType]](record, item, index, e) === false)
+            ) {
+                return false;
             }
+
+            me.fireEvent('item' + newType, me, record, item, index, e);
         }
-        if(s.successProperty){
-            v = this.getSuccess(o);
-            if(v === false || v === 'false'){
-                success = false;
+        else {
+            if (
+                (me.processContainerEvent(e) === false) ||
+                (me['onBeforeContainer' + map[type]](e) === false) ||
+                (me.fireEvent('beforecontainer' + type, me, e) === false) ||
+                (me['onContainer' + map[type]](e) === false)
+            ) {
+                return false;
             }
+
+            me.fireEvent('container' + type, me, e);
         }
 
-        
-        return {
-            success : success,
-            records : this.extractData(root, true), 
-            totalRecords : totalRecords
-        };
+        return true;
     },
 
-    
-    buildExtractors : function() {
-        if(this.ef){
-            return;
-        }
-        var s = this.meta, Record = this.recordType,
-            f = Record.prototype.fields, fi = f.items, fl = f.length;
+    isNewItemEvent: function (item, e) {
+        var me = this,
+            overItem = me.mouseOverItem,
+            type = e.type;
 
-        if(s.totalProperty) {
-            this.getTotal = this.createAccessor(s.totalProperty);
-        }
-        if(s.successProperty) {
-            this.getSuccess = this.createAccessor(s.successProperty);
-        }
-        if (s.messageProperty) {
-            this.getMessage = this.createAccessor(s.messageProperty);
+        switch (type) {
+            case 'mouseover':
+                if (item === overItem) {
+                    return false;
+                }
+                me.mouseOverItem = item;
+                return 'mouseenter';
+
+            case 'mouseout':
+                
+                if (me.stillOverItem(e, overItem)) {
+                    return false;
+                }
+                me.mouseOverItem = null;
+                return 'mouseleave';
         }
-        this.getRoot = s.root ? this.createAccessor(s.root) : function(p){return p;};
-        if (s.id || s.idProperty) {
-            var g = this.createAccessor(s.id || s.idProperty);
-            this.getId = function(rec) {
-                var r = g(rec);
-                return (r === undefined || r === '') ? null : r;
-            };
-        } else {
-            this.getId = function(){return null;};
+        return type;
+    },
+
+    
+    onItemMouseEnter: function(record, item, index, e) {
+        if (this.trackOver) {
+            this.highlightItem(item);
         }
-        var ef = [];
-        for(var i = 0; i < fl; i++){
-            f = fi[i];
-            var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
-            ef.push(this.createAccessor(map));
+    },
+
+    
+    onItemMouseLeave : function(record, item, index, e) {
+        if (this.trackOver) {
+            this.clearHighlight();
         }
-        this.ef = ef;
     },
 
     
-    simpleAccess : function(obj, subsc) {
-        return obj[subsc];
-    },
+    onItemMouseDown: Ext.emptyFn,
+    onItemMouseUp: Ext.emptyFn,
+    onItemFocus: Ext.emptyFn,
+    onItemClick: Ext.emptyFn,
+    onItemDblClick: Ext.emptyFn,
+    onItemContextMenu: Ext.emptyFn,
+    onItemKeyDown: Ext.emptyFn,
+    onBeforeItemMouseDown: Ext.emptyFn,
+    onBeforeItemMouseUp: Ext.emptyFn,
+    onBeforeItemFocus: Ext.emptyFn,
+    onBeforeItemMouseEnter: Ext.emptyFn,
+    onBeforeItemMouseLeave: Ext.emptyFn,
+    onBeforeItemClick: Ext.emptyFn,
+    onBeforeItemDblClick: Ext.emptyFn,
+    onBeforeItemContextMenu: Ext.emptyFn,
+    onBeforeItemKeyDown: Ext.emptyFn,
 
     
-    createAccessor : function(){
-        var re = /[\[\.]/;
-        return function(expr) {
-            if(Ext.isEmpty(expr)){
-                return Ext.emptyFn;
-            }
-            if(Ext.isFunction(expr)){
-                return expr;
-            }
-            var i = String(expr).search(re);
-            if(i >= 0){
-                return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
-            }
-            return function(obj){
-                return obj[expr];
-            };
+    onContainerMouseDown: Ext.emptyFn,
+    onContainerMouseUp: Ext.emptyFn,
+    onContainerMouseOver: Ext.emptyFn,
+    onContainerMouseOut: Ext.emptyFn,
+    onContainerClick: Ext.emptyFn,
+    onContainerDblClick: Ext.emptyFn,
+    onContainerContextMenu: Ext.emptyFn,
+    onContainerKeyDown: Ext.emptyFn,
+    onBeforeContainerMouseDown: Ext.emptyFn,
+    onBeforeContainerMouseUp: Ext.emptyFn,
+    onBeforeContainerMouseOver: Ext.emptyFn,
+    onBeforeContainerMouseOut: Ext.emptyFn,
+    onBeforeContainerClick: Ext.emptyFn,
+    onBeforeContainerDblClick: Ext.emptyFn,
+    onBeforeContainerContextMenu: Ext.emptyFn,
+    onBeforeContainerKeyDown: Ext.emptyFn,
 
-        };
-    }(),
+    
+    highlightItem: function(item) {
+        var me = this;
+        me.clearHighlight();
+        me.highlightedItem = item;
+        Ext.fly(item).addCls(me.overItemCls);
+    },
 
     
-    extractValues : function(data, items, len) {
-        var f, values = {};
-        for(var j = 0; j < len; j++){
-            f = items[j];
-            var v = this.ef[j](data);
-            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
+    clearHighlight: function() {
+        var me = this,
+            highlighted = me.highlightedItem;
+
+        if (highlighted) {
+            Ext.fly(highlighted).removeCls(me.overItemCls);
+            delete me.highlightedItem;
+        }
+    },
+
+    refresh: function() {
+        var me = this;
+        me.clearHighlight();
+        me.callParent(arguments);
+        if (!me.isFixedHeight()) {
+            me.doComponentLayout();
         }
-        return values;
     }
 });
 
+Ext.define('Ext.layout.component.BoundList', {
+    extend: 'Ext.layout.component.Component',
+    alias: 'layout.boundlist',
 
-Ext.data.JsonReader.Error = Ext.extend(Ext.Error, {
-    constructor : function(message, arg) {
-        this.arg = arg;
-        Ext.Error.call(this, message);
-    },
-    name : 'Ext.data.JsonReader'
-});
-Ext.apply(Ext.data.JsonReader.Error.prototype, {
-    lang: {
-        'response': 'An error occurred while json-decoding your server response',
-        'successProperty-response': 'Could not locate your "successProperty" in your server response.  Please review your JsonReader config to ensure the config-property "successProperty" matches the property in your server-response.  See the JsonReader docs.',
-        'root-undefined-config': 'Your JsonReader was configured without a "root" property.  Please review your JsonReader config and make sure to define the root property.  See the JsonReader docs.',
-        'idProperty-undefined' : 'Your JsonReader was configured without an "idProperty"  Please review your JsonReader configuration and ensure the "idProperty" is set (e.g.: "id").  See the JsonReader docs.',
-        'root-empty': 'Data was expected to be returned by the server in the "root" property of the response.  Please review your JsonReader configuration to ensure the "root" property matches that returned in the server-response.  See JsonReader docs.'
-    }
-});
+    type: 'component',
 
-Ext.data.ArrayReader = Ext.extend(Ext.data.JsonReader, {
-    
-    
-    
-    
-    readRecords : function(o){
-        this.arrayData = o;
-        var s = this.meta,
-            sid = s ? Ext.num(s.idIndex, s.id) : null,
-            recordType = this.recordType,
-            fields = recordType.prototype.fields,
-            records = [],
-            success = true,
-            v;
+    beforeLayout: function() {
+        return this.callParent(arguments) || this.owner.refreshed > 0;
+    },
 
-        var root = this.getRoot(o);
+    onLayout : function(width, height) {
+        var me = this,
+            owner = me.owner,
+            floating = owner.floating,
+            el = owner.el,
+            xy = el.getXY(),
+            isNumber = Ext.isNumber,
+            minWidth, maxWidth, minHeight, maxHeight,
+            naturalWidth, naturalHeight, constrainedWidth, constrainedHeight, undef;
 
-        for(var i = 0, len = root.length; i < len; i++) {
-            var n = root[i],
-                values = {},
-                id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
-            for(var j = 0, jlen = fields.length; j < jlen; j++) {
-                var f = fields.items[j],
-                    k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
-                v = n[k] !== undefined ? n[k] : f.defaultValue;
-                v = f.convert(v, n);
-                values[f.name] = v;
-            }
-            var record = new recordType(values, id);
-            record.json = n;
-            records[records.length] = record;
+        if (floating) {
+            
+            el.setXY([-9999,-9999]);
         }
 
-        var totalRecords = records.length;
+        
+        me.setTargetSize(width, height);
 
-        if(s.totalProperty) {
-            v = parseInt(this.getTotal(o), 10);
-            if(!isNaN(v)) {
-                totalRecords = v;
+        
+        if (!isNumber(width)) {
+            minWidth = owner.minWidth;
+            maxWidth = owner.maxWidth;
+            if (isNumber(minWidth) || isNumber(maxWidth)) {
+                naturalWidth = el.getWidth();
+                if (naturalWidth < minWidth) {
+                    constrainedWidth = minWidth;
+                }
+                else if (naturalWidth > maxWidth) {
+                    constrainedWidth = maxWidth;
+                }
+                if (constrainedWidth) {
+                    me.setTargetSize(constrainedWidth);
+                }
             }
         }
-        if(s.successProperty){
-            v = this.getSuccess(o);
-            if(v === false || v === 'false'){
-                success = false;
+        
+        if (!isNumber(height)) {
+            minHeight = owner.minHeight;
+            maxHeight = owner.maxHeight;
+            if (isNumber(minHeight) || isNumber(maxHeight)) {
+                naturalHeight = el.getHeight();
+                if (naturalHeight < minHeight) {
+                    constrainedHeight = minHeight;
+                }
+                else if (naturalHeight > maxHeight) {
+                    constrainedHeight = maxHeight;
+                }
+                if (constrainedHeight) {
+                    me.setTargetSize(undef, constrainedHeight);
+                }
             }
         }
 
-        return {
-            success : success,
-            records : records,
-            totalRecords : totalRecords
-        };
-    }
-});
-Ext.data.ArrayStore = Ext.extend(Ext.data.Store, {
-    
-    constructor: function(config){
-        Ext.data.ArrayStore.superclass.constructor.call(this, Ext.apply(config, {
-            reader: new Ext.data.ArrayReader(config)
-        }));
+        if (floating) {
+            
+            el.setXY(xy);
+        }
     },
 
-    loadData : function(data, append){
-        if(this.expandData === true){
-            var r = [];
-            for(var i = 0, len = data.length; i < len; i++){
-                r[r.length] = [data[i]];
-            }
-            data = r;
+    afterLayout: function() {
+        var me = this,
+            toolbar = me.owner.pagingToolbar;
+        me.callParent();
+        if (toolbar) {
+            toolbar.doComponentLayout();
         }
-        Ext.data.ArrayStore.superclass.loadData.call(this, data, append);
-    }
-});
-Ext.reg('arraystore', Ext.data.ArrayStore);
+    },
 
+    setTargetSize : function(width, height) {
+        var me = this,
+            owner = me.owner,
+            listHeight = null,
+            toolbar;
 
-Ext.data.SimpleStore = Ext.data.ArrayStore;
-Ext.reg('simplestore', Ext.data.SimpleStore);
-Ext.data.JsonStore = Ext.extend(Ext.data.Store, {
-    
-    constructor: function(config){
-        Ext.data.JsonStore.superclass.constructor.call(this, Ext.apply(config, {
-            reader: new Ext.data.JsonReader(config)
-        }));
+        
+        if (Ext.isNumber(height)) {
+            listHeight = height - owner.el.getFrameWidth('tb');
+            toolbar = owner.pagingToolbar;
+            if (toolbar) {
+                listHeight -= toolbar.getHeight();
+            }
+        }
+        me.setElementSize(owner.listEl, null, listHeight);
+
+        me.callParent(arguments);
     }
+
 });
-Ext.reg('jsonstore', Ext.data.JsonStore);
-Ext.data.XmlWriter = function(params) {
-    Ext.data.XmlWriter.superclass.constructor.apply(this, arguments);
-    
-    this.tpl = (typeof(this.tpl) === 'string') ? new Ext.XTemplate(this.tpl).compile() : this.tpl.compile();
-};
-Ext.extend(Ext.data.XmlWriter, Ext.data.DataWriter, {
-    
-    documentRoot: 'xrequest',
-    
-    forceDocumentRoot: false,
-    
-    root: 'records',
-    
-    xmlVersion : '1.0',
-    
-    xmlEncoding: 'ISO-8859-15',
-    
-    
-    tpl: '<tpl for="."><\u003fxml version="{version}" encoding="{encoding}"\u003f><tpl if="documentRoot"><{documentRoot}><tpl for="baseParams"><tpl for="."><{name}>{value}</{name}></tpl></tpl></tpl><tpl if="records.length&gt;1"><{root}></tpl><tpl for="records"><{parent.record}><tpl for="."><{name}>{value}</{name}></tpl></{parent.record}></tpl><tpl if="records.length&gt;1"></{root}></tpl><tpl if="documentRoot"></{documentRoot}></tpl></tpl>',
 
 
-    
-    render : function(params, baseParams, data) {
-        baseParams = this.toArray(baseParams);
-        params.xmlData = this.tpl.applyTemplate({
-            version: this.xmlVersion,
-            encoding: this.xmlEncoding,
-            documentRoot: (baseParams.length > 0 || this.forceDocumentRoot === true) ? this.documentRoot : false,
-            record: this.meta.record,
-            root: this.root,
-            baseParams: baseParams,
-            records: (Ext.isArray(data[0])) ? data : [data]
-        });
-    },
+Ext.define('Ext.toolbar.TextItem', {
+    extend: 'Ext.toolbar.Item',
+    requires: ['Ext.XTemplate'],
+    alias: 'widget.tbtext',
+    alternateClassName: 'Ext.Toolbar.TextItem',
 
     
-    createRecord : function(rec) {
-        return this.toArray(this.toHash(rec));
-    },
+    text: '',
 
+    renderTpl: '{text}',
     
-    updateRecord : function(rec) {
-        return this.toArray(this.toHash(rec));
+    baseCls: Ext.baseCSSPrefix + 'toolbar-text',
 
+    onRender : function() {
+        Ext.apply(this.renderData, {
+            text: this.text
+        });
+        this.callParent(arguments);
     },
+
     
-    destroyRecord : function(rec) {
-        var data = {};
-        data[this.meta.idProperty] = rec.id;
-        return this.toArray(data);
+    setText : function(t) {
+        if (this.rendered) {
+            this.el.update(t);
+            this.ownerCt.doLayout(); 
+        } else {
+            this.text = t;
+        }
     }
 });
 
-Ext.data.XmlReader = function(meta, recordType){
-    meta = meta || {};
+Ext.define('Ext.form.field.Trigger', {
+    extend:'Ext.form.field.Text',
+    alias: ['widget.triggerfield', 'widget.trigger'],
+    requires: ['Ext.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
+    alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
+
+    
+    fieldSubTpl: [
+        '<input id="{id}" type="{type}" ',
+            '<tpl if="name">name="{name}" </tpl>',
+            '<tpl if="size">size="{size}" </tpl>',
+            '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+            'class="{fieldCls} {typeCls}" autocomplete="off" />',
+        '<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
+            '{triggerEl}',
+            '<div class="{clearCls}" role="presentation"></div>',
+        '</div>',
+        {
+            compiled: true,
+            disableFormats: true
+        }
+    ],
 
     
-    Ext.applyIf(meta, {
-        idProperty: meta.idProperty || meta.idPath || meta.id,
-        successProperty: meta.successProperty || meta.success
-    });
 
-    Ext.data.XmlReader.superclass.constructor.call(this, meta, recordType || meta.fields);
-};
-Ext.extend(Ext.data.XmlReader, Ext.data.DataReader, {
     
-    read : function(response){
-        var doc = response.responseXML;
-        if(!doc) {
-            throw {message: "XmlReader.read: XML Document not available"};
-        }
-        return this.readRecords(doc);
-    },
+    triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
 
     
-    readRecords : function(doc){
-        
-        this.xmlData = doc;
-
-        var root    = doc.documentElement || doc,
-            q       = Ext.DomQuery,
-            totalRecords = 0,
-            success = true;
-
-        if(this.meta.totalProperty){
-            totalRecords = this.getTotal(root, 0);
-        }
-        if(this.meta.successProperty){
-            success = this.getSuccess(root);
-        }
-
-        var records = this.extractData(q.select(this.meta.record, root), true); 
-
-        
-        return {
-            success : success,
-            records : records,
-            totalRecords : totalRecords || records.length
-        };
-    },
+    triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
 
     
-    readResponse : function(action, response) {
-        var q = Ext.DomQuery,
-            doc = response.responseXML,
-            root = doc.documentElement || doc;
-
-        
-        var res = new Ext.data.Response({
-            action: action,
-            success : this.getSuccess(root),
-            message: this.getMessage(root),
-            data: this.extractData(q.select(this.meta.record, root) || q.select(this.meta.root, root), false),
-            raw: doc
-        });
+    hideTrigger: false,
 
-        if (Ext.isEmpty(res.success)) {
-            throw new Ext.data.DataReader.Error('successProperty-response', this.meta.successProperty);
-        }
+    
+    editable: true,
 
-        
-        if (action === Ext.data.Api.actions.create) {
-            var def = Ext.isDefined(res.data);
-            if (def && Ext.isEmpty(res.data)) {
-                throw new Ext.data.JsonReader.Error('root-empty', this.meta.root);
-            }
-            else if (!def) {
-                throw new Ext.data.JsonReader.Error('root-undefined-response', this.meta.root);
-            }
-        }
-        return res;
-    },
+    
+    readOnly: false,
 
-    getSuccess : function() {
-        return true;
-    },
+    
 
     
-    buildExtractors : function() {
-        if(this.ef){
-            return;
-        }
-        var s       = this.meta,
-            Record  = this.recordType,
-            f       = Record.prototype.fields,
-            fi      = f.items,
-            fl      = f.length;
+    repeatTriggerClick: false,
 
-        if(s.totalProperty) {
-            this.getTotal = this.createAccessor(s.totalProperty);
-        }
-        if(s.successProperty) {
-            this.getSuccess = this.createAccessor(s.successProperty);
-        }
-        if (s.messageProperty) {
-            this.getMessage = this.createAccessor(s.messageProperty);
-        }
-        this.getRoot = function(res) {
-            return (!Ext.isEmpty(res[this.meta.record])) ? res[this.meta.record] : res[this.meta.root];
-        };
-        if (s.idPath || s.idProperty) {
-            var g = this.createAccessor(s.idPath || s.idProperty);
-            this.getId = function(rec) {
-                var id = g(rec) || rec.id;
-                return (id === undefined || id === '') ? null : id;
-            };
-        } else {
-            this.getId = function(){return null;};
-        }
-        var ef = [];
-        for(var i = 0; i < fl; i++){
-            f = fi[i];
-            var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
-            ef.push(this.createAccessor(map));
-        }
-        this.ef = ef;
-    },
 
     
-    createAccessor : function(){
-        var q = Ext.DomQuery;
-        return function(key) {
-            switch(key) {
-                case this.meta.totalProperty:
-                    return function(root, def){
-                        return q.selectNumber(key, root, def);
-                    };
-                    break;
-                case this.meta.successProperty:
-                    return function(root, def) {
-                        var sv = q.selectValue(key, root, true);
-                        var success = sv !== false && sv !== 'false';
-                        return success;
-                    };
-                    break;
-                default:
-                    return function(root, def) {
-                        return q.selectValue(key, root, def);
-                    };
-                    break;
-            }
-        };
-    }(),
-
+    autoSize: Ext.emptyFn,
     
-    extractValues : function(data, items, len) {
-        var f, values = {};
-        for(var j = 0; j < len; j++){
-            f = items[j];
-            var v = this.ef[j](data);
-            values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue, data);
-        }
-        return values;
-    }
-});
-Ext.data.XmlStore = Ext.extend(Ext.data.Store, {
+    monitorTab: true,
     
-    constructor: function(config){
-        Ext.data.XmlStore.superclass.constructor.call(this, Ext.apply(config, {
-            reader: new Ext.data.XmlReader(config)
-        }));
-    }
-});
-Ext.reg('xmlstore', Ext.data.XmlStore);
-Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
+    mimicing: false,
+    
+    triggerIndexRe: /trigger-index-(\d+)/,
+
+    componentLayout: 'triggerfield',
+
+    initComponent: function() {
+        this.wrapFocusCls = this.triggerWrapCls + '-focus';
+        this.callParent(arguments);
+    },
 
     
-    constructor: function(config) {
-        config = config || {};
+    onRender: function(ct, position) {
+        var me = this,
+            triggerCls,
+            triggerBaseCls = me.triggerBaseCls,
+            triggerWrapCls = me.triggerWrapCls,
+            triggerConfigs = [],
+            i;
 
         
         
         
         
-        this.hasMultiSort  = true;
-        this.multiSortInfo = this.multiSortInfo || {sorters: []};
-
-        var sorters    = this.multiSortInfo.sorters,
-            groupField = config.groupField || this.groupField,
-            sortInfo   = config.sortInfo || this.sortInfo,
-            groupDir   = config.groupDir || this.groupDir;
+        if (!me.trigger1Cls) {
+            me.trigger1Cls = me.triggerCls;
+        }
 
         
-        if(groupField){
-            sorters.push({
-                field    : groupField,
-                direction: groupDir
+        for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
+            triggerConfigs.push({
+                cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
+                role: 'button'
             });
         }
+        triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
 
         
-        if (sortInfo) {
-            sorters.push(sortInfo);
-        }
+        me.addChildEls('triggerWrap');
 
-        Ext.data.GroupingStore.superclass.constructor.call(this, config);
+        Ext.applyIf(me.subTplData, {
+            triggerWrapCls: triggerWrapCls,
+            triggerEl: Ext.DomHelper.markup(triggerConfigs),
+            clearCls: me.clearCls
+        });
 
-        this.addEvents(
-          
-          'groupchange'
-        );
+        me.callParent(arguments);
+
+        
+        me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
 
-        this.applyGroupField();
+        me.doc = Ext.getDoc();
+        me.initTrigger();
     },
 
+    onEnable: function() {
+        this.callParent();
+        this.triggerWrap.unmask();
+    },
     
+    onDisable: function() {
+        this.callParent();
+        this.triggerWrap.mask();
+    },
     
-    remoteGroup : false,
-    
-    groupOnSort:false,
-
-    groupDir : 'ASC',
-
-    
-    clearGrouping : function(){
-        this.groupField = false;
+    afterRender: function() {
+        this.callParent();
+        this.updateEditState();
+        this.triggerEl.unselectable();
+    },
 
-        if(this.remoteGroup){
-            if(this.baseParams){
-                delete this.baseParams.groupBy;
-                delete this.baseParams.groupDir;
-            }
-            var lo = this.lastOptions;
-            if(lo && lo.params){
-                delete lo.params.groupBy;
-                delete lo.params.groupDir;
+    updateEditState: function() {
+        var me = this,
+            inputEl = me.inputEl,
+            triggerWrap = me.triggerWrap,
+            noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
+            displayed,
+            readOnly;
+
+        if (me.rendered) {
+            if (me.readOnly) {
+                inputEl.addCls(noeditCls);
+                readOnly = true;
+                displayed = false;
+            } else {
+                if (me.editable) {
+                    inputEl.removeCls(noeditCls);
+                    readOnly = false;
+                } else {
+                    inputEl.addCls(noeditCls);
+                    readOnly = true;
+                }
+                displayed = !me.hideTrigger;
             }
 
-            this.reload();
-        }else{
-            this.sort();
-            this.fireEvent('datachanged', this);
+            triggerWrap.setDisplayed(displayed);
+            inputEl.dom.readOnly = readOnly;
+            me.doComponentLayout();
         }
     },
 
     
-    groupBy : function(field, forceRegroup, direction) {
-        direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
-
-        if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
-            return; 
+    getTriggerWidth: function() {
+        var me = this,
+            triggerWrap = me.triggerWrap,
+            totalTriggerWidth = 0;
+        if (triggerWrap && !me.hideTrigger && !me.readOnly) {
+            me.triggerEl.each(function(trigger) {
+                totalTriggerWidth += trigger.getWidth();
+            });
+            totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
         }
+        return totalTriggerWidth;
+    },
 
-        
-        
-        var sorters = this.multiSortInfo.sorters;
-        if (sorters.length > 0 && sorters[0].field == this.groupField) {
-            sorters.shift();
+    setHideTrigger: function(hideTrigger) {
+        if (hideTrigger != this.hideTrigger) {
+            this.hideTrigger = hideTrigger;
+            this.updateEditState();
         }
+    },
 
-        this.groupField = field;
-        this.groupDir = direction;
-        this.applyGroupField();
-
-        var fireGroupEvent = function() {
-            this.fireEvent('groupchange', this, this.getGroupState());
-        };
-
-        if (this.groupOnSort) {
-            this.sort(field, direction);
-            fireGroupEvent.call(this);
-            return;
+    
+    setEditable: function(editable) {
+        if (editable != this.editable) {
+            this.editable = editable;
+            this.updateEditState();
         }
+    },
 
-        if (this.remoteGroup) {
-            this.on('load', fireGroupEvent, this, {single: true});
-            this.reload();
-        } else {
-            this.sort(sorters);
-            fireGroupEvent.call(this);
+    
+    setReadOnly: function(readOnly) {
+        if (readOnly != this.readOnly) {
+            this.readOnly = readOnly;
+            this.updateEditState();
         }
     },
 
     
-    
-    sort : function(fieldName, dir) {
-        if (this.remoteSort) {
-            return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
+    initTrigger: function() {
+        var me = this,
+            triggerWrap = me.triggerWrap,
+            triggerEl = me.triggerEl;
+
+        if (me.repeatTriggerClick) {
+            me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
+                preventDefault: true,
+                handler: function(cr, e) {
+                    me.onTriggerWrapClick(e);
+                }
+            });
+        } else {
+            me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
         }
 
-        var sorters = [];
-
-        
-        if (Ext.isArray(arguments[0])) {
-            sorters = arguments[0];
-        } else if (fieldName == undefined) {
-            
-            
-            sorters = this.sortInfo ? [this.sortInfo] : [];
-        } else {
-            
-            
-            var field = this.fields.get(fieldName);
-            if (!field) return false;
+        triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
+        triggerEl.each(function(el, c, i) {
+            el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
+        });
+        triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
+        triggerEl.each(function(el, c, i) {
+            el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
+        });
+    },
 
-            var name       = field.name,
-                sortInfo   = this.sortInfo || null,
-                sortToggle = this.sortToggle ? this.sortToggle[name] : null;
+    
+    onDestroy: function() {
+        var me = this;
+        Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
+        delete me.doc;
+        me.callParent();
+    },
 
-            if (!dir) {
-                if (sortInfo && sortInfo.field == name) { 
-                    dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
-                } else {
-                    dir = field.sortDir;
-                }
+    
+    onFocus: function() {
+        var me = this;
+        me.callParent();
+        if (!me.mimicing) {
+            me.bodyEl.addCls(me.wrapFocusCls);
+            me.mimicing = true;
+            me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
+                delay: 10
+            });
+            if (me.monitorTab) {
+                me.on('specialkey', me.checkTab, me);
             }
-
-            this.sortToggle[name] = dir;
-            this.sortInfo = {field: name, direction: dir};
-
-            sorters = [this.sortInfo];
         }
+    },
 
-        
-        if (this.groupField) {
-            sorters.unshift({direction: this.groupDir, field: this.groupField});
+    
+    checkTab: function(me, e) {
+        if (!this.ignoreMonitorTab && e.getKey() == e.TAB) {
+            this.triggerBlur();
         }
-
-        return this.multiSort.call(this, sorters, dir);
     },
 
     
-    applyGroupField: function(){
-        if (this.remoteGroup) {
-            if(!this.baseParams){
-                this.baseParams = {};
-            }
-
-            Ext.apply(this.baseParams, {
-                groupBy : this.groupField,
-                groupDir: this.groupDir
-            });
+    onBlur: Ext.emptyFn,
 
-            var lo = this.lastOptions;
-            if (lo && lo.params) {
-                lo.params.groupDir = this.groupDir;
+    
+    mimicBlur: function(e) {
+        if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
+            this.triggerBlur();
+        }
+    },
 
-                
-                delete lo.params.groupBy;
-            }
+    
+    triggerBlur: function() {
+        var me = this;
+        me.mimicing = false;
+        me.mun(me.doc, 'mousedown', me.mimicBlur, me);
+        if (me.monitorTab && me.inputEl) {
+            me.un('specialkey', me.checkTab, me);
+        }
+        Ext.form.field.Trigger.superclass.onBlur.call(me);
+        if (me.bodyEl) {
+            me.bodyEl.removeCls(me.wrapFocusCls);
         }
     },
 
+    beforeBlur: Ext.emptyFn,
+
     
-    applyGrouping : function(alwaysFireChange){
-        if(this.groupField !== false){
-            this.groupBy(this.groupField, true, this.groupDir);
-            return true;
-        }else{
-            if(alwaysFireChange === true){
-                this.fireEvent('datachanged', this);
+    
+    validateBlur: function(e) {
+        return true;
+    },
+
+    
+    
+    
+    onTriggerWrapClick: function(e) {
+        var me = this,
+            t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
+            match = t && t.className.match(me.triggerIndexRe),
+            idx,
+            triggerClickMethod;
+
+        if (match && !me.readOnly) {
+            idx = parseInt(match[1], 10);
+            triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
+            if (triggerClickMethod) {
+                triggerClickMethod.call(me, e);
             }
-            return false;
         }
     },
 
     
-    getGroupState : function(){
-        return this.groupOnSort && this.groupField !== false ?
-               (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
-    }
+    onTriggerClick: Ext.emptyFn
+
+    
+    
+    
 });
-Ext.reg('groupingstore', Ext.data.GroupingStore);
 
-Ext.data.DirectProxy = function(config){
-    Ext.apply(this, config);
-    if(typeof this.paramOrder == 'string'){
-        this.paramOrder = this.paramOrder.split(/[\s,|]/);
-    }
-    Ext.data.DirectProxy.superclass.constructor.call(this, config);
-};
 
-Ext.extend(Ext.data.DirectProxy, Ext.data.DataProxy, {
+Ext.define('Ext.form.field.Picker', {
+    extend: 'Ext.form.field.Trigger',
+    alias: 'widget.pickerfield',
+    alternateClassName: 'Ext.form.Picker',
+    requires: ['Ext.util.KeyNav'],
+
     
-    paramOrder: undefined,
+    matchFieldWidth: true,
 
     
-    paramsAsHash: true,
+    pickerAlign: 'tl-bl?',
 
     
-    directFn : undefined,
 
     
-    doRequest : function(action, rs, params, reader, callback, scope, options) {
-        var args = [],
-            directFn = this.api[action] || this.directFn;
+    openCls: Ext.baseCSSPrefix + 'pickerfield-open',
 
-        switch (action) {
-            case Ext.data.Api.actions.create:
-                args.push(params.jsonData);            
-                break;
-            case Ext.data.Api.actions.read:
-                
-                if(directFn.directCfg.method.len > 0){
-                    if(this.paramOrder){
-                        for(var i = 0, len = this.paramOrder.length; i < len; i++){
-                            args.push(params[this.paramOrder[i]]);
-                        }
-                    }else if(this.paramsAsHash){
-                        args.push(params);
-                    }
-                }
-                break;
-            case Ext.data.Api.actions.update:
-                args.push(params.jsonData);        
-                break;
-            case Ext.data.Api.actions.destroy:
-                args.push(params.jsonData);        
-                break;
-        }
+    
 
-        var trans = {
-            params : params || {},
-            request: {
-                callback : callback,
-                scope : scope,
-                arg : options
-            },
-            reader: reader
-        };
+    
+    editable: true,
+
+
+    initComponent: function() {
+        this.callParent();
 
-        args.push(this.createCallback(action, rs, trans), this);
-        directFn.apply(window, args);
+        
+        this.addEvents(
+            
+            'expand',
+            
+            'collapse',
+            
+            'select'
+        );
     },
 
-    
-    createCallback : function(action, rs, trans) {
+
+    initEvents: function() {
         var me = this;
-        return function(result, res) {
-            if (!res.status) {
-                
-                if (action === Ext.data.Api.actions.read) {
-                    me.fireEvent("loadexception", me, trans, res, null);
+        me.callParent();
+
+        
+        me.keyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
+            down: function() {
+                if (!me.isExpanded) {
+                    
+                    
+                    me.onTriggerClick();
                 }
-                me.fireEvent('exception', me, 'remote', action, trans, res, null);
-                trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
-                return;
-            }
-            if (action === Ext.data.Api.actions.read) {
-                me.onRead(action, trans, result, res);
-            } else {
-                me.onWrite(action, trans, result, res, rs);
-            }
-        };
-    },
+            },
+            esc: me.collapse,
+            scope: me,
+            forceKeyDown: true
+        });
 
-    
-    onRead : function(action, trans, result, res) {
-        var records;
-        try {
-            records = trans.reader.readRecords(result);
+        
+        if (!me.editable) {
+            me.mon(me.inputEl, 'click', me.onTriggerClick, me);
         }
-        catch (ex) {
-            
-            this.fireEvent("loadexception", this, trans, res, ex);
 
-            this.fireEvent('exception', this, 'response', action, trans, res, ex);
-            trans.request.callback.call(trans.request.scope, null, trans.request.arg, false);
-            return;
+        
+        if (Ext.isGecko) {
+            me.inputEl.dom.setAttribute('autocomplete', 'off');
         }
-        this.fireEvent("load", this, res, trans.request.arg);
-        trans.request.callback.call(trans.request.scope, records, trans.request.arg, true);
     },
-    
-    onWrite : function(action, trans, result, res, rs) {
-        var data = trans.reader.extractData(trans.reader.getRoot(result), false);
-        var success = trans.reader.getSuccess(result);
-        success = (success !== false);
-        if (success){
-            this.fireEvent("write", this, action, data, res, rs, trans.request.arg);
-        }else{
-            this.fireEvent('exception', this, 'remote', action, trans, result, rs);
-        }
-        trans.request.callback.call(trans.request.scope, data, res, success);
-    }
-});
 
-Ext.data.DirectStore = Ext.extend(Ext.data.Store, {
-    constructor : function(config){
-        
-        var c = Ext.apply({}, {
-            batchTransactions: false
-        }, config);
-        Ext.data.DirectStore.superclass.constructor.call(this, Ext.apply(c, {
-            proxy: Ext.isDefined(c.proxy) ? c.proxy : new Ext.data.DirectProxy(Ext.copyTo({}, c, 'paramOrder,paramsAsHash,directFn,api')),
-            reader: (!Ext.isDefined(c.reader) && c.fields) ? new Ext.data.JsonReader(Ext.copyTo({}, c, 'totalProperty,root,idProperty'), c.fields) : c.reader
-        }));
-    }
-});
-Ext.reg('directstore', Ext.data.DirectStore);
 
-Ext.Direct = Ext.extend(Ext.util.Observable, {
     
+    expand: function() {
+        var me = this,
+            bodyEl, picker, collapseIf;
 
-    
-    exceptions: {
-        TRANSPORT: 'xhr',
-        PARSE: 'parse',
-        LOGIN: 'login',
-        SERVER: 'exception'
-    },
+        if (me.rendered && !me.isExpanded && !me.isDestroyed) {
+            bodyEl = me.bodyEl;
+            picker = me.getPicker();
+            collapseIf = me.collapseIf;
 
-    
-    constructor: function(){
-        this.addEvents(
             
-            'event',
+            picker.show();
+            me.isExpanded = true;
+            me.alignPicker();
+            bodyEl.addCls(me.openCls);
+
             
-            'exception'
-        );
-        this.transactions = {};
-        this.providers = {};
+            me.mon(Ext.getDoc(), {
+                mousewheel: collapseIf,
+                mousedown: collapseIf,
+                scope: me
+            });
+            Ext.EventManager.onWindowResize(me.alignPicker, me);
+            me.fireEvent('expand', me);
+            me.onExpand();
+        }
     },
 
+    onExpand: Ext.emptyFn,
+
     
-    addProvider : function(provider){
-        var a = arguments;
-        if(a.length > 1){
-            for(var i = 0, len = a.length; i < len; i++){
-                this.addProvider(a[i]);
+    alignPicker: function() {
+        var me = this,
+            picker;
+
+        if (me.isExpanded) {
+            picker = me.getPicker();
+            if (me.matchFieldWidth) {
+                
+                picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
+            }
+            if (picker.isFloating()) {
+                me.doAlign();
             }
-            return;
         }
+    },
+
+    
+    doAlign: function(){
+        var me = this,
+            picker = me.picker,
+            aboveSfx = '-above',
+            isAbove;
 
+        me.picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
         
-        if(!provider.events){
-            provider = new Ext.Direct.PROVIDERS[provider.type](provider);
-        }
-        provider.id = provider.id || Ext.id();
-        this.providers[provider.id] = provider;
+        
+        isAbove = picker.el.getY() < me.inputEl.getY();
+        me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
+        picker[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
+    },
+
+    
+    collapse: function() {
+        if (this.isExpanded && !this.isDestroyed) {
+            var me = this,
+                openCls = me.openCls,
+                picker = me.picker,
+                doc = Ext.getDoc(),
+                collapseIf = me.collapseIf,
+                aboveSfx = '-above';
 
-        provider.on('data', this.onProviderData, this);
-        provider.on('exception', this.onProviderException, this);
+            
+            picker.hide();
+            me.isExpanded = false;
 
+            
+            me.bodyEl.removeCls([openCls, openCls + aboveSfx]);
+            picker.el.removeCls(picker.baseCls + aboveSfx);
 
-        if(!provider.isConnected()){
-            provider.connect();
+            
+            doc.un('mousewheel', collapseIf, me);
+            doc.un('mousedown', collapseIf, me);
+            Ext.EventManager.removeResizeListener(me.alignPicker, me);
+            me.fireEvent('collapse', me);
+            me.onCollapse();
         }
-
-        return provider;
     },
 
-    
-    getProvider : function(id){
-        return this.providers[id];
-    },
+    onCollapse: Ext.emptyFn,
 
-    removeProvider : function(id){
-        var provider = id.id ? id : this.providers[id];
-        provider.un('data', this.onProviderData, this);
-        provider.un('exception', this.onProviderException, this);
-        delete this.providers[provider.id];
-        return provider;
-    },
 
-    addTransaction: function(t){
-        this.transactions[t.tid] = t;
-        return t;
+    
+    collapseIf: function(e) {
+        var me = this;
+        if (!me.isDestroyed && !e.within(me.bodyEl, false, true) && !e.within(me.picker.el, false, true)) {
+            me.collapse();
+        }
     },
 
-    removeTransaction: function(t){
-        delete this.transactions[t.tid || t];
-        return t;
+    
+    getPicker: function() {
+        var me = this;
+        return me.picker || (me.picker = me.createPicker());
     },
 
-    getTransaction: function(tid){
-        return this.transactions[tid.tid || tid];
-    },
+    
+    createPicker: Ext.emptyFn,
 
-    onProviderData : function(provider, e){
-        if(Ext.isArray(e)){
-            for(var i = 0, len = e.length; i < len; i++){
-                this.onProviderData(provider, e[i]);
+    
+    onTriggerClick: function() {
+        var me = this;
+        if (!me.readOnly && !me.disabled) {
+            if (me.isExpanded) {
+                me.collapse();
+            } else {
+                me.expand();
             }
-            return;
+            me.inputEl.focus();
         }
-        if(e.name && e.name != 'event' && e.name != 'exception'){
-            this.fireEvent(e.name, e);
-        }else if(e.type == 'exception'){
-            this.fireEvent('exception', e);
+    },
+
+    mimicBlur: function(e) {
+        var me = this,
+            picker = me.picker;
+        
+        if (!picker || !e.within(picker.el, false, true)) {
+            me.callParent(arguments);
         }
-        this.fireEvent('event', e, provider);
     },
 
-    createEvent : function(response, extraProps){
-        return new Ext.Direct.eventTypes[response.type](Ext.apply(response, extraProps));
+    onDestroy : function(){
+        var me = this,
+            picker = me.picker;
+
+        Ext.EventManager.removeResizeListener(me.alignPicker, me);
+        Ext.destroy(me.keyNav);
+        if (picker) {
+            delete picker.pickerField;
+            picker.destroy();
+        }
+        me.callParent();
     }
+
 });
 
-Ext.Direct = new Ext.Direct();
 
-Ext.Direct.TID = 1;
-Ext.Direct.PROVIDERS = {};
-Ext.Direct.Transaction = function(config){
-    Ext.apply(this, config);
-    this.tid = ++Ext.Direct.TID;
-    this.retryCount = 0;
-};
-Ext.Direct.Transaction.prototype = {
-    send: function(){
-        this.provider.queueTransaction(this);
-    },
 
-    retry: function(){
-        this.retryCount++;
-        this.send();
-    },
+Ext.define('Ext.form.field.Spinner', {
+    extend: 'Ext.form.field.Trigger',
+    alias: 'widget.spinnerfield',
+    alternateClassName: 'Ext.form.Spinner',
+    requires: ['Ext.util.KeyNav'],
 
-    getProvider: function(){
-        return this.provider;
-    }
-};Ext.Direct.Event = function(config){
-    Ext.apply(this, config);
-};
+    trigger1Cls: Ext.baseCSSPrefix + 'form-spinner-up',
+    trigger2Cls: Ext.baseCSSPrefix + 'form-spinner-down',
 
-Ext.Direct.Event.prototype = {
-    status: true,
-    getData: function(){
-        return this.data;
-    }
-};
+    
+    spinUpEnabled: true,
 
-Ext.Direct.RemotingEvent = Ext.extend(Ext.Direct.Event, {
-    type: 'rpc',
-    getTransaction: function(){
-        return this.transaction || Ext.Direct.getTransaction(this.tid);
-    }
-});
+    
+    spinDownEnabled: true,
 
-Ext.Direct.ExceptionEvent = Ext.extend(Ext.Direct.RemotingEvent, {
-    status: false,
-    type: 'exception'
-});
+    
+    keyNavEnabled: true,
 
-Ext.Direct.eventTypes = {
-    'rpc':  Ext.Direct.RemotingEvent,
-    'event':  Ext.Direct.Event,
-    'exception':  Ext.Direct.ExceptionEvent
-};
+    
+    mouseWheelEnabled: true,
 
-Ext.direct.Provider = Ext.extend(Ext.util.Observable, {    
     
-        
-        
-    priority: 1,
+    repeatTriggerClick: true,
 
-        
     
-    constructor : function(config){
-        Ext.apply(this, config);
+    onSpinUp: Ext.emptyFn,
+
+    
+    onSpinDown: Ext.emptyFn,
+
+    initComponent: function() {
+        this.callParent();
+
         this.addEvents(
-                        
-            'connect',
-                        
-            'disconnect',
-                        
-            'data',
-                                    
-            'exception'
+            
+            'spin',
+
+            
+            'spinup',
+
+            
+            'spindown'
         );
-        Ext.direct.Provider.superclass.constructor.call(this, config);
     },
 
     
-    isConnected: function(){
-        return false;
-    },
+    onRender: function() {
+        var me = this,
+            triggers;
 
-    
-    connect: Ext.emptyFn,
-    
-    
-    disconnect: Ext.emptyFn
-});
+        me.callParent(arguments);
+        triggers = me.triggerEl;
 
-Ext.direct.JsonProvider = Ext.extend(Ext.direct.Provider, {
-    parseResponse: function(xhr){
-        if(!Ext.isEmpty(xhr.responseText)){
-            if(typeof xhr.responseText == 'object'){
-                return xhr.responseText;
-            }
-            return Ext.decode(xhr.responseText);
-        }
-        return null;
-    },
+        
+        me.spinUpEl = triggers.item(0);
+        
+        me.spinDownEl = triggers.item(1);
 
-    getEvents: function(xhr){
-        var data = null;
-        try{
-            data = this.parseResponse(xhr);
-        }catch(e){
-            var event = new Ext.Direct.ExceptionEvent({
-                data: e,
-                xhr: xhr,
-                code: Ext.Direct.exceptions.PARSE,
-                message: 'Error parsing json response: \n\n ' + data
+        
+        me.setSpinUpEnabled(me.spinUpEnabled);
+        me.setSpinDownEnabled(me.spinDownEnabled);
+
+        
+        if (me.keyNavEnabled) {
+            me.spinnerKeyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
+                scope: me,
+                up: me.spinUp,
+                down: me.spinDown
             });
-            return [event];
         }
-        var events = [];
-        if(Ext.isArray(data)){
-            for(var i = 0, len = data.length; i < len; i++){
-                events.push(Ext.Direct.createEvent(data[i]));
-            }
-        }else{
-            events.push(Ext.Direct.createEvent(data));
+
+        
+        if (me.mouseWheelEnabled) {
+            me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me);
         }
-        return events;
-    }
-});
-Ext.direct.PollingProvider = Ext.extend(Ext.direct.JsonProvider, {
-    
-    
-    priority: 3,
-    
-    
-    interval: 3000,
+    },
 
     
+    getTriggerWidth: function() {
+        return this.hideTrigger || this.readOnly ? 0 : this.spinUpEl.getWidth() + this.triggerWrap.getFrameWidth('lr');
+    },
+
     
-    
+    onTrigger1Click: function() {
+        this.spinUp();
+    },
 
     
-    constructor : function(config){
-        Ext.direct.PollingProvider.superclass.constructor.call(this, config);
-        this.addEvents(
-            
-            'beforepoll',            
-            
-            'poll'
-        );
+    onTrigger2Click: function() {
+        this.spinDown();
     },
 
     
-    isConnected: function(){
-        return !!this.pollTask;
+    spinUp: function() {
+        var me = this;
+        if (me.spinUpEnabled && !me.disabled) {
+            me.fireEvent('spin', me, 'up');
+            me.fireEvent('spinup', me);
+            me.onSpinUp();
+        }
+    },
+
+    
+    spinDown: function() {
+        var me = this;
+        if (me.spinDownEnabled && !me.disabled) {
+            me.fireEvent('spin', me, 'down');
+            me.fireEvent('spindown', me);
+            me.onSpinDown();
+        }
     },
 
     
-    connect: function(){
-        if(this.url && !this.pollTask){
-            this.pollTask = Ext.TaskMgr.start({
-                run: function(){
-                    if(this.fireEvent('beforepoll', this) !== false){
-                        if(typeof this.url == 'function'){
-                            this.url(this.baseParams);
-                        }else{
-                            Ext.Ajax.request({
-                                url: this.url,
-                                callback: this.onData,
-                                scope: this,
-                                params: this.baseParams
-                            });
-                        }
-                    }
-                },
-                interval: this.interval,
-                scope: this
-            });
-            this.fireEvent('connect', this);
-        }else if(!this.url){
-            throw 'Error initializing PollingProvider, no url configured.';
+    setSpinUpEnabled: function(enabled) {
+        var me = this,
+            wasEnabled = me.spinUpEnabled;
+        me.spinUpEnabled = enabled;
+        if (wasEnabled !== enabled && me.rendered) {
+            me.spinUpEl[enabled ? 'removeCls' : 'addCls'](me.trigger1Cls + '-disabled');
         }
     },
 
     
-    disconnect: function(){
-        if(this.pollTask){
-            Ext.TaskMgr.stop(this.pollTask);
-            delete this.pollTask;
-            this.fireEvent('disconnect', this);
+    setSpinDownEnabled: function(enabled) {
+        var me = this,
+            wasEnabled = me.spinDownEnabled;
+        me.spinDownEnabled = enabled;
+        if (wasEnabled !== enabled && me.rendered) {
+            me.spinDownEl[enabled ? 'removeCls' : 'addCls'](me.trigger2Cls + '-disabled');
         }
     },
 
     
-    onData: function(opt, success, xhr){
-        if(success){
-            var events = this.getEvents(xhr);
-            for(var i = 0, len = events.length; i < len; i++){
-                var e = events[i];
-                this.fireEvent('data', this, e);
+    onMouseWheel: function(e) {
+        var me = this,
+            delta;
+        if (me.hasFocus) {
+            delta = e.getWheelDelta();
+            if (delta > 0) {
+                me.spinUp();
             }
-        }else{
-            var e = new Ext.Direct.ExceptionEvent({
-                data: e,
-                code: Ext.Direct.exceptions.TRANSPORT,
-                message: 'Unable to connect to the server.',
-                xhr: xhr
-            });
-            this.fireEvent('data', this, e);
+            else if (delta < 0) {
+                me.spinDown();
+            }
+            e.stopEvent();
         }
+    },
+
+    onDestroy: function() {
+        Ext.destroyMembers(this, 'spinnerKeyNav', 'spinUpEl', 'spinDownEl');
+        this.callParent();
     }
+
 });
 
-Ext.Direct.PROVIDERS['polling'] = Ext.direct.PollingProvider;
-Ext.direct.RemotingProvider = Ext.extend(Ext.direct.JsonProvider, {       
-    
-    
+Ext.define('Ext.form.field.Number', {
+    extend:'Ext.form.field.Spinner',
+    alias: 'widget.numberfield',
+    alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
+
     
     
+
     
+    allowDecimals : true,
+
     
+    decimalSeparator : '.',
+
     
+    decimalPrecision : 2,
+
     
+    minValue: Number.NEGATIVE_INFINITY,
+
     
-    enableBuffer: 10,
+    maxValue: Number.MAX_VALUE,
+
     
+    step: 1,
+
     
-    maxRetries: 1,
+    minText : 'The minimum value for this field is {0}',
+
     
+    maxText : 'The maximum value for this field is {0}',
+
     
-    timeout: undefined,
+    nanText : '{0} is not a valid number',
 
-    constructor : function(config){
-        Ext.direct.RemotingProvider.superclass.constructor.call(this, config);
-        this.addEvents(
-                        
-            'beforecall',            
-                        
-            'call'
-        );
-        this.namespace = (Ext.isString(this.namespace)) ? Ext.ns(this.namespace) : this.namespace || window;
-        this.transactions = {};
-        this.callBuffer = [];
-    },
+    
+    negativeText : 'The value cannot be negative',
 
     
-    initAPI : function(){
-        var o = this.actions;
-        for(var c in o){
-            var cls = this.namespace[c] || (this.namespace[c] = {}),
-                ms = o[c];
-            for(var i = 0, len = ms.length; i < len; i++){
-                var m = ms[i];
-                cls[m.name] = this.createMethod(c, m);
-            }
-        }
-    },
+    baseChars : '0123456789',
 
     
-    isConnected: function(){
-        return !!this.connected;
-    },
+    autoStripChars: false,
 
-    connect: function(){
-        if(this.url){
-            this.initAPI();
-            this.connected = true;
-            this.fireEvent('connect', this);
-        }else if(!this.url){
-            throw 'Error initializing RemotingProvider, no url configured.';
-        }
-    },
+    initComponent: function() {
+        var me = this,
+            allowed;
 
-    disconnect: function(){
-        if(this.connected){
-            this.connected = false;
-            this.fireEvent('disconnect', this);
-        }
-    },
+        me.callParent();
 
-    onData: function(opt, success, xhr){
-        if(success){
-            var events = this.getEvents(xhr);
-            for(var i = 0, len = events.length; i < len; i++){
-                var e = events[i],
-                    t = this.getTransaction(e);
-                this.fireEvent('data', this, e);
-                if(t){
-                    this.doCallback(t, e, true);
-                    Ext.Direct.removeTransaction(t);
-                }
+        me.setMinValue(me.minValue);
+        me.setMaxValue(me.maxValue);
+
+        
+        if (me.disableKeyFilter !== true) {
+            allowed = me.baseChars + '';
+            if (me.allowDecimals) {
+                allowed += me.decimalSeparator;
             }
-        }else{
-            var ts = [].concat(opt.ts);
-            for(var i = 0, len = ts.length; i < len; i++){
-                var t = this.getTransaction(ts[i]);
-                if(t && t.retryCount < this.maxRetries){
-                    t.retry();
-                }else{
-                    var e = new Ext.Direct.ExceptionEvent({
-                        data: e,
-                        transaction: t,
-                        code: Ext.Direct.exceptions.TRANSPORT,
-                        message: 'Unable to connect to the server.',
-                        xhr: xhr
-                    });
-                    this.fireEvent('data', this, e);
-                    if(t){
-                        this.doCallback(t, e, false);
-                        Ext.Direct.removeTransaction(t);
-                    }
-                }
+            if (me.minValue < 0) {
+                allowed += '-';
+            }
+            allowed = Ext.String.escapeRegex(allowed);
+            me.maskRe = new RegExp('[' + allowed + ']');
+            if (me.autoStripChars) {
+                me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
             }
         }
     },
 
-    getCallData: function(t){
-        return {
-            action: t.action,
-            method: t.method,
-            data: t.data,
-            type: 'rpc',
-            tid: t.tid
-        };
-    },
+    
+    getErrors: function(value) {
+        var me = this,
+            errors = me.callParent(arguments),
+            format = Ext.String.format,
+            num;
 
-    doSend : function(data){
-        var o = {
-            url: this.url,
-            callback: this.onData,
-            scope: this,
-            ts: data,
-            timeout: this.timeout
-        }, callData;
+        value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
 
-        if(Ext.isArray(data)){
-            callData = [];
-            for(var i = 0, len = data.length; i < len; i++){
-                callData.push(this.getCallData(data[i]));
-            }
-        }else{
-            callData = this.getCallData(data);
+        if (value.length < 1) { 
+             return errors;
         }
 
-        if(this.enableUrlEncode){
-            var params = {};
-            params[Ext.isString(this.enableUrlEncode) ? this.enableUrlEncode : 'data'] = Ext.encode(callData);
-            o.params = params;
-        }else{
-            o.jsonData = callData;
-        }
-        Ext.Ajax.request(o);
-    },
+        value = String(value).replace(me.decimalSeparator, '.');
 
-    combineAndSend : function(){
-        var len = this.callBuffer.length;
-        if(len > 0){
-            this.doSend(len == 1 ? this.callBuffer[0] : this.callBuffer);
-            this.callBuffer = [];
+        if(isNaN(value)){
+            errors.push(format(me.nanText, value));
         }
-    },
 
-    queueTransaction: function(t){
-        if(t.form){
-            this.processForm(t);
-            return;
+        num = me.parseValue(value);
+
+        if (me.minValue === 0 && num < 0) {
+            errors.push(this.negativeText);
         }
-        this.callBuffer.push(t);
-        if(this.enableBuffer){
-            if(!this.callTask){
-                this.callTask = new Ext.util.DelayedTask(this.combineAndSend, this);
-            }
-            this.callTask.delay(Ext.isNumber(this.enableBuffer) ? this.enableBuffer : 10);
-        }else{
-            this.combineAndSend();
+        else if (num < me.minValue) {
+            errors.push(format(me.minText, me.minValue));
         }
-    },
-
-    doCall : function(c, m, args){
-        var data = null, hs = args[m.len], scope = args[m.len+1];
 
-        if(m.len !== 0){
-            data = args.slice(0, m.len);
+        if (num > me.maxValue) {
+            errors.push(format(me.maxText, me.maxValue));
         }
 
-        var t = new Ext.Direct.Transaction({
-            provider: this,
-            args: args,
-            action: c,
-            method: m.name,
-            data: data,
-            cb: scope && Ext.isFunction(hs) ? hs.createDelegate(scope) : hs
-        });
 
-        if(this.fireEvent('beforecall', this, t, m) !== false){
-            Ext.Direct.addTransaction(t);
-            this.queueTransaction(t);
-            this.fireEvent('call', this, t, m);
-        }
+        return errors;
     },
 
-    doForm : function(c, m, form, callback, scope){
-        var t = new Ext.Direct.Transaction({
-            provider: this,
-            action: c,
-            method: m.name,
-            args:[form, callback, scope],
-            cb: scope && Ext.isFunction(callback) ? callback.createDelegate(scope) : callback,
-            isForm: true
-        });
-
-        if(this.fireEvent('beforecall', this, t, m) !== false){
-            Ext.Direct.addTransaction(t);
-            var isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data',
-                params = {
-                    extTID: t.tid,
-                    extAction: c,
-                    extMethod: m.name,
-                    extType: 'rpc',
-                    extUpload: String(isUpload)
-                };
-            
-            
-            
-            Ext.apply(t, {
-                form: Ext.getDom(form),
-                isUpload: isUpload,
-                params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
-            });
-            this.fireEvent('call', this, t, m);
-            this.processForm(t);
+    rawToValue: function(rawValue) {
+        var value = this.fixPrecision(this.parseValue(rawValue));
+        if (value === null) {
+            value = rawValue || null;
         }
-    },
-    
-    processForm: function(t){
-        Ext.Ajax.request({
-            url: this.url,
-            params: t.params,
-            callback: this.onData,
-            scope: this,
-            form: t.form,
-            isUpload: t.isUpload,
-            ts: t
-        });
+        return  value;
     },
 
-    createMethod : function(c, m){
-        var f;
-        if(!m.formHandler){
-            f = function(){
-                this.doCall(c, m, Array.prototype.slice.call(arguments, 0));
-            }.createDelegate(this);
-        }else{
-            f = function(form, callback, scope){
-                this.doForm(c, m, form, callback, scope);
-            }.createDelegate(this);
-        }
-        f.directCfg = {
-            action: c,
-            method: m
-        };
-        return f;
+    valueToRaw: function(value) {
+        var me = this,
+            decimalSeparator = me.decimalSeparator;
+        value = me.parseValue(value);
+        value = me.fixPrecision(value);
+        value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
+        value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
+        return value;
     },
 
-    getTransaction: function(opt){
-        return opt && opt.tid ? Ext.Direct.getTransaction(opt.tid) : null;
+    onChange: function() {
+        var me = this,
+            value = me.getValue(),
+            valueIsNull = value === null;
+
+        me.callParent(arguments);
+
+        
+        me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
+        me.setSpinDownEnabled(valueIsNull || value > me.minValue);
     },
 
-    doCallback: function(t, e){
-        var fn = e.status ? 'success' : 'failure';
-        if(t && t.cb){
-            var hs = t.cb,
-                result = Ext.isDefined(e.result) ? e.result : e.data;
-            if(Ext.isFunction(hs)){
-                hs(result, e);
-            } else{
-                Ext.callback(hs[fn], hs.scope, [result, e]);
-                Ext.callback(hs.callback, hs.scope, [result, e]);
-            }
-        }
-    }
-});
-Ext.Direct.PROVIDERS['remoting'] = Ext.direct.RemotingProvider;
-Ext.Resizable = Ext.extend(Ext.util.Observable, {
+    
+    setMinValue : function(value) {
+        this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
+    },
 
-    constructor: function(el, config){
-        this.el = Ext.get(el);
-        if(config && config.wrap){
-            config.resizeChild = this.el;
-            this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : {cls:'xresizable-wrap'});
-            this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap';
-            this.el.setStyle('overflow', 'hidden');
-            this.el.setPositioning(config.resizeChild.getPositioning());
-            config.resizeChild.clearPositioning();
-            if(!config.width || !config.height){
-                var csize = config.resizeChild.getSize();
-                this.el.setSize(csize.width, csize.height);
-            }
-            if(config.pinned && !config.adjustments){
-                config.adjustments = 'auto';
-            }
-        }
+    
+    setMaxValue: function(value) {
+        this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
+    },
 
-        
-        this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
-        this.proxy.unselectable();
-        this.proxy.enableDisplayMode('block');
+    
+    parseValue : function(value) {
+        value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
+        return isNaN(value) ? null : value;
+    },
 
-        Ext.apply(this, config);
+    
+    fixPrecision : function(value) {
+        var me = this,
+            nan = isNaN(value),
+            precision = me.decimalPrecision;
 
-        if(this.pinned){
-            this.disableTrackOver = true;
-            this.el.addClass('x-resizable-pinned');
-        }
-        
-        var position = this.el.getStyle('position');
-        if(position != 'absolute' && position != 'fixed'){
-            this.el.setStyle('position', 'relative');
+        if (nan || !value) {
+            return nan ? '' : value;
+        } else if (!me.allowDecimals || precision <= 0) {
+            precision = 0;
         }
-        if(!this.handles){ 
-            this.handles = 's,e,se';
-            if(this.multiDirectional){
-                this.handles += ',n,w';
-            }
-        }
-        if(this.handles == 'all'){
-            this.handles = 'n s e w ne nw se sw';
-        }
-        var hs = this.handles.split(/\s*?[,;]\s*?| /);
-        var ps = Ext.Resizable.positions;
-        for(var i = 0, len = hs.length; i < len; i++){
-            if(hs[i] && ps[hs[i]]){
-                var pos = ps[hs[i]];
-                this[pos] = new Ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent, this.handleCls);
-            }
-        }
-        
-        this.corner = this.southeast;
 
-        if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
-            this.updateBox = true;
-        }
+        return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
+    },
 
-        this.activeHandle = null;
+    beforeBlur : function() {
+        var me = this,
+            v = me.parseValue(me.getRawValue());
 
-        if(this.resizeChild){
-            if(typeof this.resizeChild == 'boolean'){
-                this.resizeChild = Ext.get(this.el.dom.firstChild, true);
-            }else{
-                this.resizeChild = Ext.get(this.resizeChild, true);
-            }
+        if (!Ext.isEmpty(v)) {
+            me.setValue(v);
         }
+    },
 
-        if(this.adjustments == 'auto'){
-            var rc = this.resizeChild;
-            var hw = this.west, he = this.east, hn = this.north, hs = this.south;
-            if(rc && (hw || hn)){
-                rc.position('relative');
-                rc.setLeft(hw ? hw.el.getWidth() : 0);
-                rc.setTop(hn ? hn.el.getHeight() : 0);
-            }
-            this.adjustments = [
-                (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
-                (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
-            ];
+    onSpinUp: function() {
+        var me = this;
+        if (!me.readOnly) {
+            me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
         }
+    },
 
-        if(this.draggable){
-            this.dd = this.dynamic ?
-                this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
-            this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
-            if(this.constrainTo){
-                this.dd.constrainTo(this.constrainTo);
-            }
+    onSpinDown: function() {
+        var me = this;
+        if (!me.readOnly) {
+            me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
         }
+    }
+});
 
-        this.addEvents(
-            
-            'beforeresize',
-            
-            'resize'
-        );
-
-        if(this.width !== null && this.height !== null){
-            this.resizeTo(this.width, this.height);
-        }else{
-            this.updateChildSize();
-        }
-        if(Ext.isIE){
-            this.el.dom.style.zoom = 1;
-        }
-        Ext.Resizable.superclass.constructor.call(this);
-    },
 
+Ext.define('Ext.toolbar.Paging', {
+    extend: 'Ext.toolbar.Toolbar',
+    alias: 'widget.pagingtoolbar',
+    alternateClassName: 'Ext.PagingToolbar',
+    requires: ['Ext.toolbar.TextItem', 'Ext.form.field.Number'],
     
-    adjustments : [0, 0],
-    
-    animate : false,
-    
-    
-    disableTrackOver : false,
-    
-    draggable: false,
-    
-    duration : 0.35,
-    
-    dynamic : false,
-    
-    easing : 'easeOutStrong',
-    
-    enabled : true,
-    
-    
-    handles : false,
-    
-    multiDirectional : false,
-    
-    height : null,
-    
-    width : null,
-    
-    heightIncrement : 0,
-    
-    widthIncrement : 0,
-    
-    minHeight : 5,
-    
-    minWidth : 5,
+
     
-    maxHeight : 10000,
+    displayInfo: false,
+
     
-    maxWidth : 10000,
+    prependButtons: false,
+
     
-    minX: 0,
+    displayMsg : 'Displaying {0} - {1} of {2}',
+
     
-    minY: 0,
+    emptyMsg : 'No data to display',
+
     
-    pinned : false,
+    beforePageText : 'Page',
+
     
-    preserveRatio : false,
+    afterPageText : 'of {0}',
+
     
-    resizeChild : false,
+    firstText : 'First Page',
+
     
-    transparent: false,
+    prevText : 'Previous Page',
+
     
+    nextText : 'Next Page',
+
     
+    lastText : 'Last Page',
+
     
+    refreshText : 'Refresh',
 
+    
+    inputItemWidth : 30,
 
     
-    resizeTo : function(width, height){
-        this.el.setSize(width, height);
-        this.updateChildSize();
-        this.fireEvent('resize', this, width, height, null);
+    getPagingItems: function() {
+        var me = this;
+
+        return [{
+            itemId: 'first',
+            tooltip: me.firstText,
+            overflowText: me.firstText,
+            iconCls: Ext.baseCSSPrefix + 'tbar-page-first',
+            disabled: true,
+            handler: me.moveFirst,
+            scope: me
+        },{
+            itemId: 'prev',
+            tooltip: me.prevText,
+            overflowText: me.prevText,
+            iconCls: Ext.baseCSSPrefix + 'tbar-page-prev',
+            disabled: true,
+            handler: me.movePrevious,
+            scope: me
+        },
+        '-',
+        me.beforePageText,
+        {
+            xtype: 'numberfield',
+            itemId: 'inputItem',
+            name: 'inputItem',
+            cls: Ext.baseCSSPrefix + 'tbar-page-number',
+            allowDecimals: false,
+            minValue: 1,
+            hideTrigger: true,
+            enableKeyEvents: true,
+            selectOnFocus: true,
+            submitValue: false,
+            width: me.inputItemWidth,
+            margins: '-1 2 3 2',
+            listeners: {
+                scope: me,
+                keydown: me.onPagingKeyDown,
+                blur: me.onPagingBlur
+            }
+        },{
+            xtype: 'tbtext',
+            itemId: 'afterTextItem',
+            text: Ext.String.format(me.afterPageText, 1)
+        },
+        '-',
+        {
+            itemId: 'next',
+            tooltip: me.nextText,
+            overflowText: me.nextText,
+            iconCls: Ext.baseCSSPrefix + 'tbar-page-next',
+            disabled: true,
+            handler: me.moveNext,
+            scope: me
+        },{
+            itemId: 'last',
+            tooltip: me.lastText,
+            overflowText: me.lastText,
+            iconCls: Ext.baseCSSPrefix + 'tbar-page-last',
+            disabled: true,
+            handler: me.moveLast,
+            scope: me
+        },
+        '-',
+        {
+            itemId: 'refresh',
+            tooltip: me.refreshText,
+            overflowText: me.refreshText,
+            iconCls: Ext.baseCSSPrefix + 'tbar-loading',
+            handler: me.doRefresh,
+            scope: me
+        }];
     },
 
-    
-    startSizing : function(e, handle){
-        this.fireEvent('beforeresize', this, e);
-        if(this.enabled){ 
+    initComponent : function(){
+        var me = this,
+            pagingItems = me.getPagingItems(),
+            userItems   = me.items || me.buttons || [];
 
-            if(!this.overlay){
-                this.overlay = this.el.createProxy({tag: 'div', cls: 'x-resizable-overlay', html: '&#160;'}, Ext.getBody());
-                this.overlay.unselectable();
-                this.overlay.enableDisplayMode('block');
-                this.overlay.on({
-                    scope: this,
-                    mousemove: this.onMouseMove,
-                    mouseup: this.onMouseUp
-                });
-            }
-            this.overlay.setStyle('cursor', handle.el.getStyle('cursor'));
+        if (me.prependButtons) {
+            me.items = userItems.concat(pagingItems);
+        } else {
+            me.items = pagingItems.concat(userItems);
+        }
+        delete me.buttons;
 
-            this.resizing = true;
-            this.startBox = this.el.getBox();
-            this.startPoint = e.getXY();
-            this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
-                            (this.startBox.y + this.startBox.height) - this.startPoint[1]];
+        if (me.displayInfo) {
+            me.items.push('->');
+            me.items.push({xtype: 'tbtext', itemId: 'displayItem'});
+        }
 
-            this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
-            this.overlay.show();
+        me.callParent();
 
-            if(this.constrainTo) {
-                var ct = Ext.get(this.constrainTo);
-                this.resizeRegion = ct.getRegion().adjust(
-                    ct.getFrameWidth('t'),
-                    ct.getFrameWidth('l'),
-                    -ct.getFrameWidth('b'),
-                    -ct.getFrameWidth('r')
-                );
-            }
+        me.addEvents(
+            
+            'change',
+
+            
+            'beforechange'
+        );
+        me.on('afterlayout', me.onLoad, me, {single: true});
 
-            this.proxy.setStyle('visibility', 'hidden'); 
-            this.proxy.show();
-            this.proxy.setBox(this.startBox);
-            if(!this.dynamic){
-                this.proxy.setStyle('visibility', 'visible');
+        me.bindStore(me.store || 'ext-empty-store', true);
+    },
+    
+    updateInfo : function(){
+        var me = this,
+            displayItem = me.child('#displayItem'),
+            store = me.store,
+            pageData = me.getPageData(),
+            count, msg;
+
+        if (displayItem) {
+            count = store.getCount();
+            if (count === 0) {
+                msg = me.emptyMsg;
+            } else {
+                msg = Ext.String.format(
+                    me.displayMsg,
+                    pageData.fromRecord,
+                    pageData.toRecord,
+                    pageData.total
+                );
             }
+            displayItem.setText(msg);
+            me.doComponentLayout();
         }
     },
 
     
-    onMouseDown : function(handle, e){
-        if(this.enabled){
-            e.stopEvent();
-            this.activeHandle = handle;
-            this.startSizing(e, handle);
+    onLoad : function(){
+        var me = this,
+            pageData,
+            currPage,
+            pageCount,
+            afterText;
+
+        if (!me.rendered) {
+            return;
         }
+
+        pageData = me.getPageData();
+        currPage = pageData.currentPage;
+        pageCount = pageData.pageCount;
+        afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
+
+        me.child('#afterTextItem').setText(afterText);
+        me.child('#inputItem').setValue(currPage);
+        me.child('#first').setDisabled(currPage === 1);
+        me.child('#prev').setDisabled(currPage === 1);
+        me.child('#next').setDisabled(currPage === pageCount);
+        me.child('#last').setDisabled(currPage === pageCount);
+        me.child('#refresh').enable();
+        me.updateInfo();
+        me.fireEvent('change', me, pageData);
     },
 
     
-    onMouseUp : function(e){
-        this.activeHandle = null;
-        var size = this.resizeElement();
-        this.resizing = false;
-        this.handleOut();
-        this.overlay.hide();
-        this.proxy.hide();
-        this.fireEvent('resize', this, size.width, size.height, e);
+    getPageData : function(){
+        var store = this.store,
+            totalCount = store.getTotalCount();
+
+        return {
+            total : totalCount,
+            currentPage : store.currentPage,
+            pageCount: Math.ceil(totalCount / store.pageSize),
+            fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
+            toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
+
+        };
     },
 
     
-    updateChildSize : function(){
-        if(this.resizeChild){
-            var el = this.el;
-            var child = this.resizeChild;
-            var adj = this.adjustments;
-            if(el.dom.offsetWidth){
-                var b = el.getSize(true);
-                child.setSize(b.width+adj[0], b.height+adj[1]);
-            }
-            
-            
-            
-            
-            if(Ext.isIE){
-                setTimeout(function(){
-                    if(el.dom.offsetWidth){
-                        var b = el.getSize(true);
-                        child.setSize(b.width+adj[0], b.height+adj[1]);
-                    }
-                }, 10);
-            }
+    onLoadError : function(){
+        if (!this.rendered) {
+            return;
         }
+        this.child('#refresh').enable();
     },
 
     
-    snap : function(value, inc, min){
-        if(!inc || !value){
-            return value;
-        }
-        var newValue = value;
-        var m = value % inc;
-        if(m > 0){
-            if(m > (inc/2)){
-                newValue = value + (inc-m);
-            }else{
-                newValue = value - m;
-            }
+    readPageFromInput : function(pageData){
+        var v = this.child('#inputItem').getValue(),
+            pageNum = parseInt(v, 10);
+
+        if (!v || isNaN(pageNum)) {
+            this.child('#inputItem').setValue(pageData.currentPage);
+            return false;
         }
-        return Math.max(min, newValue);
+        return pageNum;
     },
 
-    
-    resizeElement : function(){
-        var box = this.proxy.getBox();
-        if(this.updateBox){
-            this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
-        }else{
-            this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
-        }
-        this.updateChildSize();
-        if(!this.dynamic){
-            this.proxy.hide();
-        }
-        if(this.draggable && this.constrainTo){
-            this.dd.resetConstraints();
-            this.dd.constrainTo(this.constrainTo);
-        }
-        return box;
+    onPagingFocus : function(){
+        this.child('#inputItem').select();
     },
 
     
-    constrain : function(v, diff, m, mx){
-        if(v - diff < m){
-            diff = v - m;
-        }else if(v - diff > mx){
-            diff = v - mx;
-        }
-        return diff;
+    onPagingBlur : function(e){
+        var curPage = this.getPageData().currentPage;
+        this.child('#inputItem').setValue(curPage);
     },
 
     
-    onMouseMove : function(e){
-        if(this.enabled && this.activeHandle){
-            try{
-
-            if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
-                return;
-            }
+    onPagingKeyDown : function(field, e){
+        var me = this,
+            k = e.getKey(),
+            pageData = me.getPageData(),
+            increment = e.shiftKey ? 10 : 1,
+            pageNum;
 
-            
-            var curSize = this.curSize || this.startBox,
-                x = this.startBox.x, y = this.startBox.y,
-                ox = x,
-                oy = y,
-                w = curSize.width,
-                h = curSize.height,
-                ow = w,
-                oh = h,
-                mw = this.minWidth,
-                mh = this.minHeight,
-                mxw = this.maxWidth,
-                mxh = this.maxHeight,
-                wi = this.widthIncrement,
-                hi = this.heightIncrement,
-                eventXY = e.getXY(),
-                diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
-                diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
-                pos = this.activeHandle.position,
-                tw,
-                th;
-
-            switch(pos){
-                case 'east':
-                    w += diffX;
-                    w = Math.min(Math.max(mw, w), mxw);
-                    break;
-                case 'south':
-                    h += diffY;
-                    h = Math.min(Math.max(mh, h), mxh);
-                    break;
-                case 'southeast':
-                    w += diffX;
-                    h += diffY;
-                    w = Math.min(Math.max(mw, w), mxw);
-                    h = Math.min(Math.max(mh, h), mxh);
-                    break;
-                case 'north':
-                    diffY = this.constrain(h, diffY, mh, mxh);
-                    y += diffY;
-                    h -= diffY;
-                    break;
-                case 'west':
-                    diffX = this.constrain(w, diffX, mw, mxw);
-                    x += diffX;
-                    w -= diffX;
-                    break;
-                case 'northeast':
-                    w += diffX;
-                    w = Math.min(Math.max(mw, w), mxw);
-                    diffY = this.constrain(h, diffY, mh, mxh);
-                    y += diffY;
-                    h -= diffY;
-                    break;
-                case 'northwest':
-                    diffX = this.constrain(w, diffX, mw, mxw);
-                    diffY = this.constrain(h, diffY, mh, mxh);
-                    y += diffY;
-                    h -= diffY;
-                    x += diffX;
-                    w -= diffX;
-                    break;
-               case 'southwest':
-                    diffX = this.constrain(w, diffX, mw, mxw);
-                    h += diffY;
-                    h = Math.min(Math.max(mh, h), mxh);
-                    x += diffX;
-                    w -= diffX;
-                    break;
+        if (k == e.RETURN) {
+            e.stopEvent();
+            pageNum = me.readPageFromInput(pageData);
+            if (pageNum !== false) {
+                pageNum = Math.min(Math.max(1, pageNum), pageData.pageCount);
+                if(me.fireEvent('beforechange', me, pageNum) !== false){
+                    me.store.loadPage(pageNum);
+                }
             }
-
-            var sw = this.snap(w, wi, mw);
-            var sh = this.snap(h, hi, mh);
-            if(sw != w || sh != h){
-                switch(pos){
-                    case 'northeast':
-                        y -= sh - h;
-                    break;
-                    case 'north':
-                        y -= sh - h;
-                        break;
-                    case 'southwest':
-                        x -= sw - w;
-                    break;
-                    case 'west':
-                        x -= sw - w;
-                        break;
-                    case 'northwest':
-                        x -= sw - w;
-                        y -= sh - h;
-                    break;
+        } else if (k == e.HOME || k == e.END) {
+            e.stopEvent();
+            pageNum = k == e.HOME ? 1 : pageData.pageCount;
+            field.setValue(pageNum);
+        } else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
+            e.stopEvent();
+            pageNum = me.readPageFromInput(pageData);
+            if (pageNum) {
+                if (k == e.DOWN || k == e.PAGEDOWN) {
+                    increment *= -1;
                 }
-                w = sw;
-                h = sh;
-            }
-
-            if(this.preserveRatio){
-                switch(pos){
-                    case 'southeast':
-                    case 'east':
-                        h = oh * (w/ow);
-                        h = Math.min(Math.max(mh, h), mxh);
-                        w = ow * (h/oh);
-                       break;
-                    case 'south':
-                        w = ow * (h/oh);
-                        w = Math.min(Math.max(mw, w), mxw);
-                        h = oh * (w/ow);
-                        break;
-                    case 'northeast':
-                        w = ow * (h/oh);
-                        w = Math.min(Math.max(mw, w), mxw);
-                        h = oh * (w/ow);
-                    break;
-                    case 'north':
-                        tw = w;
-                        w = ow * (h/oh);
-                        w = Math.min(Math.max(mw, w), mxw);
-                        h = oh * (w/ow);
-                        x += (tw - w) / 2;
-                        break;
-                    case 'southwest':
-                        h = oh * (w/ow);
-                        h = Math.min(Math.max(mh, h), mxh);
-                        tw = w;
-                        w = ow * (h/oh);
-                        x += tw - w;
-                        break;
-                    case 'west':
-                        th = h;
-                        h = oh * (w/ow);
-                        h = Math.min(Math.max(mh, h), mxh);
-                        y += (th - h) / 2;
-                        tw = w;
-                        w = ow * (h/oh);
-                        x += tw - w;
-                       break;
-                    case 'northwest':
-                        tw = w;
-                        th = h;
-                        h = oh * (w/ow);
-                        h = Math.min(Math.max(mh, h), mxh);
-                        w = ow * (h/oh);
-                        y += th - h;
-                        x += tw - w;
-                        break;
-
+                pageNum += increment;
+                if (pageNum >= 1 && pageNum <= pageData.pages) {
+                    field.setValue(pageNum);
                 }
             }
-            this.proxy.setBounds(x, y, w, h);
-            if(this.dynamic){
-                this.resizeElement();
-            }
-            }catch(ex){}
         }
     },
 
     
-    handleOver : function(){
-        if(this.enabled){
-            this.el.addClass('x-resizable-over');
+    beforeLoad : function(){
+        if(this.rendered && this.refresh){
+            this.refresh.disable();
         }
     },
 
     
-    handleOut : function(){
-        if(!this.resizing){
-            this.el.removeClass('x-resizable-over');
+    doLoad : function(start){
+        if(this.fireEvent('beforechange', this, o) !== false){
+            this.store.load();
         }
     },
 
     
-    getEl : function(){
-        return this.el;
+    moveFirst : function(){
+        if (this.fireEvent('beforechange', this, 1) !== false){
+            this.store.loadPage(1);
+        }
     },
 
     
-    getResizeChild : function(){
-        return this.resizeChild;
+    movePrevious : function(){
+        var me = this,
+            prev = me.store.currentPage - 1;
+
+        if (prev > 0) {
+            if (me.fireEvent('beforechange', me, prev) !== false) {
+                me.store.previousPage();
+            }
+        }
     },
 
     
-    destroy : function(removeEl){
-        Ext.destroy(this.dd, this.overlay, this.proxy);
-        this.overlay = null;
-        this.proxy = null;
+    moveNext : function(){
+        var me = this,
+            total = me.getPageData().pageCount,
+            next = me.store.currentPage + 1;
 
-        var ps = Ext.Resizable.positions;
-        for(var k in ps){
-            if(typeof ps[k] != 'function' && this[ps[k]]){
-                this[ps[k]].destroy();
+        if (next <= total) {
+            if (me.fireEvent('beforechange', me, next) !== false) {
+                me.store.nextPage();
             }
         }
-        if(removeEl){
-            this.el.update('');
-            Ext.destroy(this.el);
-            this.el = null;
-        }
-        this.purgeListeners();
     },
 
-    syncHandleHeight : function(){
-        var h = this.el.getHeight(true);
-        if(this.west){
-            this.west.el.setHeight(h);
-        }
-        if(this.east){
-            this.east.el.setHeight(h);
+    
+    moveLast : function(){
+        var me = this,
+            last = me.getPageData().pageCount;
+
+        if (me.fireEvent('beforechange', me, last) !== false) {
+            me.store.loadPage(last);
         }
-    }
-});
+    },
 
+    
+    doRefresh : function(){
+        var me = this,
+            current = me.store.currentPage;
 
+        if (me.fireEvent('beforechange', me, current) !== false) {
+            me.store.loadPage(current);
+        }
+    },
 
-Ext.Resizable.positions = {
-    n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
-};
+    
+    bindStore : function(store, initial){
+        var me = this;
 
-Ext.Resizable.Handle = Ext.extend(Object, {
-    constructor : function(rz, pos, disableTrackOver, transparent, cls){
-       if(!this.tpl){
-            
-            var tpl = Ext.DomHelper.createTemplate(
-                {tag: 'div', cls: 'x-resizable-handle x-resizable-handle-{0}'}
-            );
-            tpl.compile();
-            Ext.Resizable.Handle.prototype.tpl = tpl;
-        }
-        this.position = pos;
-        this.rz = rz;
-        this.el = this.tpl.append(rz.el.dom, [this.position], true);
-        this.el.unselectable();
-        if(transparent){
-            this.el.setOpacity(0);
-        }
-        if(!Ext.isEmpty(cls)){
-            this.el.addClass(cls);
+        if (!initial && me.store) {
+            if(store !== me.store && me.store.autoDestroy){
+                me.store.destroyStore();
+            }else{
+                me.store.un('beforeload', me.beforeLoad, me);
+                me.store.un('load', me.onLoad, me);
+                me.store.un('exception', me.onLoadError, me);
+            }
+            if(!store){
+                me.store = null;
+            }
         }
-        this.el.on('mousedown', this.onMouseDown, this);
-        if(!disableTrackOver){
-            this.el.on({
-                scope: this,
-                mouseover: this.onMouseOver,
-                mouseout: this.onMouseOut
+        if (store) {
+            store = Ext.data.StoreManager.lookup(store);
+            store.on({
+                scope: me,
+                beforeload: me.beforeLoad,
+                load: me.onLoad,
+                exception: me.onLoadError
             });
         }
+        me.store = store;
     },
 
     
-    afterResize : function(rz){
-        
-    },
-    
-    onMouseDown : function(e){
-        this.rz.onMouseDown(this, e);
-    },
-    
-    onMouseOver : function(e){
-        this.rz.handleOver(this, e);
+    unbind : function(store){
+        this.bindStore(null);
     },
+
     
-    onMouseOut : function(e){
-        this.rz.handleOut(this, e);
+    bind : function(store){
+        this.bindStore(store);
     },
+
     
-    destroy : function(){
-        Ext.destroy(this.el);
-        this.el = null;
+    onDestroy : function(){
+        this.bindStore(null);
+        this.callParent();
     }
 });
 
-Ext.Window = Ext.extend(Ext.Panel, {
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-
-    
-    baseCls : 'x-window',
-    
-    resizable : true,
-    
-    draggable : true,
-    
-    closable : true,
-    
-    closeAction : 'close',
-    
-    constrain : false,
-    
-    constrainHeader : false,
-    
-    plain : false,
-    
-    minimizable : false,
-    
-    maximizable : false,
-    
-    minHeight : 100,
-    
-    minWidth : 200,
-    
-    expandOnShow : true,
-
-    
-    collapsible : false,
-
-    
-    initHidden : undefined,
-
-    
-    hidden : true,
-
-    
-    
-    
-    
-    
-    elements : 'header,body',
-    
-    frame : true,
-    
-    floating : true,
 
-    
-    initComponent : function(){
-        this.initTools();
-        Ext.Window.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            
-            
-            'resize',
-            
-            'maximize',
-            
-            'minimize',
-            
-            'restore'
-        );
-        
-        if(Ext.isDefined(this.initHidden)){
-            this.hidden = this.initHidden;
-        }
-        if(this.hidden === false){
-            this.hidden = true;
-            this.show();
-        }
-    },
+Ext.define('Ext.view.BoundList', {
+    extend: 'Ext.view.View',
+    alias: 'widget.boundlist',
+    alternateClassName: 'Ext.BoundList',
+    requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],
 
     
-    getState : function(){
-        return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
-    },
+    pageSize: 0,
 
     
-    onRender : function(ct, position){
-        Ext.Window.superclass.onRender.call(this, ct, position);
-
-        if(this.plain){
-            this.el.addClass('x-window-plain');
-        }
-
-        
-        this.focusEl = this.el.createChild({
-                    tag: 'a', href:'#', cls:'x-dlg-focus',
-                    tabIndex:'-1', html: '&#160;'});
-        this.focusEl.swallowEvent('click', true);
-
-        this.proxy = this.el.createProxy('x-window-proxy');
-        this.proxy.enableDisplayMode('block');
-
-        if(this.modal){
-            this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
-            this.mask.enableDisplayMode('block');
-            this.mask.hide();
-            this.mon(this.mask, 'click', this.focus, this);
-        }
-        if(this.maximizable){
-            this.mon(this.header, 'dblclick', this.toggleMaximize, this);
-        }
-    },
 
     
-    initEvents : function(){
-        Ext.Window.superclass.initEvents.call(this);
-        if(this.animateTarget){
-            this.setAnimateTarget(this.animateTarget);
-        }
-
-        if(this.resizable){
-            this.resizer = new Ext.Resizable(this.el, {
-                minWidth: this.minWidth,
-                minHeight:this.minHeight,
-                handles: this.resizeHandles || 'all',
-                pinned: true,
-                resizeElement : this.resizerAction,
-                handleCls: 'x-window-handle'
-            });
-            this.resizer.window = this;
-            this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
-        }
+    autoScroll: true,
+    baseCls: Ext.baseCSSPrefix + 'boundlist',
+    itemCls: Ext.baseCSSPrefix + 'boundlist-item',
+    listItemCls: '',
+    shadow: false,
+    trackOver: true,
+    refreshed: 0,
 
-        if(this.draggable){
-            this.header.addClass('x-window-draggable');
-        }
-        this.mon(this.el, 'mousedown', this.toFront, this);
-        this.manager = this.manager || Ext.WindowMgr;
-        this.manager.register(this);
-        if(this.maximized){
-            this.maximized = false;
-            this.maximize();
-        }
-        if(this.closable){
-            var km = this.getKeyMap();
-            km.on(27, this.onEsc, this);
-            km.disable();
-        }
-    },
+    ariaRole: 'listbox',
 
-    initDraggable : function(){
-        
-        this.dd = new Ext.Window.DD(this);
-    },
+    componentLayout: 'boundlist',
 
-   
-    onEsc : function(k, e){
-        e.stopEvent();
-        this[this.closeAction]();
-    },
+    renderTpl: ['<div id="{id}-listEl" class="list-ct"></div>'],
 
-    
-    beforeDestroy : function(){
-        if(this.rendered){
-            this.hide();
-            this.clearAnchor();
-            Ext.destroy(
-                this.focusEl,
-                this.resizer,
-                this.dd,
-                this.proxy,
-                this.mask
-            );
-        }
-        Ext.Window.superclass.beforeDestroy.call(this);
-    },
+    initComponent: function() {
+        var me = this,
+            baseCls = me.baseCls,
+            itemCls = me.itemCls;
+            
+        me.selectedItemCls = baseCls + '-selected';
+        me.overItemCls = baseCls + '-item-over';
+        me.itemSelector = "." + itemCls;
 
-    
-    onDestroy : function(){
-        if(this.manager){
-            this.manager.unregister(this);
+        if (me.floating) {
+            me.addCls(baseCls + '-floating');
         }
-        Ext.Window.superclass.onDestroy.call(this);
-    },
 
-    
-    initTools : function(){
-        if(this.minimizable){
-            this.addTool({
-                id: 'minimize',
-                handler: this.minimize.createDelegate(this, [])
-            });
-        }
-        if(this.maximizable){
-            this.addTool({
-                id: 'maximize',
-                handler: this.maximize.createDelegate(this, [])
-            });
-            this.addTool({
-                id: 'restore',
-                handler: this.restore.createDelegate(this, []),
-                hidden:true
-            });
+        if (!me.tpl) {
+            
+            
+            me.tpl = Ext.create('Ext.XTemplate',
+                '<ul><tpl for=".">',
+                    '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
+                '</tpl></ul>'
+            );
+        } else if (Ext.isString(me.tpl)) {
+            me.tpl = Ext.create('Ext.XTemplate', me.tpl);
         }
-        if(this.closable){
-            this.addTool({
-                id: 'close',
-                handler: this[this.closeAction].createDelegate(this, [])
-            });
+
+        if (me.pageSize) {
+            me.pagingToolbar = me.createPagingToolbar();
         }
-    },
 
-    
-    resizerAction : function(){
-        var box = this.proxy.getBox();
-        this.proxy.hide();
-        this.window.handleResize(box);
-        return box;
+        me.callParent();
+
+        me.addChildEls('listEl');
     },
 
-    
-    beforeResize : function(){
-        this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); 
-        this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
-        this.resizeBox = this.el.getBox();
+    createPagingToolbar: function() {
+        return Ext.widget('pagingtoolbar', {
+            pageSize: this.pageSize,
+            store: this.store,
+            border: false
+        });
     },
 
-    
-    updateHandles : function(){
-        if(Ext.isIE && this.resizer){
-            this.resizer.syncHandleHeight();
-            this.el.repaint();
+    onRender: function() {
+        var me = this,
+            toolbar = me.pagingToolbar;
+        me.callParent(arguments);
+        if (toolbar) {
+            toolbar.render(me.el);
         }
     },
 
-    
-    handleResize : function(box){
-        var rz = this.resizeBox;
-        if(rz.x != box.x || rz.y != box.y){
-            this.updateBox(box);
-        }else{
-            this.setSize(box);
-            if (Ext.isIE6 && Ext.isStrict) {
-                this.doLayout();
-            }
+    bindStore : function(store, initial) {
+        var me = this,
+            toolbar = me.pagingToolbar;
+        me.callParent(arguments);
+        if (toolbar) {
+            toolbar.bindStore(store, initial);
         }
-        this.focus();
-        this.updateHandles();
-        this.saveState();
     },
 
-    
-    focus : function(){
-        var f = this.focusEl,
-            db = this.defaultButton,
-            t = typeof db,
-            el,
-            ct;
-        if(Ext.isDefined(db)){
-            if(Ext.isNumber(db) && this.fbar){
-                f = this.fbar.items.get(db);
-            }else if(Ext.isString(db)){
-                f = Ext.getCmp(db);
-            }else{
-                f = db;
-            }
-            el = f.getEl();
-            ct = Ext.getDom(this.container);
-            if (el && ct) {
-                if (!Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
-                    return;
-                }
-            }
-        }
-        f = f || this.focusEl;
-        f.focus.defer(10, f);
+    getTargetEl: function() {
+        return this.listEl || this.el;
     },
 
-    
-    setAnimateTarget : function(el){
-        el = Ext.get(el);
-        this.animateTarget = el;
+    getInnerTpl: function(displayField) {
+        return '{' + displayField + '}';
     },
 
-    
-    beforeShow : function(){
-        delete this.el.lastXY;
-        delete this.el.lastLT;
-        if(this.x === undefined || this.y === undefined){
-            var xy = this.el.getAlignToXY(this.container, 'c-c');
-            var pos = this.el.translatePoints(xy[0], xy[1]);
-            this.x = this.x === undefined? pos.left : this.x;
-            this.y = this.y === undefined? pos.top : this.y;
+    refresh: function() {
+        var me = this;
+        me.callParent();
+        if (me.isVisible()) {
+            me.refreshed++;
+            me.doComponentLayout();
+            me.refreshed--;
         }
-        this.el.setLeftTop(this.x, this.y);
+    },
 
-        if(this.expandOnShow){
-            this.expand(false);
-        }
+    initAria: function() {
+        this.callParent();
 
-        if(this.modal){
-            Ext.getBody().addClass('x-body-masked');
-            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
-            this.mask.show();
-        }
-    },
+        var selModel = this.getSelectionModel(),
+            mode     = selModel.getSelectionMode(),
+            actionEl = this.getActionEl();
 
-    
-    show : function(animateTarget, cb, scope){
-        if(!this.rendered){
-            this.render(Ext.getBody());
-        }
-        if(this.hidden === false){
-            this.toFront();
-            return this;
-        }
-        if(this.fireEvent('beforeshow', this) === false){
-            return this;
-        }
-        if(cb){
-            this.on('show', cb, scope, {single:true});
-        }
-        this.hidden = false;
-        if(Ext.isDefined(animateTarget)){
-            this.setAnimateTarget(animateTarget);
-        }
-        this.beforeShow();
-        if(this.animateTarget){
-            this.animShow();
-        }else{
-            this.afterShow();
+        
+        if (mode !== 'SINGLE') {
+            actionEl.dom.setAttribute('aria-multiselectable', true);
         }
-        return this;
     },
 
-    
-    afterShow : function(isAnim){
-        if (this.isDestroyed){
-            return false;
-        }
-        this.proxy.hide();
-        this.el.setStyle('display', 'block');
-        this.el.show();
-        if(this.maximized){
-            this.fitContainer();
-        }
-        if(Ext.isMac && Ext.isGecko2){ 
-            this.cascade(this.setAutoScroll);
-        }
+    onDestroy: function() {
+        Ext.destroyMembers(this, 'pagingToolbar', 'listEl');
+        this.callParent();
+    }
+});
 
-        if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
-            Ext.EventManager.onWindowResize(this.onWindowResize, this);
-        }
-        this.doConstrain();
-        this.doLayout();
-        if(this.keyMap){
-            this.keyMap.enable();
-        }
-        this.toFront();
-        this.updateHandles();
-        if(isAnim && (Ext.isIE || Ext.isWebKit)){
-            var sz = this.getSize();
-            this.onResize(sz.width, sz.height);
-        }
-        this.onShow();
-        this.fireEvent('show', this);
-    },
+
+Ext.define('Ext.view.BoundListKeyNav', {
+    extend: 'Ext.util.KeyNav',
+    requires: 'Ext.view.BoundList',
 
     
-    animShow : function(){
-        this.proxy.show();
-        this.proxy.setBox(this.animateTarget.getBox());
-        this.proxy.setOpacity(0);
-        var b = this.getBox();
-        this.el.setStyle('display', 'none');
-        this.proxy.shift(Ext.apply(b, {
-            callback: this.afterShow.createDelegate(this, [true], false),
-            scope: this,
-            easing: 'easeNone',
-            duration: 0.25,
-            opacity: 0.5
-        }));
+
+    constructor: function(el, config) {
+        var me = this;
+        me.boundList = config.boundList;
+        me.callParent([el, Ext.apply({}, config, me.defaultHandlers)]);
     },
 
-    
-    hide : function(animateTarget, cb, scope){
-        if(this.hidden || this.fireEvent('beforehide', this) === false){
-            return this;
-        }
-        if(cb){
-            this.on('hide', cb, scope, {single:true});
-        }
-        this.hidden = true;
-        if(animateTarget !== undefined){
-            this.setAnimateTarget(animateTarget);
-        }
-        if(this.modal){
-            this.mask.hide();
-            Ext.getBody().removeClass('x-body-masked');
-        }
-        if(this.animateTarget){
-            this.animHide();
-        }else{
-            this.el.hide();
-            this.afterHide();
+    defaultHandlers: {
+        up: function() {
+            var me = this,
+                boundList = me.boundList,
+                allItems = boundList.all,
+                oldItem = boundList.highlightedItem,
+                oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
+                newItemIdx = oldItemIdx > 0 ? oldItemIdx - 1 : allItems.getCount() - 1; 
+            me.highlightAt(newItemIdx);
+        },
+
+        down: function() {
+            var me = this,
+                boundList = me.boundList,
+                allItems = boundList.all,
+                oldItem = boundList.highlightedItem,
+                oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
+                newItemIdx = oldItemIdx < allItems.getCount() - 1 ? oldItemIdx + 1 : 0; 
+            me.highlightAt(newItemIdx);
+        },
+
+        pageup: function() {
+            
+        },
+
+        pagedown: function() {
+            
+        },
+
+        home: function() {
+            this.highlightAt(0);
+        },
+
+        end: function() {
+            var me = this;
+            me.highlightAt(me.boundList.all.getCount() - 1);
+        },
+
+        enter: function(e) {
+            this.selectHighlighted(e);
         }
-        return this;
     },
 
     
-    afterHide : function(){
-        this.proxy.hide();
-        if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
-            Ext.EventManager.removeResizeListener(this.onWindowResize, this);
-        }
-        if(this.keyMap){
-            this.keyMap.disable();
+    highlightAt: function(index) {
+        var boundList = this.boundList,
+            item = boundList.all.item(index);
+        if (item) {
+            item = item.dom;
+            boundList.highlightItem(item);
+            boundList.getTargetEl().scrollChildIntoView(item, false);
         }
-        this.onHide();
-        this.fireEvent('hide', this);
     },
 
     
-    animHide : function(){
-        this.proxy.setOpacity(0.5);
-        this.proxy.show();
-        var tb = this.getBox(false);
-        this.proxy.setBox(tb);
-        this.el.hide();
-        this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
-            callback: this.afterHide,
-            scope: this,
-            duration: 0.25,
-            easing: 'easeNone',
-            opacity: 0
-        }));
-    },
+    selectHighlighted: function(e) {
+        var me = this,
+            boundList = me.boundList,
+            highlighted = boundList.highlightedItem,
+            selModel = boundList.getSelectionModel();
+        if (highlighted) {
+            selModel.selectWithEvent(boundList.getRecord(highlighted), e);
+        }
+    }
 
-    
-    onShow : Ext.emptyFn,
+});
 
-    
-    onHide : Ext.emptyFn,
+Ext.define('Ext.form.field.ComboBox', {
+    extend:'Ext.form.field.Picker',
+    requires: ['Ext.util.DelayedTask', 'Ext.EventObject', 'Ext.view.BoundList', 'Ext.view.BoundListKeyNav', 'Ext.data.StoreManager'],
+    alternateClassName: 'Ext.form.ComboBox',
+    alias: ['widget.combobox', 'widget.combo'],
 
     
-    onWindowResize : function(){
-        if(this.maximized){
-            this.fitContainer();
-        }
-        if(this.modal){
-            this.mask.setSize('100%', '100%');
-            var force = this.mask.dom.offsetHeight;
-            this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
-        }
-        this.doConstrain();
-    },
+    triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
 
     
-    doConstrain : function(){
-        if(this.constrain || this.constrainHeader){
-            var offsets;
-            if(this.constrain){
-                offsets = {
-                    right:this.el.shadowOffset,
-                    left:this.el.shadowOffset,
-                    bottom:this.el.shadowOffset
-                };
-            }else {
-                var s = this.getSize();
-                offsets = {
-                    right:-(s.width - 100),
-                    bottom:-(s.height - 25)
-                };
-            }
+    hiddenDataCls: Ext.baseCSSPrefix + 'hide-display ' + Ext.baseCSSPrefix + 'form-data-hidden',
 
-            var xy = this.el.getConstrainToXY(this.container, true, offsets);
-            if(xy){
-                this.setPosition(xy[0], xy[1]);
-            }
+    
+    fieldSubTpl: [
+        '<div class="{hiddenDataCls}" role="presentation"></div>',
+        '<input id="{id}" type="{type}" ',
+            '<tpl if="size">size="{size}" </tpl>',
+            '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
+            'class="{fieldCls} {typeCls}" autocomplete="off" />',
+        '<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
+            '{triggerEl}',
+            '<div class="{clearCls}" role="presentation"></div>',
+        '</div>',
+        {
+            compiled: true,
+            disableFormats: true
         }
+    ],
+
+    getSubTplData: function(){
+        var me = this;
+        Ext.applyIf(me.subTplData, {
+            hiddenDataCls: me.hiddenDataCls
+        });
+        return me.callParent(arguments);
     },
 
-    
-    ghost : function(cls){
-        var ghost = this.createGhost(cls);
-        var box = this.getBox(true);
-        ghost.setLeftTop(box.x, box.y);
-        ghost.setWidth(box.width);
-        this.el.hide();
-        this.activeGhost = ghost;
-        return ghost;
+    afterRender: function(){
+        var me = this;
+        me.callParent(arguments);
+        me.setHiddenValue(me.value);
     },
 
     
-    unghost : function(show, matchPosition){
-        if(!this.activeGhost) {
-            return;
-        }
-        if(show !== false){
-            this.el.show();
-            this.focus.defer(10, this);
-            if(Ext.isMac && Ext.isGecko2){ 
-                this.cascade(this.setAutoScroll);
-            }
-        }
-        if(matchPosition !== false){
-            this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
-        }
-        this.activeGhost.hide();
-        this.activeGhost.remove();
-        delete this.activeGhost;
-    },
 
     
-    minimize : function(){
-        this.fireEvent('minimize', this);
-        return this;
-    },
+    multiSelect: false,
 
     
-    close : function(){
-        if(this.fireEvent('beforeclose', this) !== false){
-            if(this.hidden){
-                this.doClose();
-            }else{
-                this.hide(null, this.doClose, this);
-            }
-        }
-    },
+    delimiter: ', ',
 
     
-    doClose : function(){
-        this.fireEvent('close', this);
-        this.destroy();
-    },
+    displayField: 'text',
 
     
-    maximize : function(){
-        if(!this.maximized){
-            this.expand(false);
-            this.restoreSize = this.getSize();
-            this.restorePos = this.getPosition(true);
-            if (this.maximizable){
-                this.tools.maximize.hide();
-                this.tools.restore.show();
-            }
-            this.maximized = true;
-            this.el.disableShadow();
 
-            if(this.dd){
-                this.dd.lock();
-            }
-            if(this.collapsible){
-                this.tools.toggle.hide();
-            }
-            this.el.addClass('x-window-maximized');
-            this.container.addClass('x-window-maximized-ct');
+    
+    triggerAction: 'all',
 
-            this.setPosition(0, 0);
-            this.fitContainer();
-            this.fireEvent('maximize', this);
-        }
-        return this;
-    },
+    
+    allQuery: '',
 
     
-    restore : function(){
-        if(this.maximized){
-            var t = this.tools;
-            this.el.removeClass('x-window-maximized');
-            if(t.restore){
-                t.restore.hide();
-            }
-            if(t.maximize){
-                t.maximize.show();
-            }
-            this.setPosition(this.restorePos[0], this.restorePos[1]);
-            this.setSize(this.restoreSize.width, this.restoreSize.height);
-            delete this.restorePos;
-            delete this.restoreSize;
-            this.maximized = false;
-            this.el.enableShadow(true);
+    queryParam: 'query',
 
-            if(this.dd){
-                this.dd.unlock();
-            }
-            if(this.collapsible && t.toggle){
-                t.toggle.show();
-            }
-            this.container.removeClass('x-window-maximized-ct');
+    
+    queryMode: 'remote',
 
-            this.doConstrain();
-            this.fireEvent('restore', this);
-        }
-        return this;
-    },
+    queryCaching: true,
 
     
-    toggleMaximize : function(){
-        return this[this.maximized ? 'restore' : 'maximize']();
-    },
+    pageSize: 0,
 
     
-    fitContainer : function(){
-        var vs = this.container.getViewSize(false);
-        this.setSize(vs.width, vs.height);
-    },
 
     
-    
-    setZIndex : function(index){
-        if(this.modal){
-            this.mask.setStyle('z-index', index);
-        }
-        this.el.setZIndex(++index);
-        index += 5;
-
-        if(this.resizer){
-            this.resizer.proxy.setStyle('z-index', ++index);
-        }
-
-        this.lastZIndex = index;
-    },
 
     
-    alignTo : function(element, position, offsets){
-        var xy = this.el.getAlignToXY(element, position, offsets);
-        this.setPagePosition(xy[0], xy[1]);
-        return this;
-    },
+    autoSelect: true,
 
     
-    anchorTo : function(el, alignment, offsets, monitorScroll){
-        this.clearAnchor();
-        this.anchorTarget = {
-            el: el,
-            alignment: alignment,
-            offsets: offsets
-        };
+    typeAhead: false,
 
-        Ext.EventManager.onWindowResize(this.doAnchor, this);
-        var tm = typeof monitorScroll;
-        if(tm != 'undefined'){
-            Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
-                {buffer: tm == 'number' ? monitorScroll : 50});
-        }
-        return this.doAnchor();
-    },
+    
+    typeAheadDelay: 250,
 
     
-    doAnchor : function(){
-        var o = this.anchorTarget;
-        this.alignTo(o.el, o.alignment, o.offsets);
-        return this;
-    },
+    selectOnTab: true,
 
     
-    clearAnchor : function(){
-        if(this.anchorTarget){
-            Ext.EventManager.removeResizeListener(this.doAnchor, this);
-            Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
-            delete this.anchorTarget;
-        }
-        return this;
-    },
+    forceSelection: false,
 
     
-    toFront : function(e){
-        if(this.manager.bringToFront(this)){
-            if(!e || !e.getTarget().focus){
-                this.focus();
-            }
-        }
-        return this;
-    },
 
     
-    setActive : function(active){
-        if(active){
-            if(!this.maximized){
-                this.el.enableShadow(true);
-            }
-            this.fireEvent('activate', this);
-        }else{
-            this.el.disableShadow();
-            this.fireEvent('deactivate', this);
-        }
-    },
 
     
-    toBack : function(){
-        this.manager.sendToBack(this);
-        return this;
+    defaultListConfig: {
+        emptyText: '',
+        loadingText: 'Loading...',
+        loadingHeight: 70,
+        minWidth: 70,
+        maxHeight: 300,
+        shadow: 'sides'
     },
 
     
-    center : function(){
-        var xy = this.el.getAlignToXY(this.container, 'c-c');
-        this.setPagePosition(xy[0], xy[1]);
-        return this;
-    }
 
     
-});
-Ext.reg('window', Ext.Window);
 
+    
+    ignoreSelection: 0,
 
-Ext.Window.DD = function(win){
-    this.win = win;
-    Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
-    this.setHandleElId(win.header.id);
-    this.scroll = false;
-};
+    initComponent: function() {
+        var me = this,
+            isDefined = Ext.isDefined,
+            store = me.store,
+            transform = me.transform,
+            transformSelect, isLocalMode;
 
-Ext.extend(Ext.Window.DD, Ext.dd.DD, {
-    moveOnly:true,
-    headerOffsets:[100, 25],
-    startDrag : function(){
-        var w = this.win;
-        this.proxy = w.ghost();
-        if(w.constrain !== false){
-            var so = w.el.shadowOffset;
-            this.constrainTo(w.container, {right: so, left: so, bottom: so});
-        }else if(w.constrainHeader !== false){
-            var s = this.proxy.getSize();
-            this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
-        }
-    },
-    b4Drag : Ext.emptyFn,
+        Ext.applyIf(me.renderSelectors, {
+            hiddenDataEl: '.' + me.hiddenDataCls.split(' ').join('.')
+        });
+        
 
-    onDrag : function(e){
-        this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
-    },
+        this.addEvents(
+            
+            'beforequery',
 
-    endDrag : function(e){
-        this.win.unghost();
-        this.win.saveState();
-    }
-});
+            
+            'select',
 
-Ext.WindowGroup = function(){
-    var list = {};
-    var accessList = [];
-    var front = null;
+            
+            'beforeselect',
 
-    
-    var sortWindows = function(d1, d2){
-        return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
-    };
+            
+            'beforedeselect'
+        );
 
-    
-    var orderWindows = function(){
-        var a = accessList, len = a.length;
-        if(len > 0){
-            a.sort(sortWindows);
-            var seed = a[0].manager.zseed;
-            for(var i = 0; i < len; i++){
-                var win = a[i];
-                if(win && !win.hidden){
-                    win.setZIndex(seed + (i*10));
+        
+        if (transform) {
+            transformSelect = Ext.getDom(transform);
+            if (transformSelect) {
+                store = Ext.Array.map(Ext.Array.from(transformSelect.options), function(option) {
+                    return [option.value, option.text];
+                });
+                if (!me.name) {
+                    me.name = transformSelect.name;
+                }
+                if (!('value' in me)) {
+                    me.value = transformSelect.value;
                 }
             }
         }
-        activateLast();
-    };
 
-    
-    var setActiveWin = function(win){
-        if(win != front){
-            if(front){
-                front.setActive(false);
-            }
-            front = win;
-            if(win){
-                win.setActive(true);
+        me.bindStore(store || 'ext-empty-store', true);
+        store = me.store;
+        if (store.autoCreated) {
+            me.queryMode = 'local';
+            me.valueField = me.displayField = 'field1';
+            if (!store.expanded) {
+                me.displayField = 'field2';
             }
         }
-    };
 
-    
-    var activateLast = function(){
-        for(var i = accessList.length-1; i >=0; --i) {
-            if(!accessList[i].hidden){
-                setActiveWin(accessList[i]);
-                return;
-            }
+
+        if (!isDefined(me.valueField)) {
+            me.valueField = me.displayField;
         }
-        
-        setActiveWin(null);
-    };
 
-    return {
-        
-        zseed : 9000,
+        isLocalMode = me.queryMode === 'local';
+        if (!isDefined(me.queryDelay)) {
+            me.queryDelay = isLocalMode ? 10 : 500;
+        }
+        if (!isDefined(me.minChars)) {
+            me.minChars = isLocalMode ? 0 : 4;
+        }
 
-        
-        register : function(win){
-            if(win.manager){
-                win.manager.unregister(win);
-            }
-            win.manager = this;
+        if (!me.displayTpl) {
+            me.displayTpl = Ext.create('Ext.XTemplate',
+                '<tpl for=".">' +
+                    '{[typeof values === "string" ? values : values["' + me.displayField + '"]]}' +
+                    '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
+                '</tpl>'
+            );
+        } else if (Ext.isString(me.displayTpl)) {
+            me.displayTpl = Ext.create('Ext.XTemplate', me.displayTpl);
+        }
 
-            list[win.id] = win;
-            accessList.push(win);
-            win.on('hide', activateLast);
-        },
+        me.callParent();
 
-        
-        unregister : function(win){
-            delete win.manager;
-            delete list[win.id];
-            win.un('hide', activateLast);
-            accessList.remove(win);
-        },
+        me.doQueryTask = Ext.create('Ext.util.DelayedTask', me.doRawQuery, me);
 
         
-        get : function(id){
-            return typeof id == "object" ? id : list[id];
-        },
+        if (me.store.getCount() > 0) {
+            me.setValue(me.value);
+        }
 
         
-        bringToFront : function(win){
-            win = this.get(win);
-            if(win != front){
-                win._lastAccess = new Date().getTime();
-                orderWindows();
-                return true;
-            }
-            return false;
-        },
+        if (transformSelect) {
+            me.render(transformSelect.parentNode, transformSelect);
+            Ext.removeNode(transformSelect);
+            delete me.renderTo;
+        }
+    },
 
-        
-        sendToBack : function(win){
-            win = this.get(win);
-            win._lastAccess = -(new Date().getTime());
-            orderWindows();
-            return win;
-        },
+    
+    getStore : function(){
+        return this.store;
+    },
 
-        
-        hideAll : function(){
-            for(var id in list){
-                if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
-                    list[id].hide();
-                }
-            }
-        },
+    beforeBlur: function() {
+        this.doQueryTask.cancel();
+        this.assertValue();
+    },
 
-        
-        getActive : function(){
-            return front;
-        },
+    
+    assertValue: function() {
+        var me = this,
+            value = me.getRawValue(),
+            rec;
 
-        
-        getBy : function(fn, scope){
-            var r = [];
-            for(var i = accessList.length-1; i >=0; --i) {
-                var win = accessList[i];
-                if(fn.call(scope||win, win) !== false){
-                    r.push(win);
+        if (me.forceSelection) {
+            if (me.multiSelect) {
+                
+                
+                if (value !== me.getDisplayValue()) {
+                    me.setValue(me.lastSelection);
                 }
-            }
-            return r;
-        },
-
-        
-        each : function(fn, scope){
-            for(var id in list){
-                if(list[id] && typeof list[id] != "function"){
-                    if(fn.call(scope || list[id], list[id]) === false){
-                        return;
-                    }
+            } else {
+                
+                
+                rec = me.findRecordByDisplay(value);
+                if (rec) {
+                    me.select(rec);
+                } else {
+                    me.setValue(me.lastSelection);
                 }
             }
         }
-    };
-};
+        me.collapse();
+    },
 
+    onTypeAhead: function() {
+        var me = this,
+            displayField = me.displayField,
+            record = me.store.findRecord(displayField, me.getRawValue()),
+            boundList = me.getPicker(),
+            newValue, len, selStart;
 
+        if (record) {
+            newValue = record.get(displayField);
+            len = newValue.length;
+            selStart = me.getRawValue().length;
 
-Ext.WindowMgr = new Ext.WindowGroup();
-Ext.MessageBox = function(){
-    var dlg, opt, mask, waitTimer,
-        bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
-        buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
-        buttonNames = ['ok', 'yes', 'no', 'cancel'];
+            boundList.highlightItem(boundList.getNode(record));
 
-    
-    var handleButton = function(button){
-        buttons[button].blur();
-        if(dlg.isVisible()){
-            dlg.hide();
-            handleHide();
-            Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
+            if (selStart !== 0 && selStart !== len) {
+                me.setRawValue(newValue);
+                me.selectText(selStart, newValue.length);
+            }
         }
-    };
+    },
 
     
-    var handleHide = function(){
-        if(opt && opt.cls){
-            dlg.el.removeClass(opt.cls);
-        }
-        progressBar.reset();        
-    };
-
     
-    var handleEsc = function(d, k, e){
-        if(opt && opt.closable !== false){
-            dlg.hide();
-            handleHide();
-        }
-        if(e){
-            e.stopEvent();
-        }
-    };
+    resetToDefault: function() {
 
-    
-    var updateButtons = function(b){
-        var width = 0,
-            cfg;
-        if(!b){
-            Ext.each(buttonNames, function(name){
-                buttons[name].hide();
-            });
-            return width;
-        }
-        dlg.footer.dom.style.display = '';
-        Ext.iterate(buttons, function(name, btn){
-            cfg = b[name];
-            if(cfg){
-                btn.show();
-                btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
-                width += btn.getEl().getWidth() + 15;
-            }else{
-                btn.hide();
-            }
-        });
-        return width;
-    };
+    },
+
+    bindStore: function(store, initial) {
+        var me = this,
+            oldStore = me.store;
 
-    return {
         
-        getDialog : function(titleText){
-           if(!dlg){
-                var btns = [];
-                
-                buttons = {};
-                Ext.each(buttonNames, function(name){
-                    btns.push(buttons[name] = new Ext.Button({
-                        text: this.buttonText[name],
-                        handler: handleButton.createCallback(name),
-                        hideMode: 'offsets'
-                    }));
-                }, this);
-                dlg = new Ext.Window({
-                    autoCreate : true,
-                    title:titleText,
-                    resizable:false,
-                    constrain:true,
-                    constrainHeader:true,
-                    minimizable : false,
-                    maximizable : false,
-                    stateful: false,
-                    modal: true,
-                    shim:true,
-                    buttonAlign:"center",
-                    width:400,
-                    height:100,
-                    minHeight: 80,
-                    plain:true,
-                    footer:true,
-                    closable:true,
-                    close : function(){
-                        if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
-                            handleButton("no");
-                        }else{
-                            handleButton("cancel");
-                        }
-                    },
-                    fbar: new Ext.Toolbar({
-                        items: btns,
-                        enableOverflow: false
-                    })
-                });
-                dlg.render(document.body);
-                dlg.getEl().addClass('x-window-dlg');
-                mask = dlg.mask;
-                bodyEl = dlg.body.createChild({
-                    html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
-                });
-                iconEl = Ext.get(bodyEl.dom.firstChild);
-                var contentEl = bodyEl.dom.childNodes[1];
-                msgEl = Ext.get(contentEl.firstChild);
-                textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
-                textboxEl.enableDisplayMode();
-                textboxEl.addKeyListener([10,13], function(){
-                    if(dlg.isVisible() && opt && opt.buttons){
-                        if(opt.buttons.ok){
-                            handleButton("ok");
-                        }else if(opt.buttons.yes){
-                            handleButton("yes");
-                        }
-                    }
-                });
-                textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
-                textareaEl.enableDisplayMode();
-                progressBar = new Ext.ProgressBar({
-                    renderTo:bodyEl
+        
+        if (oldStore && !initial) {
+            if (oldStore !== store && oldStore.autoDestroy) {
+                oldStore.destroyStore();
+            } else {
+                oldStore.un({
+                    scope: me,
+                    load: me.onLoad,
+                    exception: me.collapse
                 });
-               bodyEl.createChild({cls:'x-clear'});
             }
-            return dlg;
-        },
+            if (!store) {
+                me.store = null;
+                if (me.picker) {
+                    me.picker.bindStore(null);
+                }
+            }
+        }
+        if (store) {
+            if (!initial) {
+                me.resetToDefault();
+            }
 
-        
-        updateText : function(text){
-            if(!dlg.isVisible() && !opt.width){
-                dlg.setSize(this.maxWidth, 100); 
+            me.store = Ext.data.StoreManager.lookup(store);
+            me.store.on({
+                scope: me,
+                load: me.onLoad,
+                exception: me.collapse
+            });
+
+            if (me.picker) {
+                me.picker.bindStore(store);
             }
-            msgEl.update(text || '&#160;');
+        }
+    },
 
-            var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
-                mw = msgEl.getWidth() + msgEl.getMargins('lr'),
-                fw = dlg.getFrameWidth('lr'),
-                bw = dlg.body.getFrameWidth('lr'),
-                w;
-                
-            if (Ext.isIE && iw > 0){
+    onLoad: function() {
+        var me = this,
+            value = me.value;
+
+        
+        if (me.rawQuery) {
+            me.rawQuery = false;
+            me.syncSelection();
+            if (me.picker && !me.picker.getSelectionModel().hasSelection()) {
+                me.doAutoSelect();
+            }
+        }
+        
+        else {
+            
+            if (me.value) {
+                me.setValue(me.value);
+            } else {
                 
                 
-                iw += 3;
+                if (me.store.getCount()) {
+                    me.doAutoSelect();
+                } else {
+                    me.setValue('');
+                }
             }
-            w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
-                    Math.max(opt.minWidth || this.minWidth, bwidth || 0));
+        }
+    },
 
-            if(opt.prompt === true){
-                activeTextEl.setWidth(w-iw-fw-bw);
-            }
-            if(opt.progress === true || opt.wait === true){
-                progressBar.setSize(w-iw-fw-bw);
-            }
-            if(Ext.isIE && w == bwidth){
-                w += 4; 
-            }
-            dlg.setSize(w, 'auto').center();
-            return this;
-        },
+    
+    doRawQuery: function() {
+        this.doQuery(this.getRawValue(), false, true);
+    },
+
+    
+    doQuery: function(queryString, forceAll, rawQuery) {
+        queryString = queryString || '';
 
         
-        updateProgress : function(value, progressText, msg){
-            progressBar.updateProgress(value, progressText);
-            if(msg){
-                this.updateText(msg);
-            }
-            return this;
-        },
+        
+        var me = this,
+            qe = {
+                query: queryString,
+                forceAll: forceAll,
+                combo: me,
+                cancel: false
+            },
+            store = me.store,
+            isLocalMode = me.queryMode === 'local';
+
+        if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
+            return false;
+        }
 
         
-        isVisible : function(){
-            return dlg && dlg.isVisible();
-        },
+        queryString = qe.query;
+        forceAll = qe.forceAll;
 
         
-        hide : function(){
-            var proxy = dlg ? dlg.activeGhost : null;
-            if(this.isVisible() || proxy){
-                dlg.hide();
-                handleHide();
-                if (proxy){
+        if (forceAll || (queryString.length >= me.minChars)) {
+            
+            me.expand();
+
+            
+            if (!me.queryCaching || me.lastQuery !== queryString) {
+                me.lastQuery = queryString;
+
+                if (isLocalMode) {
                     
+                    if (forceAll) {
+                        store.clearFilter();
+                    } else {
+                        
+                        store.clearFilter(true);
+                        store.filter(me.displayField, queryString);
+                    }
+                } else {
                     
-                    dlg.unghost(false, false);
-                } 
-            }
-            return this;
-        },
+                    me.rawQuery = rawQuery;
 
-        
-        show : function(options){
-            if(this.isVisible()){
-                this.hide();
-            }
-            opt = options;
-            var d = this.getDialog(opt.title || "&#160;");
-
-            d.setTitle(opt.title || "&#160;");
-            var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
-            d.tools.close.setDisplayed(allowClose);
-            activeTextEl = textboxEl;
-            opt.prompt = opt.prompt || (opt.multiline ? true : false);
-            if(opt.prompt){
-                if(opt.multiline){
-                    textboxEl.hide();
-                    textareaEl.show();
-                    textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
-                    activeTextEl = textareaEl;
-                }else{
-                    textboxEl.show();
-                    textareaEl.hide();
-                }
-            }else{
-                textboxEl.hide();
-                textareaEl.hide();
-            }
-            activeTextEl.dom.value = opt.value || "";
-            if(opt.prompt){
-                d.focusEl = activeTextEl;
-            }else{
-                var bs = opt.buttons;
-                var db = null;
-                if(bs && bs.ok){
-                    db = buttons["ok"];
-                }else if(bs && bs.yes){
-                    db = buttons["yes"];
-                }
-                if (db){
-                    d.focusEl = db;
-                }
-            }
-            if(Ext.isDefined(opt.iconCls)){
-              d.setIconClass(opt.iconCls);
-            }
-            this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
-            bwidth = updateButtons(opt.buttons);
-            progressBar.setVisible(opt.progress === true || opt.wait === true);
-            this.updateProgress(0, opt.progressText);
-            this.updateText(opt.msg);
-            if(opt.cls){
-                d.el.addClass(opt.cls);
-            }
-            d.proxyDrag = opt.proxyDrag === true;
-            d.modal = opt.modal !== false;
-            d.mask = opt.modal !== false ? mask : false;
-            if(!d.isVisible()){
-                
-                document.body.appendChild(dlg.el.dom);
-                d.setAnimateTarget(opt.animEl);
-                
-                d.on('show', function(){
-                    if(allowClose === true){
-                        d.keyMap.enable();
-                    }else{
-                        d.keyMap.disable();
+                    
+                    
+                    if (me.pageSize) {
+                        
+                        me.loadPage(1);
+                    } else {
+                        store.load({
+                            params: me.getParams(queryString)
+                        });
                     }
-                }, this, {single:true});
-                d.show(opt.animEl);
+                }
             }
-            if(opt.wait === true){
-                progressBar.wait(opt.waitConfig);
+
+            
+            if (me.getRawValue() !== me.getDisplayValue()) {
+                me.ignoreSelection++;
+                me.picker.getSelectionModel().deselectAll();
+                me.ignoreSelection--;
             }
-            return this;
-        },
 
-        
-        setIcon : function(icon){
-            if(!dlg){
-                bufferIcon = icon;
-                return;
+            if (isLocalMode) {
+                me.doAutoSelect();
             }
-            bufferIcon = undefined;
-            if(icon && icon != ''){
-                iconEl.removeClass('x-hidden');
-                iconEl.replaceClass(iconCls, icon);
-                bodyEl.addClass('x-dlg-icon');
-                iconCls = icon;
-            }else{
-                iconEl.replaceClass(iconCls, 'x-hidden');
-                bodyEl.removeClass('x-dlg-icon');
-                iconCls = '';
+            if (me.typeAhead) {
+                me.doTypeAhead();
             }
-            return this;
-        },
+        }
+        return true;
+    },
 
-        
-        progress : function(title, msg, progressText){
-            this.show({
-                title : title,
-                msg : msg,
-                buttons: false,
-                progress:true,
-                closable:false,
-                minWidth: this.minProgressWidth,
-                progressText: progressText
-            });
-            return this;
-        },
+    loadPage: function(pageNum){
+        this.store.loadPage(pageNum, {
+            params: this.getParams(this.lastQuery)
+        });
+    },
 
+    onPageChange: function(toolbar, newPage){
         
-        wait : function(msg, title, config){
-            this.show({
-                title : title,
-                msg : msg,
-                buttons: false,
-                closable:false,
-                wait:true,
-                modal:true,
-                minWidth: this.minProgressWidth,
-                waitConfig: config
-            });
-            return this;
-        },
+        this.loadPage(newPage);
+        return false;
+    },
 
-        
-        alert : function(title, msg, fn, scope){
-            this.show({
-                title : title,
-                msg : msg,
-                buttons: this.OK,
-                fn: fn,
-                scope : scope,
-                minWidth: this.minWidth
-            });
-            return this;
-        },
+    
+    getParams: function(queryString) {
+        var params = {},
+            param = this.queryParam;
 
-        
-        confirm : function(title, msg, fn, scope){
-            this.show({
-                title : title,
-                msg : msg,
-                buttons: this.YESNO,
-                fn: fn,
-                scope : scope,
-                icon: this.QUESTION,
-                minWidth: this.minWidth
-            });
-            return this;
-        },
+        if (param) {
+            params[param] = queryString;
+        }
+        return params;
+    },
 
-        
-        prompt : function(title, msg, fn, scope, multiline, value){
-            this.show({
-                title : title,
-                msg : msg,
-                buttons: this.OKCANCEL,
-                fn: fn,
-                minWidth: this.minPromptWidth,
-                scope : scope,
-                prompt:true,
-                multiline: multiline,
-                value: value
-            });
-            return this;
-        },
+    
+    doAutoSelect: function() {
+        var me = this,
+            picker = me.picker,
+            lastSelected, itemNode;
+        if (picker && me.autoSelect && me.store.getCount() > 0) {
+            
+            lastSelected = picker.getSelectionModel().lastSelected;
+            itemNode = picker.getNode(lastSelected || 0);
+            if (itemNode) {
+                picker.highlightItem(itemNode);
+                picker.listEl.scrollChildIntoView(itemNode, false);
+            }
+        }
+    },
 
-        
-        OK : {ok:true},
-        
-        CANCEL : {cancel:true},
-        
-        OKCANCEL : {ok:true, cancel:true},
-        
-        YESNO : {yes:true, no:true},
-        
-        YESNOCANCEL : {yes:true, no:true, cancel:true},
-        
-        INFO : 'ext-mb-info',
-        
-        WARNING : 'ext-mb-warning',
-        
-        QUESTION : 'ext-mb-question',
-        
-        ERROR : 'ext-mb-error',
+    doTypeAhead: function() {
+        if (!this.typeAheadTask) {
+            this.typeAheadTask = Ext.create('Ext.util.DelayedTask', this.onTypeAhead, this);
+        }
+        if (this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
+            this.typeAheadTask.delay(this.typeAheadDelay);
+        }
+    },
 
-        
-        defaultTextHeight : 75,
-        
-        maxWidth : 600,
-        
-        minWidth : 100,
-        
-        minProgressWidth : 250,
-        
-        minPromptWidth: 250,
-        
-        buttonText : {
-            ok : "OK",
-            cancel : "Cancel",
-            yes : "Yes",
-            no : "No"
+    onTriggerClick: function() {
+        var me = this;
+        if (!me.readOnly && !me.disabled) {
+            if (me.isExpanded) {
+                me.collapse();
+            } else {
+                me.onFocus({});
+                if (me.triggerAction === 'all') {
+                    me.doQuery(me.allQuery, true);
+                } else {
+                    me.doQuery(me.getRawValue(), false, true);
+                }
+            }
+            me.inputEl.focus();
+        }
+    },
+
+
+    
+    onKeyUp: function(e, t) {
+        var me = this,
+            key = e.getKey();
+
+        if (!me.readOnly && !me.disabled && me.editable) {
+            me.lastKey = key;
+            
+            
+
+            
+            if (!e.isSpecialKey() || key == e.BACKSPACE || key == e.DELETE) {
+                me.doQueryTask.delay(me.queryDelay);
+            }
         }
-    };
-}();
 
+        if (me.enableKeyEvents) {
+            me.callParent(arguments);
+        }
+    },
 
-Ext.Msg = Ext.MessageBox;
-Ext.dd.PanelProxy = function(panel, config){
-    this.panel = panel;
-    this.id = this.panel.id +'-ddproxy';
-    Ext.apply(this, config);
-};
+    initEvents: function() {
+        var me = this;
+        me.callParent();
 
-Ext.dd.PanelProxy.prototype = {
+        
+        if (!me.enableKeyEvents) {
+            me.mon(me.inputEl, 'keyup', me.onKeyUp, me);
+        }
+    },
     
-    insertProxy : true,
+    onDestroy: function(){
+        this.bindStore(null);
+        this.callParent();    
+    },
 
-    
-    setStatus : Ext.emptyFn,
-    reset : Ext.emptyFn,
-    update : Ext.emptyFn,
-    stop : Ext.emptyFn,
-    sync: Ext.emptyFn,
+    createPicker: function() {
+        var me = this,
+            picker,
+            menuCls = Ext.baseCSSPrefix + 'menu',
+            opts = Ext.apply({
+                pickerField: me,
+                selModel: {
+                    mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
+                },
+                floating: true,
+                hidden: true,
+                ownerCt: me.ownerCt,
+                cls: me.el.up('.' + menuCls) ? menuCls : '',
+                store: me.store,
+                displayField: me.displayField,
+                focusOnToFront: false,
+                pageSize: me.pageSize,
+                tpl: me.tpl
+            }, me.listConfig, me.defaultListConfig);
+
+        picker = me.picker = Ext.create('Ext.view.BoundList', opts);
+        if (me.pageSize) {
+            picker.pagingToolbar.on('beforechange', me.onPageChange, me);
+        }
+
+        me.mon(picker, {
+            itemclick: me.onItemClick,
+            refresh: me.onListRefresh,
+            scope: me
+        });
 
-    
-    getEl : function(){
-        return this.ghost;
+        me.mon(picker.getSelectionModel(), {
+            'beforeselect': me.onBeforeSelect,
+            'beforedeselect': me.onBeforeDeselect,
+            'selectionchange': me.onListSelectionChange,
+            scope: me
+        });
+
+        return picker;
     },
 
-    
-    getGhost : function(){
-        return this.ghost;
+    alignPicker: function(){
+        var me = this,
+            picker = me.picker,
+            heightAbove = me.getPosition()[1] - Ext.getBody().getScroll().top,
+            heightBelow = Ext.Element.getViewHeight() - heightAbove - me.getHeight(),
+            space = Math.max(heightAbove, heightBelow);
+
+        me.callParent();
+        if (picker.getHeight() > space) {
+            picker.setHeight(space - 5); 
+            me.doAlign();
+        }
     },
 
-    
-    getProxy : function(){
-        return this.proxy;
+    onListRefresh: function() {
+        this.alignPicker();
+        this.syncSelection();
     },
 
-    
-    hide : function(){
-        if(this.ghost){
-            if(this.proxy){
-                this.proxy.remove();
-                delete this.proxy;
+    onItemClick: function(picker, record){
+        
+        var me = this,
+            lastSelection = me.lastSelection,
+            valueField = me.valueField,
+            selected;
+
+        if (!me.multiSelect && lastSelection) {
+            selected = lastSelection[0];
+            if (selected && (record.get(valueField) === selected.get(valueField))) {
+                
+                me.displayTplData = [record.data];
+                me.setRawValue(me.getDisplayValue());
+                me.collapse();
             }
-            this.panel.el.dom.style.display = '';
-            this.ghost.remove();
-            delete this.ghost;
         }
     },
 
-    
-    show : function(){
-        if(!this.ghost){
-            this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
-            this.ghost.setXY(this.panel.el.getXY());
-            if(this.insertProxy){
-                this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
-                this.proxy.setSize(this.panel.getSize());
-            }
-            this.panel.el.dom.style.display = 'none';
-        }
+    onBeforeSelect: function(list, record) {
+        return this.fireEvent('beforeselect', this, record, record.index);
     },
 
-    
-    repair : function(xy, callback, scope){
-        this.hide();
-        if(typeof callback == "function"){
-            callback.call(scope || this);
+    onBeforeDeselect: function(list, record) {
+        return this.fireEvent('beforedeselect', this, record, record.index);
+    },
+
+    onListSelectionChange: function(list, selectedRecords) {
+        var me = this,
+            isMulti = me.multiSelect,
+            hasRecords = selectedRecords.length > 0;
+        
+        
+        if (!me.ignoreSelection && me.isExpanded) {
+            if (!isMulti) {
+                Ext.defer(me.collapse, 1, me);
+            }
+            
+            if (isMulti || hasRecords) {
+                me.setValue(selectedRecords, false);
+            }
+            if (hasRecords) {
+                me.fireEvent('select', me, selectedRecords);
+            }
+            me.inputEl.focus();
         }
     },
 
     
-    moveProxy : function(parentNode, before){
-        if(this.proxy){
-            parentNode.insertBefore(this.proxy.dom, before);
-        }
-    }
-};
+    onExpand: function() {
+        var me = this,
+            keyNav = me.listKeyNav,
+            selectOnTab = me.selectOnTab,
+            picker = me.getPicker();
 
+        
+        if (keyNav) {
+            keyNav.enable();
+        } else {
+            keyNav = me.listKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
+                boundList: picker,
+                forceKeyDown: true,
+                tab: function(e) {
+                    if (selectOnTab) {
+                        this.selectHighlighted(e);
+                        me.triggerBlur();
+                    }
+                    
+                    return true;
+                }
+            });
+        }
 
-Ext.Panel.DD = function(panel, cfg){
-    this.panel = panel;
-    this.dragData = {panel: panel};
-    this.proxy = new Ext.dd.PanelProxy(panel, cfg);
-    Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
-    var h = panel.header;
-    if(h){
-        this.setHandleElId(h.id);
-    }
-    (h ? h : this.panel.body).setStyle('cursor', 'move');
-    this.scroll = false;
-};
+        
+        if (selectOnTab) {
+            me.ignoreMonitorTab = true;
+        }
 
-Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
-    showFrame: Ext.emptyFn,
-    startDrag: Ext.emptyFn,
-    b4StartDrag: function(x, y) {
-        this.proxy.show();
-    },
-    b4MouseDown: function(e) {
-        var x = e.getPageX();
-        var y = e.getPageY();
-        this.autoOffset(x, y);
-    },
-    onInitDrag : function(x, y){
-        this.onStartDrag(x, y);
-        return true;
-    },
-    createFrame : Ext.emptyFn,
-    getDragEl : function(e){
-        return this.proxy.ghost.dom;
-    },
-    endDrag : function(e){
-        this.proxy.hide();
-        this.panel.saveState();
+        Ext.defer(keyNav.enable, 1, keyNav); 
+        me.inputEl.focus();
     },
 
-    autoOffset : function(x, y) {
-        x -= this.startPageX;
-        y -= this.startPageY;
-        this.setDelta(x, y);
-    }
-});
-Ext.state.Provider = Ext.extend(Ext.util.Observable, {
     
-    constructor : function(){
-        
-        this.addEvents("statechange");
-        this.state = {};
-        Ext.state.Provider.superclass.constructor.call(this);
+    onCollapse: function() {
+        var me = this,
+            keyNav = me.listKeyNav;
+        if (keyNav) {
+            keyNav.disable();
+            me.ignoreMonitorTab = false;
+        }
     },
+
     
-    
-    get : function(name, defaultValue){
-        return typeof this.state[name] == "undefined" ?
-            defaultValue : this.state[name];
+    select: function(r) {
+        this.setValue(r, true);
     },
 
     
-    clear : function(name){
-        delete this.state[name];
-        this.fireEvent("statechange", this, name, null);
+    findRecord: function(field, value) {
+        var ds = this.store,
+            idx = ds.findExact(field, value);
+        return idx !== -1 ? ds.getAt(idx) : false;
     },
 
     
-    set : function(name, value){
-        this.state[name] = value;
-        this.fireEvent("statechange", this, name, value);
+    findRecordByValue: function(value) {
+        return this.findRecord(this.valueField, value);
     },
 
     
-    decodeValue : function(cookie){
-        
-        var re = /^(a|n|d|b|s|o|e)\:(.*)$/,
-            matches = re.exec(unescape(cookie)),
-            all,
-            type,
-            v,
-            kv;
-        if(!matches || !matches[1]){
-            return; 
-        }
-        type = matches[1];
-        v = matches[2];
-        switch(type){
-            case 'e':
-                return null;
-            case 'n':
-                return parseFloat(v);
-            case 'd':
-                return new Date(Date.parse(v));
-            case 'b':
-                return (v == '1');
-            case 'a':
-                all = [];
-                if(v != ''){
-                    Ext.each(v.split('^'), function(val){
-                        all.push(this.decodeValue(val));
-                    }, this);
-                }
-                return all;
-           case 'o':
-                all = {};
-                if(v != ''){
-                    Ext.each(v.split('^'), function(val){
-                        kv = val.split('=');
-                        all[kv[0]] = this.decodeValue(kv[1]);
-                    }, this);
-                }
-                return all;
-           default:
-                return v;
-        }
+    findRecordByDisplay: function(value) {
+        return this.findRecord(this.displayField, value);
     },
 
     
-    encodeValue : function(v){
-        var enc,
-            flat = '',
-            i = 0,
-            len,
-            key;
-        if(v == null){
-            return 'e:1';    
-        }else if(typeof v == 'number'){
-            enc = 'n:' + v;
-        }else if(typeof v == 'boolean'){
-            enc = 'b:' + (v ? '1' : '0');
-        }else if(Ext.isDate(v)){
-            enc = 'd:' + v.toGMTString();
-        }else if(Ext.isArray(v)){
-            for(len = v.length; i < len; i++){
-                flat += this.encodeValue(v[i]);
-                if(i != len - 1){
-                    flat += '^';
-                }
-            }
-            enc = 'a:' + flat;
-        }else if(typeof v == 'object'){
-            for(key in v){
-                if(typeof v[key] != 'function' && v[key] !== undefined){
-                    flat += key + '=' + this.encodeValue(v[key]) + '^';
-                }
-            }
-            enc = 'o:' + flat.substring(0, flat.length-1);
-        }else{
-            enc = 's:' + v;
-        }
-        return escape(enc);
-    }
-});
+    setValue: function(value, doSelect) {
+        var me = this,
+            valueNotFoundText = me.valueNotFoundText,
+            inputEl = me.inputEl,
+            i, len, record,
+            models = [],
+            displayTplData = [],
+            processedValue = [];
 
-Ext.state.Manager = function(){
-    var provider = new Ext.state.Provider();
+        if (me.store.loading) {
+            
+            me.value = value;
+            me.setHiddenValue(me.value);
+            return me;
+        }
 
-    return {
         
-        setProvider : function(stateProvider){
-            provider = stateProvider;
-        },
+        value = Ext.Array.from(value);
 
         
-        get : function(key, defaultValue){
-            return provider.get(key, defaultValue);
-        },
+        for (i = 0, len = value.length; i < len; i++) {
+            record = value[i];
+            if (!record || !record.isModel) {
+                record = me.findRecordByValue(record);
+            }
+            
+            if (record) {
+                models.push(record);
+                displayTplData.push(record.data);
+                processedValue.push(record.get(me.valueField));
+            }
+            
+            
+            else {
+                
+                if (!me.forceSelection) {
+                    displayTplData.push(value[i]);
+                    processedValue.push(value[i]);
+                }
+                
+                else if (Ext.isDefined(valueNotFoundText)) {
+                    displayTplData.push(valueNotFoundText);
+                }
+            }
+        }
 
         
-         set : function(key, value){
-            provider.set(key, value);
-        },
+        me.setHiddenValue(processedValue);
+        me.value = me.multiSelect ? processedValue : processedValue[0];
+        if (!Ext.isDefined(me.value)) {
+            me.value = null;
+        }
+        me.displayTplData = displayTplData; 
+        me.lastSelection = me.valueModels = models;
 
-        
-        clear : function(key){
-            provider.clear(key);
-        },
+        if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
+            inputEl.removeCls(me.emptyCls);
+        }
 
         
-        getProvider : function(){
-            return provider;
+        me.setRawValue(me.getDisplayValue());
+        me.checkChange();
+
+        if (doSelect !== false) {
+            me.syncSelection();
         }
-    };
-}();
+        me.applyEmptyText();
 
-Ext.state.CookieProvider = Ext.extend(Ext.state.Provider, {
-    
-    constructor : function(config){
-        Ext.state.CookieProvider.superclass.constructor.call(this);
-        this.path = "/";
-        this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
-        this.domain = null;
-        this.secure = false;
-        Ext.apply(this, config);
-        this.state = this.readCookies();
+        return me;
     },
+
     
-    
-    set : function(name, value){
-        if(typeof value == "undefined" || value === null){
-            this.clear(name);
+    setHiddenValue: function(values){
+        var me = this, i;
+        if (!me.hiddenDataEl) {
             return;
         }
-        this.setCookie(name, value);
-        Ext.state.CookieProvider.superclass.set.call(this, name, value);
+        values = Ext.Array.from(values);
+        var dom = me.hiddenDataEl.dom,
+            childNodes = dom.childNodes,
+            input = childNodes[0],
+            valueCount = values.length,
+            childrenCount = childNodes.length;
+        
+        if (!input && valueCount > 0) {
+            me.hiddenDataEl.update(Ext.DomHelper.markup({tag:'input', type:'hidden', name:me.name}));
+            childrenCount = 1;
+            input = dom.firstChild;
+        }
+        while (childrenCount > valueCount) {
+            dom.removeChild(childNodes[0]);
+            -- childrenCount;
+        }
+        while (childrenCount < valueCount) {
+            dom.appendChild(input.cloneNode(true));
+            ++ childrenCount;
+        }
+        for (i = 0; i < valueCount; i++) {
+            childNodes[i].value = values[i];
+        }
     },
 
     
-    clear : function(name){
-        this.clearCookie(name);
-        Ext.state.CookieProvider.superclass.clear.call(this, name);
+    getDisplayValue: function() {
+        return this.displayTpl.apply(this.displayTplData);
     },
 
-    
-    readCookies : function(){
-        var cookies = {},
-            c = document.cookie + ";",
-            re = /\s?(.*?)=(.*?);/g,
-           matches,
-            name,
-            value;
-       while((matches = re.exec(c)) != null){
-            name = matches[1];
-            value = matches[2];
-            if(name && name.substring(0,3) == "ys-"){
-                cookies[name.substr(3)] = this.decodeValue(value);
+    getValue: function() {
+        
+        
+        
+        var me = this,
+            picker = me.picker,
+            rawValue = me.getRawValue(), 
+            value = me.value; 
+
+        if (me.getDisplayValue() !== rawValue) {
+            value = rawValue;
+            me.value = me.displayTplData = me.valueModels = null;
+            if (picker) {
+                me.ignoreSelection++;
+                picker.getSelectionModel().deselectAll();
+                me.ignoreSelection--;
             }
         }
-        return cookies;
+
+        return value;
+    },
+
+    getSubmitValue: function() {
+        return this.getValue();
+    },
+
+    isEqual: function(v1, v2) {
+        var fromArray = Ext.Array.from,
+            i, len;
+
+        v1 = fromArray(v1);
+        v2 = fromArray(v2);
+        len = v1.length;
+
+        if (len !== v2.length) {
+            return false;
+        }
+
+        for(i = 0; i < len; i++) {
+            if (v2[i] !== v1[i]) {
+                return false;
+            }
+        }
+
+        return true;
     },
 
     
-    setCookie : function(name, value){
-        document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
-           ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
-           ((this.path == null) ? "" : ("; path=" + this.path)) +
-           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
-           ((this.secure == true) ? "; secure" : "");
+    clearValue: function() {
+        this.setValue([]);
     },
 
     
-    clearCookie : function(name){
-        document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
-           ((this.path == null) ? "" : ("; path=" + this.path)) +
-           ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
-           ((this.secure == true) ? "; secure" : "");
+    syncSelection: function() {
+        var me = this,
+            ExtArray = Ext.Array,
+            picker = me.picker,
+            selection, selModel;
+        if (picker) {
+            
+            selection = [];
+            ExtArray.forEach(me.valueModels || [], function(value) {
+                if (value && value.isModel && me.store.indexOf(value) >= 0) {
+                    selection.push(value);
+                }
+            });
+
+            
+            me.ignoreSelection++;
+            selModel = picker.getSelectionModel();
+            selModel.deselectAll();
+            if (selection.length) {
+                selModel.select(selection);
+            }
+            me.ignoreSelection--;
+        }
     }
 });
-Ext.DataView = Ext.extend(Ext.BoxComponent, {
-    
-    
-    
-    
-    
-    
-    
+
+
+Ext.define('Ext.picker.Month', {
+    extend: 'Ext.Component',
+    requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
+    alias: 'widget.monthpicker',
+    alternateClassName: 'Ext.MonthPicker',
+
+    renderTpl: [
+        '<div id="{id}-bodyEl" class="{baseCls}-body">',
+          '<div class="{baseCls}-months">',
+              '<tpl for="months">',
+                  '<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
+              '</tpl>',
+          '</div>',
+          '<div class="{baseCls}-years">',
+              '<div class="{baseCls}-yearnav">',
+                  '<button id="{id}-prevEl" class="{baseCls}-yearnav-prev"></button>',
+                  '<button id="{id}-nextEl" class="{baseCls}-yearnav-next"></button>',
+              '</div>',
+              '<tpl for="years">',
+                  '<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
+              '</tpl>',
+          '</div>',
+          '<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
+        '</div>',
+        '<tpl if="showButtons">',
+          '<div id="{id}-buttonsEl" class="{baseCls}-buttons"></div>',
+        '</tpl>'
+    ],
+
     
+    okText: 'OK',
+
     
-    selectedClass : "x-view-selected",
+    cancelText: 'Cancel',
+
     
-    emptyText : "",
+    baseCls: Ext.baseCSSPrefix + 'monthpicker',
 
     
-    deferEmptyText: true,
+    showButtons: true,
+
     
-    trackOver: false,
+
     
+    width: 178,
+
     
-    blockRefresh: false,
+    smallCls: Ext.baseCSSPrefix + 'monthpicker-small',
 
     
-    last: false,
+    totalYears: 10,
+    yearOffset: 5, 
+    monthOffset: 6, 
 
     
-    initComponent : function(){
-        Ext.DataView.superclass.initComponent.call(this);
-        if(Ext.isString(this.tpl) || Ext.isArray(this.tpl)){
-            this.tpl = new Ext.XTemplate(this.tpl);
-        }
+    initComponent: function(){
+        var me = this;
 
-        this.addEvents(
-            
-            "beforeclick",
+        me.selectedCls = me.baseCls + '-selected';
+        me.addEvents(
             
-            "click",
-            
-            "mouseenter",
-            
-            "mouseleave",
+            'cancelclick',
+
             
-            "containerclick",
+            'monthclick',
+
             
-            "dblclick",
+            'monthdblclick',
+
             
-            "contextmenu",
+            'okclick',
+
             
-            "containercontextmenu",
+            'select',
+
             
-            "selectionchange",
+            'yearclick',
 
             
-            "beforeselect"
+            'yeardblclick'
         );
-
-        this.store = Ext.StoreMgr.lookup(this.store);
-        this.all = new Ext.CompositeElementLite();
-        this.selected = new Ext.CompositeElementLite();
+        if (me.small) {
+            me.addCls(me.smallCls);
+        }
+        me.setValue(me.value);
+        me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
+        this.callParent();
     },
 
     
-    afterRender : function(){
-        Ext.DataView.superclass.afterRender.call(this);
+    onRender: function(ct, position){
+        var me = this,
+            i = 0,
+            months = [],
+            shortName = Ext.Date.getShortMonthName,
+            monthLen = me.monthOffset;
+
+        for (; i < monthLen; ++i) {
+            months.push(shortName(i), shortName(i + monthLen));
+        }
 
-               this.mon(this.getTemplateTarget(), {
-            "click": this.onClick,
-            "dblclick": this.onDblClick,
-            "contextmenu": this.onContextMenu,
-            scope:this
+        Ext.apply(me.renderData, {
+            months: months,
+            years: me.getYears(),
+            showButtons: me.showButtons
         });
 
-        if(this.overClass || this.trackOver){
-            this.mon(this.getTemplateTarget(), {
-                "mouseover": this.onMouseOver,
-                "mouseout": this.onMouseOut,
-                scope:this
+        me.addChildEls('bodyEl', 'prevEl', 'nextEl', 'buttonsEl');
+
+        me.callParent(arguments);
+    },
+
+    
+    afterRender: function(){
+        var me = this,
+            body = me.bodyEl,
+            buttonsEl = me.buttonsEl;
+
+        me.callParent();
+
+        me.mon(body, 'click', me.onBodyClick, me);
+        me.mon(body, 'dblclick', me.onBodyClick, me);
+
+        
+        me.years = body.select('.' + me.baseCls + '-year a');
+        me.months = body.select('.' + me.baseCls + '-month a');
+
+        if (me.showButtons) {
+            me.okBtn = Ext.create('Ext.button.Button', {
+                text: me.okText,
+                renderTo: buttonsEl,
+                handler: me.onOkClick,
+                scope: me
+            });
+            me.cancelBtn = Ext.create('Ext.button.Button', {
+                text: me.cancelText,
+                renderTo: buttonsEl,
+                handler: me.onCancelClick,
+                scope: me
             });
         }
 
-        if(this.store){
-            this.bindStore(this.store, true);
-        }
+        me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
+            handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
+        });
+
+        me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
+        me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
+            handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
+        });
+        me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
+        me.updateBody();
     },
 
     
-    refresh : function() {
-        this.clearSelections(false, true);
-        var el = this.getTemplateTarget();
-        el.update("");
-        var records = this.store.getRange();
-        if(records.length < 1){
-            if(!this.deferEmptyText || this.hasSkippedEmptyText){
-                el.update(this.emptyText);
+    setValue: function(value){
+        var me = this,
+            active = me.activeYear,
+            offset = me.monthOffset,
+            year,
+            index;
+
+        if (!value) {
+            me.value = [null, null];
+        } else if (Ext.isDate(value)) {
+            me.value = [value.getMonth(), value.getFullYear()];
+        } else {
+            me.value = [value[0], value[1]];
+        }
+
+        if (me.rendered) {
+            year = me.value[1];
+            if (year !== null) {
+                if ((year < active || year > active + me.yearOffset)) {
+                    me.activeYear = year - me.yearOffset + 1;
+                }
             }
-            this.all.clear();
-        }else{
-            this.tpl.overwrite(el, this.collectData(records, 0));
-            this.all.fill(Ext.query(this.itemSelector, el.dom));
-            this.updateIndexes(0);
+            me.updateBody();
         }
-        this.hasSkippedEmptyText = true;
+
+        return me;
     },
 
-    getTemplateTarget: function(){
-        return this.el;
+    
+    getValue: function(){
+        return this.value;
     },
 
     
-    prepareData : function(data){
-        return data;
+    hasSelection: function(){
+        var value = this.value;
+        return value[0] !== null && value[1] !== null;
     },
 
     
-    collectData : function(records, startIndex){
-        var r = [];
-        for(var i = 0, len = records.length; i < len; i++){
-            r[r.length] = this.prepareData(records[i].data, startIndex+i, records[i]);
+    getYears: function(){
+        var me = this,
+            offset = me.yearOffset,
+            start = me.activeYear, 
+            end = start + offset,
+            i = start,
+            years = [];
+
+        for (; i < end; ++i) {
+            years.push(i, i + offset);
         }
-        return r;
+
+        return years;
     },
 
     
-    bufferRender : function(records){
-        var div = document.createElement('div');
-        this.tpl.overwrite(div, this.collectData(records));
-        return Ext.query(this.itemSelector, div);
+    updateBody: function(){
+        var me = this,
+            years = me.years,
+            months = me.months,
+            yearNumbers = me.getYears(),
+            cls = me.selectedCls,
+            value = me.getYear(null),
+            month = me.value[0],
+            monthOffset = me.monthOffset,
+            year;
+
+        if (me.rendered) {
+            years.removeCls(cls);
+            months.removeCls(cls);
+            years.each(function(el, all, index){
+                year = yearNumbers[index];
+                el.dom.innerHTML = year;
+                if (year == value) {
+                    el.dom.className = cls;
+                }
+            });
+            if (month !== null) {
+                if (month < monthOffset) {
+                    month = month * 2;
+                } else {
+                    month = (month - monthOffset) * 2 + 1;
+                }
+                months.item(month).addCls(cls);
+            }
+        }
     },
 
     
-    onUpdate : function(ds, record){
-        var index = this.store.indexOf(record);
-        if(index > -1){
-            var sel = this.isSelected(index);
-            var original = this.all.elements[index];
-            var node = this.bufferRender([record], index)[0];
+    getYear: function(defaultValue, offset) {
+        var year = this.value[1];
+        offset = offset || 0;
+        return year === null ? defaultValue : year + offset;
+    },
 
-            this.all.replaceElement(index, node, true);
-            if(sel){
-                this.selected.replaceElement(original, node);
-                this.all.item(index).addClass(this.selectedClass);
-            }
-            this.updateIndexes(index, index);
+    
+    onBodyClick: function(e, t) {
+        var me = this,
+            isDouble = e.type == 'dblclick';
+
+        if (e.getTarget('.' + me.baseCls + '-month')) {
+            e.stopEvent();
+            me.onMonthClick(t, isDouble);
+        } else if (e.getTarget('.' + me.baseCls + '-year')) {
+            e.stopEvent();
+            me.onYearClick(t, isDouble);
         }
     },
 
     
-    onAdd : function(ds, records, index){
-        if(this.all.getCount() === 0){
-            this.refresh();
-            return;
+    adjustYear: function(offset){
+        if (typeof offset != 'number') {
+            offset = this.totalYears;
         }
-        var nodes = this.bufferRender(records, index), n, a = this.all.elements;
-        if(index < this.all.getCount()){
-            n = this.all.item(index).insertSibling(nodes, 'before', true);
-            a.splice.apply(a, [index, 0].concat(nodes));
-        }else{
-            n = this.all.last().insertSibling(nodes, 'after', true);
-            a.push.apply(a, nodes);
-        }
-        this.updateIndexes(index);
+        this.activeYear += offset;
+        this.updateBody();
     },
 
     
-    onRemove : function(ds, record, index){
-        this.deselect(index);
-        this.all.removeElement(index, true);
-        this.updateIndexes(index);
-        if (this.store.getCount() === 0){
-            this.refresh();
-        }
+    onOkClick: function(){
+        this.fireEvent('okclick', this, this.value);
     },
 
     
-    refreshNode : function(index){
-        this.onUpdate(this.store, this.store.getAt(index));
+    onCancelClick: function(){
+        this.fireEvent('cancelclick', this);
     },
 
     
-    updateIndexes : function(startIndex, endIndex){
-        var ns = this.all.elements;
-        startIndex = startIndex || 0;
-        endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
-        for(var i = startIndex; i <= endIndex; i++){
-            ns[i].viewIndex = i;
-        }
+    onMonthClick: function(target, isDouble){
+        var me = this;
+        me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
+        me.updateBody();
+        me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
+        me.fireEvent('select', me, me.value);
     },
+
     
+    onYearClick: function(target, isDouble){
+        var me = this;
+        me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
+        me.updateBody();
+        me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
+        me.fireEvent('select', me, me.value);
+
+    },
+
     
-    getStore : function(){
-        return this.store;
+    resolveOffset: function(index, offset){
+        if (index % 2 === 0) {
+            return (index / 2);
+        } else {
+            return offset + Math.floor(index / 2);
+        }
     },
 
     
-    bindStore : function(store, initial){
-        if(!initial && this.store){
-            if(store !== this.store && this.store.autoDestroy){
-                this.store.destroy();
-            }else{
-                this.store.un("beforeload", this.onBeforeLoad, this);
-                this.store.un("datachanged", this.onDataChanged, this);
-                this.store.un("add", this.onAdd, this);
-                this.store.un("remove", this.onRemove, this);
-                this.store.un("update", this.onUpdate, this);
-                this.store.un("clear", this.refresh, this);
-            }
-            if(!store){
-                this.store = null;
+    beforeDestroy: function(){
+        var me = this;
+        me.years = me.months = null;
+        Ext.destroyMembers(me, 'backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
+        me.callParent();
+    }
+});
+
+
+Ext.define('Ext.picker.Date', {
+    extend: 'Ext.Component',
+    requires: [
+        'Ext.XTemplate',
+        'Ext.button.Button',
+        'Ext.button.Split',
+        'Ext.util.ClickRepeater',
+        'Ext.util.KeyNav',
+        'Ext.EventObject',
+        'Ext.fx.Manager',
+        'Ext.picker.Month'
+    ],
+    alias: 'widget.datepicker',
+    alternateClassName: 'Ext.DatePicker',
+
+    renderTpl: [
+        '<div class="{cls}" id="{id}" role="grid" title="{ariaTitle} {value:this.longDay}">',
+            '<div role="presentation" class="{baseCls}-header">',
+                '<div class="{baseCls}-prev"><a id="{id}-prevEl" href="#" role="button" title="{prevText}"></a></div>',
+                '<div class="{baseCls}-month" id="{id}-middleBtnEl"></div>',
+                '<div class="{baseCls}-next"><a id="{id}-nextEl" href="#" role="button" title="{nextText}"></a></div>',
+            '</div>',
+            '<table id="{id}-eventEl" class="{baseCls}-inner" cellspacing="0" role="presentation">',
+                '<thead role="presentation"><tr role="presentation">',
+                    '<tpl for="dayNames">',
+                        '<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
+                    '</tpl>',
+                '</tr></thead>',
+                '<tbody role="presentation"><tr role="presentation">',
+                    '<tpl for="days">',
+                        '{#:this.isEndOfWeek}',
+                        '<td role="gridcell" id="{[Ext.id()]}">',
+                            '<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
+                                '<em role="presentation"><span role="presentation"></span></em>',
+                            '</a>',
+                        '</td>',
+                    '</tpl>',
+                '</tr></tbody>',
+            '</table>',
+            '<tpl if="showToday">',
+                '<div id="{id}-footerEl" role="presentation" class="{baseCls}-footer"></div>',
+            '</tpl>',
+        '</div>',
+        {
+            firstInitial: function(value) {
+                return value.substr(0,1);
+            },
+            isEndOfWeek: function(value) {
+                
+                
+                value--;
+                var end = value % 7 === 0 && value !== 0;
+                return end ? '</tr><tr role="row">' : '';
+            },
+            longDay: function(value){
+                return Ext.Date.format(value, this.longDayFormat);
             }
         }
-        if(store){
-            store = Ext.StoreMgr.lookup(store);
-            store.on({
-                scope: this,
-                beforeload: this.onBeforeLoad,
-                datachanged: this.onDataChanged,
-                add: this.onAdd,
-                remove: this.onRemove,
-                update: this.onUpdate,
-                clear: this.refresh
-            });
-        }
-        this.store = store;
-        if(store){
-            this.refresh();
-        }
+    ],
+
+    ariaTitle: 'Date Picker',
+
+    
+    todayText : 'Today',
+
+    
+
+    
+
+    
+    todayTip : '{0} (Spacebar)',
+
+    
+    minText : 'This date is before the minimum date',
+
+    
+    maxText : 'This date is after the maximum date',
+
+    
+
+    
+    disabledDaysText : 'Disabled',
+
+    
+    disabledDatesText : 'Disabled',
+
+    
+
+    
+
+    
+    nextText : 'Next Month (Control+Right)',
+
+    
+    prevText : 'Previous Month (Control+Left)',
+
+    
+    monthYearText : 'Choose a month (Control+Up/Down to move years)',
+
+    
+    startDay : 0,
+
+    
+    showToday : true,
+
+    
+
+    
+
+    
+
+    
+
+    
+
+    
+    disableAnim: false,
+
+    
+    baseCls: Ext.baseCSSPrefix + 'datepicker',
+
+    
+
+    
+
+    
+    longDayFormat: 'F d, Y',
+
+    
+
+    
+    focusOnShow: false,
+
+    
+    
+    focusOnSelect: true,
+
+    width: 178,
+
+    
+    
+    initHour: 12, 
+
+    numDays: 42,
+
+    
+    initComponent : function() {
+        var me = this,
+            clearTime = Ext.Date.clearTime;
+
+        me.selectedCls = me.baseCls + '-selected';
+        me.disabledCellCls = me.baseCls + '-disabled';
+        me.prevCls = me.baseCls + '-prevday';
+        me.activeCls = me.baseCls + '-active';
+        me.nextCls = me.baseCls + '-prevday';
+        me.todayCls = me.baseCls + '-today';
+        me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
+        this.callParent();
+
+        me.value = me.value ?
+                 clearTime(me.value, true) : clearTime(new Date());
+
+        me.addEvents(
+            
+            'select'
+        );
+
+        me.initDisabledDays();
     },
+
     
+    onRender : function(container, position){
+        
+
+        var me = this,
+            days = new Array(me.numDays),
+            today = Ext.Date.format(new Date(), me.format);
+
+        Ext.applyIf(me, {
+            renderData: {}
+        });
+
+        Ext.apply(me.renderData, {
+            dayNames: me.dayNames,
+            ariaTitle: me.ariaTitle,
+            value: me.value,
+            showToday: me.showToday,
+            prevText: me.prevText,
+            nextText: me.nextText,
+            days: days
+        });
+        me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
+
+        me.addChildEls('eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl');
+
+        this.callParent(arguments);
+        me.el.unselectable();
+
+        me.cells = me.eventEl.select('tbody td');
+        me.textNodes = me.eventEl.query('tbody td span');
+
+        me.monthBtn = Ext.create('Ext.button.Split', {
+            text: '',
+            tooltip: me.monthYearText,
+            renderTo: me.middleBtnEl
+        });
+        
+
+
+        me.todayBtn = Ext.create('Ext.button.Button', {
+            renderTo: me.footerEl,
+            text: Ext.String.format(me.todayText, today),
+            tooltip: Ext.String.format(me.todayTip, today),
+            handler: me.selectToday,
+            scope: me
+        });
+    },
+
     
-    onDataChanged: function() {
-        if (this.blockRefresh !== true) {
-            this.refresh.apply(this, arguments);
+    initEvents: function(){
+        var me = this,
+            eDate = Ext.Date,
+            day = eDate.DAY;
+
+        this.callParent();
+
+        me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
+            handler: me.showPrevMonth,
+            scope: me,
+            preventDefault: true,
+            stopDefault: true
+        });
+
+        me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
+            handler: me.showNextMonth,
+            scope: me,
+            preventDefault:true,
+            stopDefault:true
+        });
+
+        me.keyNav = Ext.create('Ext.util.KeyNav', me.eventEl, Ext.apply({
+            scope: me,
+            'left' : function(e){
+                if(e.ctrlKey){
+                    me.showPrevMonth();
+                }else{
+                    me.update(eDate.add(me.activeDate, day, -1));
+                }
+            },
+
+            'right' : function(e){
+                if(e.ctrlKey){
+                    me.showNextMonth();
+                }else{
+                    me.update(eDate.add(me.activeDate, day, 1));
+                }
+            },
+
+            'up' : function(e){
+                if(e.ctrlKey){
+                    me.showNextYear();
+                }else{
+                    me.update(eDate.add(me.activeDate, day, -7));
+                }
+            },
+
+            'down' : function(e){
+                if(e.ctrlKey){
+                    me.showPrevYear();
+                }else{
+                    me.update(eDate.add(me.activeDate, day, 7));
+                }
+            },
+            'pageUp' : me.showNextMonth,
+            'pageDown' : me.showPrevMonth,
+            'enter' : function(e){
+                e.stopPropagation();
+                return true;
+            }
+        }, me.keyNavConfig));
+
+        if(me.showToday){
+            me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday,  me);
         }
+        me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
+        me.mon(me.eventEl, 'click', me.handleDateClick,  me, {delegate: 'a.' + me.baseCls + '-date'});
+        me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
+        me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
+        me.update(me.value);
     },
 
     
-    findItemFromChild : function(node){
-        return Ext.fly(node).findParent(this.itemSelector, this.getTemplateTarget());
-    },
+    initDisabledDays : function(){
+        var me = this,
+            dd = me.disabledDates,
+            re = '(?:',
+            len;
 
-    
-    onClick : function(e){
-        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
-        if(item){
-            var index = this.indexOf(item);
-            if(this.onItemClick(item, index, e) !== false){
-                this.fireEvent("click", this, index, item, e);
-            }
-        }else{
-            if(this.fireEvent("containerclick", this, e) !== false){
-                this.onContainerClick(e);
-            }
-        }
-    },
+        if(!me.disabledDatesRE && dd){
+                len = dd.length - 1;
 
-    onContainerClick : function(e){
-        this.clearSelections();
+            Ext.each(dd, function(d, i){
+                re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
+                if(i != len){
+                    re += '|';
+                }
+            }, me);
+            me.disabledDatesRE = new RegExp(re + ')');
+        }
     },
 
     
-    onContextMenu : function(e){
-        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
-        if(item){
-            this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
+    setDisabledDates : function(dd){
+        var me = this;
+
+        if(Ext.isArray(dd)){
+            me.disabledDates = dd;
+            me.disabledDatesRE = null;
         }else{
-            this.fireEvent("containercontextmenu", this, e);
+            me.disabledDatesRE = dd;
         }
+        me.initDisabledDays();
+        me.update(me.value, true);
+        return me;
     },
 
     
-    onDblClick : function(e){
-        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
-        if(item){
-            this.fireEvent("dblclick", this, this.indexOf(item), item, e);
-        }
+    setDisabledDays : function(dd){
+        this.disabledDays = dd;
+        return this.update(this.value, true);
     },
 
     
-    onMouseOver : function(e){
-        var item = e.getTarget(this.itemSelector, this.getTemplateTarget());
-        if(item && item !== this.lastItem){
-            this.lastItem = item;
-            Ext.fly(item).addClass(this.overClass);
-            this.fireEvent("mouseenter", this, this.indexOf(item), item, e);
-        }
+    setMinDate : function(dt){
+        this.minDate = dt;
+        return this.update(this.value, true);
     },
 
     
-    onMouseOut : function(e){
-        if(this.lastItem){
-            if(!e.within(this.lastItem, true, true)){
-                Ext.fly(this.lastItem).removeClass(this.overClass);
-                this.fireEvent("mouseleave", this, this.indexOf(this.lastItem), this.lastItem, e);
-                delete this.lastItem;
-            }
-        }
+    setMaxDate : function(dt){
+        this.maxDate = dt;
+        return this.update(this.value, true);
     },
 
     
-    onItemClick : function(item, index, e){
-        if(this.fireEvent("beforeclick", this, index, item, e) === false){
-            return false;
-        }
-        if(this.multiSelect){
-            this.doMultiSelection(item, index, e);
-            e.preventDefault();
-        }else if(this.singleSelect){
-            this.doSingleSelection(item, index, e);
-            e.preventDefault();
-        }
-        return true;
+    setValue : function(value){
+        this.value = Ext.Date.clearTime(value, true);
+        return this.update(this.value);
     },
 
     
-    doSingleSelection : function(item, index, e){
-        if(e.ctrlKey && this.isSelected(index)){
-            this.deselect(index);
-        }else{
-            this.select(index, false);
-        }
+    getValue : function(){
+        return this.value;
     },
 
     
-    doMultiSelection : function(item, index, e){
-        if(e.shiftKey && this.last !== false){
-            var last = this.last;
-            this.selectRange(last, index, e.ctrlKey);
-            this.last = last; 
-        }else{
-            if((e.ctrlKey||this.simpleSelect) && this.isSelected(index)){
-                this.deselect(index);
-            }else{
-                this.select(index, e.ctrlKey || e.shiftKey || this.simpleSelect);
-            }
-        }
+    focus : function(){
+        this.update(this.activeDate);
     },
 
     
-    getSelectionCount : function(){
-        return this.selected.getCount();
+    onEnable: function(){
+        this.callParent();
+        this.setDisabledStatus(false);
+        this.update(this.activeDate);
+
     },
 
     
-    getSelectedNodes : function(){
-        return this.selected.elements;
+    onDisable : function(){
+        this.callParent();
+        this.setDisabledStatus(true);
     },
 
     
-    getSelectedIndexes : function(){
-        var indexes = [], s = this.selected.elements;
-        for(var i = 0, len = s.length; i < len; i++){
-            indexes.push(s[i].viewIndex);
+    setDisabledStatus : function(disabled){
+        var me = this;
+
+        me.keyNav.setDisabled(disabled);
+        me.prevRepeater.setDisabled(disabled);
+        me.nextRepeater.setDisabled(disabled);
+        if (me.showToday) {
+            me.todayKeyListener.setDisabled(disabled);
+            me.todayBtn.setDisabled(disabled);
         }
-        return indexes;
     },
 
     
-    getSelectedRecords : function(){
-        var r = [], s = this.selected.elements;
-        for(var i = 0, len = s.length; i < len; i++){
-            r[r.length] = this.store.getAt(s[i].viewIndex);
-        }
-        return r;
+    getActive: function(){
+        return this.activeDate || this.value;
     },
 
     
-    getRecords : function(nodes){
-        var r = [], s = nodes;
-        for(var i = 0, len = s.length; i < len; i++){
-            r[r.length] = this.store.getAt(s[i].viewIndex);
+    runAnimation: function(isHide){
+        var picker = this.monthPicker,
+            options = {
+                duration: 200,
+                callback: function(){
+                    if (isHide) {
+                        picker.hide();
+                    } else {
+                        picker.show();
+                    }
+                }
+            };
+
+        if (isHide) {
+            picker.el.slideOut('t', options);
+        } else {
+            picker.el.slideIn('t', options);
         }
-        return r;
     },
 
     
-    getRecord : function(node){
-        return this.store.getAt(node.viewIndex);
-    },
+    hideMonthPicker : function(animate){
+        var me = this,
+            picker = me.monthPicker;
 
-    
-    clearSelections : function(suppressEvent, skipUpdate){
-        if((this.multiSelect || this.singleSelect) && this.selected.getCount() > 0){
-            if(!skipUpdate){
-                this.selected.removeClass(this.selectedClass);
-            }
-            this.selected.clear();
-            this.last = false;
-            if(!suppressEvent){
-                this.fireEvent("selectionchange", this, this.selected.elements);
+        if (picker) {
+            if (me.shouldAnimate(animate)) {
+                me.runAnimation(true);
+            } else {
+                picker.hide();
             }
         }
+        return me;
     },
 
     
-    isSelected : function(node){
-        return this.selected.contains(this.getNode(node));
-    },
-
-    
-    deselect : function(node){
-        if(this.isSelected(node)){
-            node = this.getNode(node);
-            this.selected.removeElement(node);
-            if(this.last == node.viewIndex){
-                this.last = false;
+    showMonthPicker : function(animate){
+        var me = this,
+            picker;
+        
+        if (me.rendered && !me.disabled) {
+            picker = me.createMonthPicker();
+            picker.setValue(me.getActive());
+            picker.setSize(me.getSize());
+            picker.setPosition(-1, -1);
+            if (me.shouldAnimate(animate)) {
+                me.runAnimation(false);
+            } else {
+                picker.show();
             }
-            Ext.fly(node).removeClass(this.selectedClass);
-            this.fireEvent("selectionchange", this, this.selected.elements);
         }
+        return me;
+    },
+    
+    
+    shouldAnimate: function(animate){
+        return Ext.isDefined(animate) ? animate : !this.disableAnim;
     },
 
     
-    select : function(nodeInfo, keepExisting, suppressEvent){
-        if(Ext.isArray(nodeInfo)){
-            if(!keepExisting){
-                this.clearSelections(true);
-            }
-            for(var i = 0, len = nodeInfo.length; i < len; i++){
-                this.select(nodeInfo[i], true, true);
-            }
-            if(!suppressEvent){
-                this.fireEvent("selectionchange", this, this.selected.elements);
-            }
-        } else{
-            var node = this.getNode(nodeInfo);
-            if(!keepExisting){
-                this.clearSelections(true);
-            }
-            if(node && !this.isSelected(node)){
-                if(this.fireEvent("beforeselect", this, node, this.selected.elements) !== false){
-                    Ext.fly(node).addClass(this.selectedClass);
-                    this.selected.add(node);
-                    this.last = node.viewIndex;
-                    if(!suppressEvent){
-                        this.fireEvent("selectionchange", this, this.selected.elements);
-                    }
+    createMonthPicker: function(){
+        var me = this,
+            picker = me.monthPicker;
+
+        if (!picker) {
+            me.monthPicker = picker = Ext.create('Ext.picker.Month', {
+                renderTo: me.el,
+                floating: true,
+                shadow: false,
+                small: me.showToday === false,
+                listeners: {
+                    scope: me,
+                    cancelclick: me.onCancelClick,
+                    okclick: me.onOkClick,
+                    yeardblclick: me.onOkClick,
+                    monthdblclick: me.onOkClick
                 }
+            });
+            if (!me.disableAnim) {
+                
+                picker.el.setStyle('display', 'none');
             }
+            me.on('beforehide', Ext.Function.bind(me.hideMonthPicker, me, [false]));
         }
+        return picker;
     },
 
     
-    selectRange : function(start, end, keepExisting){
-        if(!keepExisting){
-            this.clearSelections(true);
+    onOkClick: function(picker, value){
+        var me = this,
+            month = value[0],
+            year = value[1],
+            date = new Date(year, month, me.getActive().getDate());
+
+        if (date.getMonth() !== month) {
+            
+            date = new Date(year, month, 1).getLastDateOfMonth();
         }
-        this.select(this.getNodes(start, end), true);
+        me.update(date);
+        me.hideMonthPicker();
     },
 
     
-    getNode : function(nodeInfo){
-        if(Ext.isString(nodeInfo)){
-            return document.getElementById(nodeInfo);
-        }else if(Ext.isNumber(nodeInfo)){
-            return this.all.elements[nodeInfo];
-        }else if(nodeInfo instanceof Ext.data.Record){
-            var idx = this.store.indexOf(nodeInfo);
-            return this.all.elements[idx];
-        }
-        return nodeInfo;
+    onCancelClick: function(){
+        this.hideMonthPicker();
     },
 
     
-    getNodes : function(start, end){
-        var ns = this.all.elements;
-        start = start || 0;
-        end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
-        var nodes = [], i;
-        if(start <= end){
-            for(i = start; i <= end && ns[i]; i++){
-                nodes.push(ns[i]);
-            }
-        } else{
-            for(i = start; i >= end && ns[i]; i--){
-                nodes.push(ns[i]);
-            }
-        }
-        return nodes;
+    showPrevMonth : function(e){
+        return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
     },
 
     
-    indexOf : function(node){
-        node = this.getNode(node);
-        if(Ext.isNumber(node.viewIndex)){
-            return node.viewIndex;
-        }
-        return this.all.indexOf(node);
+    showNextMonth : function(e){
+        return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
     },
 
     
-    onBeforeLoad : function(){
-        if(this.loadingText){
-            this.clearSelections(false, true);
-            this.getTemplateTarget().update('<div class="loading-indicator">'+this.loadingText+'</div>');
-            this.all.clear();
-        }
+    showPrevYear : function(){
+        this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
     },
 
-    onDestroy : function(){
-        this.all.clear();
-        this.selected.clear();
-        Ext.DataView.superclass.onDestroy.call(this);
-        this.bindStore(null);
-    }
-});
-
-
-Ext.DataView.prototype.setStore = Ext.DataView.prototype.bindStore;
-
-Ext.reg('dataview', Ext.DataView);
-
-Ext.list.ListView = Ext.extend(Ext.DataView, {
-    
-    
-    
-    itemSelector: 'dl',
-    
-    selectedClass:'x-list-selected',
-    
-    overClass:'x-list-over',
-    
-    
-    scrollOffset : undefined,
-    
-    columnResize: true,
-    
-    
-    columnSort: true,
     
+    showNextYear : function(){
+        this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
+    },
 
     
-    maxColumnWidth: Ext.isIE ? 99 : 100,
-
-    initComponent : function(){
-        if(this.columnResize){
-            this.colResizer = new Ext.list.ColumnResizer(this.colResizer);
-            this.colResizer.init(this);
-        }
-        if(this.columnSort){
-            this.colSorter = new Ext.list.Sorter(this.columnSort);
-            this.colSorter.init(this);
-        }
-        if(!this.internalTpl){
-            this.internalTpl = new Ext.XTemplate(
-                '<div class="x-list-header"><div class="x-list-header-inner">',
-                    '<tpl for="columns">',
-                    '<div style="width:{[values.width*100]}%;text-align:{align};"><em unselectable="on" id="',this.id, '-xlhd-{#}">',
-                        '{header}',
-                    '</em></div>',
-                    '</tpl>',
-                    '<div class="x-clear"></div>',
-                '</div></div>',
-                '<div class="x-list-body"><div class="x-list-body-inner">',
-                '</div></div>'
-            );
-        }
-        if(!this.tpl){
-            this.tpl = new Ext.XTemplate(
-                '<tpl for="rows">',
-                    '<dl>',
-                        '<tpl for="parent.columns">',
-                        '<dt style="width:{[values.width*100]}%;text-align:{align};">',
-                        '<em unselectable="on"<tpl if="cls"> class="{cls}</tpl>">',
-                            '{[values.tpl.apply(parent)]}',
-                        '</em></dt>',
-                        '</tpl>',
-                        '<div class="x-clear"></div>',
-                    '</dl>',
-                '</tpl>'
-            );
-        };
-
-        var cs = this.columns,
-            allocatedWidth = 0,
-            colsWithWidth = 0,
-            len = cs.length,
-            columns = [];
-
-        for(var i = 0; i < len; i++){
-            var c = cs[i];
-            if(!c.isColumn) {
-                c.xtype = c.xtype ? (/^lv/.test(c.xtype) ? c.xtype : 'lv' + c.xtype) : 'lvcolumn';
-                c = Ext.create(c);
-            }
-            if(c.width) {
-                allocatedWidth += c.width*100;
-                colsWithWidth++;
-            }
-            columns.push(c);
-        }
-
-        cs = this.columns = columns;
-
-        
-        if(colsWithWidth < len){
-            var remaining = len - colsWithWidth;
-            if(allocatedWidth < this.maxColumnWidth){
-                var perCol = ((this.maxColumnWidth-allocatedWidth) / remaining)/100;
-                for(var j = 0; j < len; j++){
-                    var c = cs[j];
-                    if(!c.width){
-                        c.width = perCol;
-                    }
-                }
+    handleMouseWheel : function(e){
+        e.stopEvent();
+        if(!this.disabled){
+            var delta = e.getWheelDelta();
+            if(delta > 0){
+                this.showPrevMonth();
+            } else if(delta < 0){
+                this.showNextMonth();
             }
         }
-        Ext.list.ListView.superclass.initComponent.call(this);
-    },
-
-    onRender : function(){
-        this.autoEl = {
-            cls: 'x-list-wrap'
-        };
-        Ext.list.ListView.superclass.onRender.apply(this, arguments);
-
-        this.internalTpl.overwrite(this.el, {columns: this.columns});
-
-        this.innerBody = Ext.get(this.el.dom.childNodes[1].firstChild);
-        this.innerHd = Ext.get(this.el.dom.firstChild.firstChild);
-
-        if(this.hideHeaders){
-            this.el.dom.firstChild.style.display = 'none';
-        }
-    },
-
-    getTemplateTarget : function(){
-        return this.innerBody;
     },
 
     
-    collectData : function(){
-        var rs = Ext.list.ListView.superclass.collectData.apply(this, arguments);
-        return {
-            columns: this.columns,
-            rows: rs
-        }
-    },
+    handleDateClick : function(e, t){
+        var me = this,
+            handler = me.handler;
 
-    verifyInternalSize : function(){
-        if(this.lastSize){
-            this.onResize(this.lastSize.width, this.lastSize.height);
+        e.stopEvent();
+        if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
+            me.cancelFocus = me.focusOnSelect === false;
+            me.setValue(new Date(t.dateValue));
+            delete me.cancelFocus;
+            me.fireEvent('select', me, me.value);
+            if (handler) {
+                handler.call(me.scope || me, me, me.value);
+            }
+            
+            
+            
+            
+            me.onSelect();
         }
     },
 
     
-    onResize : function(w, h){
-        var bd = this.innerBody.dom;
-        var hd = this.innerHd.dom;
-        if(!bd){
-            return;
-        }
-        var bdp = bd.parentNode;
-        if(Ext.isNumber(w)){
-            var sw = w - Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
-            if(this.reserveScrollOffset || ((bdp.offsetWidth - bdp.clientWidth) > 10)){
-                bd.style.width = sw + 'px';
-                hd.style.width = sw + 'px';
-            }else{
-                bd.style.width = w + 'px';
-                hd.style.width = w + 'px';
-                setTimeout(function(){
-                    if((bdp.offsetWidth - bdp.clientWidth) > 10){
-                        bd.style.width = sw + 'px';
-                        hd.style.width = sw + 'px';
-                    }
-                }, 10);
-            }
-        }
-        if(Ext.isNumber(h)){
-            bdp.style.height = (h - hd.parentNode.offsetHeight) + 'px';
-        }
+    onSelect: function() {
+        if (this.hideOnSelect) {
+             this.hide();
+         }
     },
 
-    updateIndexes : function(){
-        Ext.list.ListView.superclass.updateIndexes.apply(this, arguments);
-        this.verifyInternalSize();
-    },
+    
+    selectToday : function(){
+        var me = this,
+            btn = me.todayBtn,
+            handler = me.handler;
 
-    findHeaderIndex : function(hd){
-        hd = hd.dom || hd;
-        var pn = hd.parentNode, cs = pn.parentNode.childNodes;
-        for(var i = 0, c; c = cs[i]; i++){
-            if(c == pn){
-                return i;
+        if(btn && !btn.disabled){
+            me.setValue(Ext.Date.clearTime(new Date()));
+            me.fireEvent('select', me, me.value);
+            if (handler) {
+                handler.call(me.scope || me, me, me.value);
             }
+            me.onSelect();
         }
-        return -1;
+        return me;
     },
 
-    setHdWidths : function(){
-        var els = this.innerHd.dom.getElementsByTagName('div');
-        for(var i = 0, cs = this.columns, len = cs.length; i < len; i++){
-            els[i].style.width = (cs[i].width*100) + '%';
-        }
-    }
-});
-
-Ext.reg('listview', Ext.list.ListView);
-
-
-Ext.ListView = Ext.list.ListView;
-Ext.list.Column = Ext.extend(Object, {
-    
-    isColumn: true,
     
-            
-    align: 'left',
-        
-    header: '',
-    
-        
-    width: null,
+    selectedUpdate: function(date, active){
+        var me = this,
+            t = date.getTime(),
+            cells = me.cells,
+            cls = me.selectedCls;
+
+        cells.removeCls(cls);
+        cells.each(function(c){
+            if (c.dom.firstChild.dateValue == t) {
+                me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
+                c.addCls(cls);
+                if(me.isVisible() && !me.cancelFocus){
+                    Ext.fly(c.dom.firstChild).focus(50);
+                }
+                return false;
+            }
+        }, this);
+    },
 
     
-    cls: '',
-    
-    
+    fullUpdate: function(date, active){
+        var me = this,
+            cells = me.cells.elements,
+            textNodes = me.textNodes,
+            disabledCls = me.disabledCellCls,
+            eDate = Ext.Date,
+            i = 0,
+            extraDays = 0,
+            visible = me.isVisible(),
+            sel = +eDate.clearTime(date, true),
+            today = +eDate.clearTime(new Date()),
+            min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
+            max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
+            ddMatch = me.disabledDatesRE,
+            ddText = me.disabledDatesText,
+            ddays = me.disabledDays ? me.disabledDays.join('') : false,
+            ddaysText = me.disabledDaysText,
+            format = me.format,
+            days = eDate.getDaysInMonth(date),
+            firstOfMonth = eDate.getFirstDateOfMonth(date),
+            startingPos = firstOfMonth.getDay() - me.startDay,
+            previousMonth = eDate.add(date, eDate.MONTH, -1),
+            longDayFormat = me.longDayFormat,
+            prevStart,
+            current,
+            disableToday,
+            tempDate,
+            setCellClass,
+            html,
+            cls,
+            formatValue,
+            value;
 
-    
-    
-    constructor : function(c){
-        if(!c.tpl){
-            c.tpl = new Ext.XTemplate('{' + c.dataIndex + '}');
-        }
-        else if(Ext.isString(c.tpl)){
-            c.tpl = new Ext.XTemplate(c.tpl);
+        if (startingPos < 0) {
+            startingPos += 7;
         }
-        
-        Ext.apply(this, c);
-    }
-});
-
-Ext.reg('lvcolumn', Ext.list.Column);
 
+        days += startingPos;
+        prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
+        current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
 
-Ext.list.NumberColumn = Ext.extend(Ext.list.Column, {
-        
-    format: '0,000.00',
-    
-    constructor : function(c) {
-        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':number("' + (c.format || this.format) + '")}');       
-        Ext.list.NumberColumn.superclass.constructor.call(this, c);
-    }
-});
-
-Ext.reg('lvnumbercolumn', Ext.list.NumberColumn);
-
-
-Ext.list.DateColumn = Ext.extend(Ext.list.Column, {
-    format: 'm/d/Y',
-    constructor : function(c) {
-        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':date("' + (c.format || this.format) + '")}');      
-        Ext.list.DateColumn.superclass.constructor.call(this, c);
-    }
-});
-Ext.reg('lvdatecolumn', Ext.list.DateColumn);
+        if (me.showToday) {
+            tempDate = eDate.clearTime(new Date());
+            disableToday = (tempDate < min || tempDate > max ||
+                (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
+                (ddays && ddays.indexOf(tempDate.getDay()) != -1));
 
+            if (!me.disabled) {
+                me.todayBtn.setDisabled(disableToday);
+                me.todayKeyListener.setDisabled(disableToday);
+            }
+        }
 
-Ext.list.BooleanColumn = Ext.extend(Ext.list.Column, {
-    
-    trueText: 'true',
-    
-    falseText: 'false',
-    
-    undefinedText: '&#160;',
-    
-    constructor : function(c) {
-        c.tpl = c.tpl || new Ext.XTemplate('{' + c.dataIndex + ':this.format}');
-        
-        var t = this.trueText, f = this.falseText, u = this.undefinedText;
-        c.tpl.format = function(v){
-            if(v === undefined){
-                return u;
+        setCellClass = function(cell){
+            value = +eDate.clearTime(current, true);
+            cell.title = eDate.format(current, longDayFormat);
+            
+            cell.firstChild.dateValue = value;
+            if(value == today){
+                cell.className += ' ' + me.todayCls;
+                cell.title = me.todayText;
+            }
+            if(value == sel){
+                cell.className += ' ' + me.selectedCls;
+                me.el.dom.setAttribute('aria-activedescendant', cell.id);
+                if (visible && me.floating) {
+                    Ext.fly(cell.firstChild).focus(50);
+                }
+            }
+            
+            if(value < min) {
+                cell.className = disabledCls;
+                cell.title = me.minText;
+                return;
+            }
+            if(value > max) {
+                cell.className = disabledCls;
+                cell.title = me.maxText;
+                return;
+            }
+            if(ddays){
+                if(ddays.indexOf(current.getDay()) != -1){
+                    cell.title = ddaysText;
+                    cell.className = disabledCls;
+                }
             }
-            if(!v || v === 'false'){
-                return f;
+            if(ddMatch && format){
+                formatValue = eDate.dateFormat(current, format);
+                if(ddMatch.test(formatValue)){
+                    cell.title = ddText.replace('%0', formatValue);
+                    cell.className = disabledCls;
+                }
             }
-            return t;
         };
-        
-        Ext.list.DateColumn.superclass.constructor.call(this, c);
-    }
-});
-
-Ext.reg('lvbooleancolumn', Ext.list.BooleanColumn);
-Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
-    
-    minPct: .05,
-
-    constructor: function(config){
-        Ext.apply(this, config);
-        Ext.list.ColumnResizer.superclass.constructor.call(this);
-    },
-    init : function(listView){
-        this.view = listView;
-        listView.on('render', this.initEvents, this);
-    },
 
-    initEvents : function(view){
-        view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
-        this.tracker = new Ext.dd.DragTracker({
-            onBeforeStart: this.onBeforeStart.createDelegate(this),
-            onStart: this.onStart.createDelegate(this),
-            onDrag: this.onDrag.createDelegate(this),
-            onEnd: this.onEnd.createDelegate(this),
-            tolerance: 3,
-            autoStart: 300
-        });
-        this.tracker.initEl(view.innerHd);
-        view.on('beforedestroy', this.tracker.destroy, this.tracker);
-    },
-
-    handleHdMove : function(e, t){
-        var hw = 5,
-            x = e.getPageX(),
-            hd = e.getTarget('em', 3, true);
-        if(hd){
-            var r = hd.getRegion(),
-                ss = hd.dom.style,
-                pn = hd.dom.parentNode;
-
-            if(x - r.left <= hw && pn != pn.parentNode.firstChild){
-                this.activeHd = Ext.get(pn.previousSibling.firstChild);
-                ss.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
-            } else if(r.right - x <= hw && pn != pn.parentNode.lastChild.previousSibling){
-                this.activeHd = hd;
-                ss.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
-            } else{
-                delete this.activeHd;
-                ss.cursor = '';
+        for(; i < me.numDays; ++i) {
+            if (i < startingPos) {
+                html = (++prevStart);
+                cls = me.prevCls;
+            } else if (i >= days) {
+                html = (++extraDays);
+                cls = me.nextCls;
+            } else {
+                html = i - startingPos + 1;
+                cls = me.activeCls;
             }
+            textNodes[i].innerHTML = html;
+            cells[i].className = cls;
+            current.setDate(current.getDate() + 1);
+            setCellClass(cells[i]);
         }
-    },
 
-    onBeforeStart : function(e){
-        this.dragHd = this.activeHd;
-        return !!this.dragHd;
+        me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
     },
 
-    onStart: function(e){
-        this.view.disableHeaders = true;
-        this.proxy = this.view.el.createChild({cls:'x-list-resizer'});
-        this.proxy.setHeight(this.view.el.getHeight());
-
-        var x = this.tracker.getXY()[0],
-            w = this.view.innerHd.getWidth();
-
-        this.hdX = this.dragHd.getX();
-        this.hdIndex = this.view.findHeaderIndex(this.dragHd);
-
-        this.proxy.setX(this.hdX);
-        this.proxy.setWidth(x-this.hdX);
-
-        this.minWidth = w*this.minPct;
-        this.maxWidth = w - (this.minWidth*(this.view.columns.length-1-this.hdIndex));
-    },
+    
+    update : function(date, forceRefresh){
+        var me = this,
+            active = me.activeDate;
 
-    onDrag: function(e){
-        var cursorX = this.tracker.getXY()[0];
-        this.proxy.setWidth((cursorX-this.hdX).constrain(this.minWidth, this.maxWidth));
+        if (me.rendered) {
+            me.activeDate = date;
+            if(!forceRefresh && active && me.el && active.getMonth() == date.getMonth() && active.getFullYear() == date.getFullYear()){
+                me.selectedUpdate(date, active);
+            } else {
+                me.fullUpdate(date, active);
+            }
+        }
+        return me;
     },
 
-    onEnd: function(e){
-        
-        var nw = this.proxy.getWidth();
-        this.proxy.remove();
-
-        var index = this.hdIndex,
-            vw = this.view,
-            cs = vw.columns,
-            len = cs.length,
-            w = this.view.innerHd.getWidth(),
-            minPct = this.minPct * 100,
-            pct = Math.ceil((nw * vw.maxColumnWidth) / w),
-            diff = (cs[index].width * 100) - pct,
-            eachItem = Math.floor(diff / (len-1-index)),
-            mod = diff - (eachItem * (len-1-index));
-
-        for(var i = index+1; i < len; i++){
-            var cw = (cs[i].width * 100) + eachItem,
-                ncw = Math.max(minPct, cw);
-            if(cw != ncw){
-                mod += cw - ncw;
-            }
-            cs[i].width = ncw / 100;
-        }
-        cs[index].width = pct / 100;
-        cs[index+1].width += (mod / 100);
-        delete this.dragHd;
-        vw.setHdWidths();
-        vw.refresh();
-        setTimeout(function(){
-            vw.disableHeaders = false;
-        }, 100);
-    }
-});
-
-
-Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;
-Ext.list.Sorter = Ext.extend(Ext.util.Observable, {
     
-    sortClasses : ["sort-asc", "sort-desc"],
+    beforeDestroy : function() {
+        var me = this;
 
-    constructor: function(config){
-        Ext.apply(this, config);
-        Ext.list.Sorter.superclass.constructor.call(this);
+        if (me.rendered) {
+            Ext.destroy(
+                me.todayKeyListener,
+                me.keyNav,
+                me.monthPicker,
+                me.monthBtn,
+                me.nextRepeater,
+                me.prevRepeater,
+                me.todayBtn
+            );
+            delete me.textNodes;
+            delete me.cells.elements;
+        }
+        me.callParent();
     },
 
-    init : function(listView){
-        this.view = listView;
-        listView.on('render', this.initEvents, this);
-    },
+    
+    onShow: function() {
+        this.callParent(arguments);
+        if (this.focusOnShow) {
+            this.focus();
+        }
+    }
+},
 
-    initEvents : function(view){
-        view.mon(view.innerHd, 'click', this.onHdClick, this);
-        view.innerHd.setStyle('cursor', 'pointer');
-        view.mon(view.store, 'datachanged', this.updateSortState, this);
-        this.updateSortState.defer(10, this, [view.store]);
-    },
 
-    updateSortState : function(store){
-        var state = store.getSortState();
-        if(!state){
-            return;
-        }
-        this.sortState = state;
-        var cs = this.view.columns, sortColumn = -1;
-        for(var i = 0, len = cs.length; i < len; i++){
-            if(cs[i].dataIndex == state.field){
-                sortColumn = i;
-                break;
-            }
-        }
-        if(sortColumn != -1){
-            var sortDir = state.direction;
-            this.updateSortIcon(sortColumn, sortDir);
-        }
-    },
+function() {
+    var proto = this.prototype;
 
-    updateSortIcon : function(col, dir){
-        var sc = this.sortClasses;
-        var hds = this.view.innerHd.select('em').removeClass(sc);
-        hds.item(col).addClass(sc[dir == "DESC" ? 1 : 0]);
-    },
+    proto.monthNames = Ext.Date.monthNames;
 
-    onHdClick : function(e){
-        var hd = e.getTarget('em', 3);
-        if(hd && !this.view.disableHeaders){
-            var index = this.view.findHeaderIndex(hd);
-            this.view.store.sort(this.view.columns[index].dataIndex);
-        }
-    }
+    proto.dayNames = Ext.Date.dayNames;
+
+    proto.format = Ext.Date.defaultFormat;
 });
 
 
-Ext.ListView.Sorter = Ext.list.Sorter;
-Ext.TabPanel = Ext.extend(Ext.Panel,  {
-    
-    
-    
-    deferredRender : true,
-    
-    tabWidth : 120,
-    
-    minTabWidth : 30,
-    
-    resizeTabs : false,
-    
-    enableTabScroll : false,
+Ext.define('Ext.form.field.Date', {
+    extend:'Ext.form.field.Picker',
+    alias: 'widget.datefield',
+    requires: ['Ext.picker.Date'],
+    alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'],
+
     
-    scrollIncrement : 0,
+    format : "m/d/Y",
     
-    scrollRepeatInterval : 400,
+    altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",
     
-    scrollDuration : 0.35,
+    disabledDaysText : "Disabled",
     
-    animScroll : true,
+    disabledDatesText : "Disabled",
     
-    tabPosition : 'top',
+    minText : "The date in this field must be equal to or after {0}",
     
-    baseCls : 'x-tab-panel',
+    maxText : "The date in this field must be equal to or before {0}",
     
-    autoTabs : false,
+    invalidText : "{0} is not a valid date - it must be in the format {1}",
     
-    autoTabSelector : 'div.x-tab',
+    triggerCls : Ext.baseCSSPrefix + 'form-date-trigger',
     
-    activeTab : undefined,
+    showToday : true,
     
-    tabMargin : 2,
     
-    plain : false,
     
-    wheelIncrement : 20,
-
     
-    idDelimiter : '__',
 
     
-    itemCls : 'x-tab-item',
 
     
-    elements : 'body',
-    headerAsText : false,
-    frame : false,
-    hideBorders :true,
-
     
-    initComponent : function(){
-        this.frame = false;
-        Ext.TabPanel.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'beforetabchange',
-            
-            'tabchange',
-            
-            'contextmenu'
-        );
-        
-        this.setLayout(new Ext.layout.CardLayout(Ext.apply({
-            layoutOnCardChange: this.layoutOnTabChange,
-            deferredRender: this.deferredRender
-        }, this.layoutConfig)));
+    initTime: '12', 
 
-        if(this.tabPosition == 'top'){
-            this.elements += ',header';
-            this.stripTarget = 'header';
-        }else {
-            this.elements += ',footer';
-            this.stripTarget = 'footer';
-        }
-        if(!this.stack){
-            this.stack = Ext.TabPanel.AccessStack();
-        }
-        this.initItems();
-    },
+    initTimeFormat: 'H',
 
+    matchFieldWidth: false,
     
-    onRender : function(ct, position){
-        Ext.TabPanel.superclass.onRender.call(this, ct, position);
+    startDay: 0,
 
-        if(this.plain){
-            var pos = this.tabPosition == 'top' ? 'header' : 'footer';
-            this[pos].addClass('x-tab-panel-'+pos+'-plain');
-        }
-
-        var st = this[this.stripTarget];
-
-        this.stripWrap = st.createChild({cls:'x-tab-strip-wrap', cn:{
-            tag:'ul', cls:'x-tab-strip x-tab-strip-'+this.tabPosition}});
-
-        var beforeEl = (this.tabPosition=='bottom' ? this.stripWrap : null);
-        st.createChild({cls:'x-tab-strip-spacer'}, beforeEl);
-        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
-
-        
-        this.edge = this.strip.createChild({tag:'li', cls:'x-tab-edge', cn: [{tag: 'span', cls: 'x-tab-strip-text', cn: '&#160;'}]});
-        this.strip.createChild({cls:'x-clear'});
-
-        this.body.addClass('x-tab-panel-body-'+this.tabPosition);
-
-        
-        if(!this.itemTpl){
-            var tt = new Ext.Template(
-                 '<li class="{cls}" id="{id}"><a class="x-tab-strip-close"></a>',
-                 '<a class="x-tab-right" href="#"><em class="x-tab-left">',
-                 '<span class="x-tab-strip-inner"><span class="x-tab-strip-text {iconCls}">{text}</span></span>',
-                 '</em></a></li>'
-            );
-            tt.disableFormats = true;
-            tt.compile();
-            Ext.TabPanel.prototype.itemTpl = tt;
-        }
-
-        this.items.each(this.initTab, this);
-    },
+    initComponent : function(){
+        var me = this,
+            isString = Ext.isString,
+            min, max;
 
-    
-    afterRender : function(){
-        Ext.TabPanel.superclass.afterRender.call(this);
-        if(this.autoTabs){
-            this.readTabs(false);
+        min = me.minValue;
+        max = me.maxValue;
+        if(isString(min)){
+            me.minValue = me.parseDate(min);
         }
-        if(this.activeTab !== undefined){
-            var item = Ext.isObject(this.activeTab) ? this.activeTab : this.items.get(this.activeTab);
-            delete this.activeTab;
-            this.setActiveTab(item);
+        if(isString(max)){
+            me.maxValue = me.parseDate(max);
         }
-    },
+        me.disabledDatesRE = null;
+        me.initDisabledDays();
 
-    
-    initEvents : function(){
-        Ext.TabPanel.superclass.initEvents.call(this);
-        this.mon(this.strip, {
-            scope: this,
-            mousedown: this.onStripMouseDown,
-            contextmenu: this.onStripContextMenu
-        });
-        if(this.enableTabScroll){
-            this.mon(this.strip, 'mousewheel', this.onWheel, this);
-        }
+        me.callParent();
     },
 
-    
-    findTargets : function(e){
-        var item = null,
-            itemEl = e.getTarget('li:not(.x-tab-edge)', this.strip);
+    initValue: function() {
+        var me = this,
+            value = me.value;
 
-        if(itemEl){
-            item = this.getComponent(itemEl.id.split(this.idDelimiter)[1]);
-            if(item.disabled){
-                return {
-                    close : null,
-                    item : null,
-                    el : null
-                };
-            }
+        
+        if (Ext.isString(value)) {
+            me.value = me.rawToValue(value);
         }
-        return {
-            close : e.getTarget('.x-tab-strip-close', this.strip),
-            item : item,
-            el : itemEl
-        };
-    },
 
-    
-    onStripMouseDown : function(e){
-        if(e.button !== 0){
-            return;
-        }
-        e.preventDefault();
-        var t = this.findTargets(e);
-        if(t.close){
-            if (t.item.fireEvent('beforeclose', t.item) !== false) {
-                t.item.fireEvent('close', t.item);
-                this.remove(t.item);
-            }
-            return;
-        }
-        if(t.item && t.item != this.activeTab){
-            this.setActiveTab(t.item);
-        }
+        me.callParent();
     },
 
     
-    onStripContextMenu : function(e){
-        e.preventDefault();
-        var t = this.findTargets(e);
-        if(t.item){
-            this.fireEvent('contextmenu', this, t.item, e);
-        }
-    },
+    initDisabledDays : function(){
+        if(this.disabledDates){
+            var dd = this.disabledDates,
+                len = dd.length - 1,
+                re = "(?:";
 
-    
-    readTabs : function(removeExisting){
-        if(removeExisting === true){
-            this.items.each(function(item){
-                this.remove(item);
+            Ext.each(dd, function(d, i){
+                re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(d.dateFormat(this.format)) + '$' : dd[i];
+                if (i !== len) {
+                    re += '|';
+                }
             }, this);
+            this.disabledDatesRE = new RegExp(re + ')');
         }
-        var tabs = this.el.query(this.autoTabSelector);
-        for(var i = 0, len = tabs.length; i < len; i++){
-            var tab = tabs[i],
-                title = tab.getAttribute('title');
-            tab.removeAttribute('title');
-            this.add({
-                title: title,
-                contentEl: tab
-            });
-        }
-    },
-
-    
-    initTab : function(item, index){
-        var before = this.strip.dom.childNodes[index],
-            p = this.getTemplateArgs(item),
-            el = before ?
-                 this.itemTpl.insertBefore(before, p) :
-                 this.itemTpl.append(this.strip, p),
-            cls = 'x-tab-strip-over',
-            tabEl = Ext.get(el);
-
-        tabEl.hover(function(){
-            if(!item.disabled){
-                tabEl.addClass(cls);
-            }
-        }, function(){
-            tabEl.removeClass(cls);
-        });
-
-        if(item.tabTip){
-            tabEl.child('span.x-tab-strip-text', true).qtip = item.tabTip;
-        }
-        item.tabEl = el;
-
-        
-        tabEl.select('a').on('click', function(e){
-            if(!e.getPageX()){
-                this.onStripMouseDown(e);
-            }
-        }, this, {preventDefault: true});
-
-        item.on({
-            scope: this,
-            disable: this.onItemDisabled,
-            enable: this.onItemEnabled,
-            titlechange: this.onItemTitleChanged,
-            iconchange: this.onItemIconChanged,
-            beforeshow: this.onBeforeShowItem
-        });
     },
 
-
-
     
-    getTemplateArgs : function(item) {
-        var cls = item.closable ? 'x-tab-strip-closable' : '';
-        if(item.disabled){
-            cls += ' x-item-disabled';
-        }
-        if(item.iconCls){
-            cls += ' x-tab-with-icon';
-        }
-        if(item.tabCls){
-            cls += ' ' + item.tabCls;
-        }
-
-        return {
-            id: this.id + this.idDelimiter + item.getItemId(),
-            text: item.title,
-            cls: cls,
-            iconCls: item.iconCls || ''
-        };
-    },
+    setDisabledDates : function(dd){
+        var me = this,
+            picker = me.picker;
 
-    
-    onAdd : function(c){
-        Ext.TabPanel.superclass.onAdd.call(this, c);
-        if(this.rendered){
-            var items = this.items;
-            this.initTab(c, items.indexOf(c));
-            this.delegateUpdates();
+        me.disabledDates = dd;
+        me.initDisabledDays();
+        if (picker) {
+            picker.setDisabledDates(me.disabledDatesRE);
         }
     },
 
     
-    onBeforeAdd : function(item){
-        var existing = item.events ? (this.items.containsKey(item.getItemId()) ? item : null) : this.items.get(item);
-        if(existing){
-            this.setActiveTab(item);
-            return false;
-        }
-        Ext.TabPanel.superclass.onBeforeAdd.apply(this, arguments);
-        var es = item.elements;
-        item.elements = es ? es.replace(',header', '') : es;
-        item.border = (item.border === true);
-    },
-
-    
-    onRemove : function(c){
-        var te = Ext.get(c.tabEl);
-        
-        if(te){
-            te.select('a').removeAllListeners();
-            Ext.destroy(te);
-        }
-        Ext.TabPanel.superclass.onRemove.call(this, c);
-        this.stack.remove(c);
-        delete c.tabEl;
-        c.un('disable', this.onItemDisabled, this);
-        c.un('enable', this.onItemEnabled, this);
-        c.un('titlechange', this.onItemTitleChanged, this);
-        c.un('iconchange', this.onItemIconChanged, this);
-        c.un('beforeshow', this.onBeforeShowItem, this);
-        if(c == this.activeTab){
-            var next = this.stack.next();
-            if(next){
-                this.setActiveTab(next);
-            }else if(this.items.getCount() > 0){
-                this.setActiveTab(0);
-            }else{
-                this.setActiveTab(null);
-            }
-        }
-        if(!this.destroying){
-            this.delegateUpdates();
-        }
-    },
+    setDisabledDays : function(dd){
+        var picker = this.picker;
 
-    
-    onBeforeShowItem : function(item){
-        if(item != this.activeTab){
-            this.setActiveTab(item);
-            return false;
+        this.disabledDays = dd;
+        if (picker) {
+            picker.setDisabledDays(dd);
         }
     },
 
     
-    onItemDisabled : function(item){
-        var el = this.getTabEl(item);
-        if(el){
-            Ext.fly(el).addClass('x-item-disabled');
-        }
-        this.stack.remove(item);
-    },
+    setMinValue : function(dt){
+        var me = this,
+            picker = me.picker,
+            minValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
 
-    
-    onItemEnabled : function(item){
-        var el = this.getTabEl(item);
-        if(el){
-            Ext.fly(el).removeClass('x-item-disabled');
+        me.minValue = minValue;
+        if (picker) {
+            picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
+            picker.setMinDate(minValue);
         }
     },
 
     
-    onItemTitleChanged : function(item){
-        var el = this.getTabEl(item);
-        if(el){
-            Ext.fly(el).child('span.x-tab-strip-text', true).innerHTML = item.title;
-        }
-    },
+    setMaxValue : function(dt){
+        var me = this,
+            picker = me.picker,
+            maxValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
 
-    
-    onItemIconChanged : function(item, iconCls, oldCls){
-        var el = this.getTabEl(item);
-        if(el){
-            el = Ext.get(el);
-            el.child('span.x-tab-strip-text').replaceClass(oldCls, iconCls);
-            el[Ext.isEmpty(iconCls) ? 'removeClass' : 'addClass']('x-tab-with-icon');
+        me.maxValue = maxValue;
+        if (picker) {
+            picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
+            picker.setMaxDate(maxValue);
         }
     },
 
     
-    getTabEl : function(item){
-        var c = this.getComponent(item);
-        return c ? c.tabEl : null;
-    },
-
-    
-    onResize : function(){
-        Ext.TabPanel.superclass.onResize.apply(this, arguments);
-        this.delegateUpdates();
-    },
-
-    
-    beginUpdate : function(){
-        this.suspendUpdates = true;
-    },
-
-    
-    endUpdate : function(){
-        this.suspendUpdates = false;
-        this.delegateUpdates();
-    },
-
-    
-    hideTabStripItem : function(item){
-        item = this.getComponent(item);
-        var el = this.getTabEl(item);
-        if(el){
-            el.style.display = 'none';
-            this.delegateUpdates();
-        }
-        this.stack.remove(item);
-    },
+    getErrors: function(value) {
+        var me = this,
+            format = Ext.String.format,
+            clearTime = Ext.Date.clearTime,
+            errors = me.callParent(arguments),
+            disabledDays = me.disabledDays,
+            disabledDatesRE = me.disabledDatesRE,
+            minValue = me.minValue,
+            maxValue = me.maxValue,
+            len = disabledDays ? disabledDays.length : 0,
+            i = 0,
+            svalue,
+            fvalue,
+            day,
+            time;
 
-    
-    unhideTabStripItem : function(item){
-        item = this.getComponent(item);
-        var el = this.getTabEl(item);
-        if(el){
-            el.style.display = '';
-            this.delegateUpdates();
-        }
-    },
+        value = me.formatDate(value || me.processRawValue(me.getRawValue()));
 
-    
-    delegateUpdates : function(){
-        if(this.suspendUpdates){
-            return;
-        }
-        if(this.resizeTabs && this.rendered){
-            this.autoSizeTabs();
-        }
-        if(this.enableTabScroll && this.rendered){
-            this.autoScrollTabs();
+        if (value === null || value.length < 1) { 
+             return errors;
         }
-    },
 
-    
-    autoSizeTabs : function(){
-        var count = this.items.length,
-            ce = this.tabPosition != 'bottom' ? 'header' : 'footer',
-            ow = this[ce].dom.offsetWidth,
-            aw = this[ce].dom.clientWidth;
-
-        if(!this.resizeTabs || count < 1 || !aw){ 
-            return;
+        svalue = value;
+        value = me.parseDate(value);
+        if (!value) {
+            errors.push(format(me.invalidText, svalue, me.format));
+            return errors;
         }
 
-        var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.tabMargin, this.tabWidth), this.minTabWidth); 
-        this.lastTabWidth = each;
-        var lis = this.strip.query('li:not(.x-tab-edge)');
-        for(var i = 0, len = lis.length; i < len; i++) {
-            var li = lis[i],
-                inner = Ext.fly(li).child('.x-tab-strip-inner', true),
-                tw = li.offsetWidth,
-                iw = inner.offsetWidth;
-            inner.style.width = (each - (tw-iw)) + 'px';
+        time = value.getTime();
+        if (minValue && time < clearTime(minValue).getTime()) {
+            errors.push(format(me.minText, me.formatDate(minValue)));
         }
-    },
 
-    
-    adjustBodyWidth : function(w){
-        if(this.header){
-            this.header.setWidth(w);
-        }
-        if(this.footer){
-            this.footer.setWidth(w);
+        if (maxValue && time > clearTime(maxValue).getTime()) {
+            errors.push(format(me.maxText, me.formatDate(maxValue)));
         }
-        return w;
-    },
 
-    
-    setActiveTab : function(item){
-        item = this.getComponent(item);
-        if(this.fireEvent('beforetabchange', this, item, this.activeTab) === false){
-            return;
-        }
-        if(!this.rendered){
-            this.activeTab = item;
-            return;
-        }
-        if(this.activeTab != item){
-            if(this.activeTab){
-                var oldEl = this.getTabEl(this.activeTab);
-                if(oldEl){
-                    Ext.fly(oldEl).removeClass('x-tab-strip-active');
-                }
-            }
-            this.activeTab = item;
-            if(item){
-                var el = this.getTabEl(item);
-                Ext.fly(el).addClass('x-tab-strip-active');
-                this.stack.add(item);
+        if (disabledDays) {
+            day = value.getDay();
 
-                this.layout.setActiveItem(item);
-                if(this.scrolling){
-                    this.scrollToTab(item, this.animScroll);
+            for(; i < len; i++) {
+                if (day === disabledDays[i]) {
+                    errors.push(me.disabledDaysText);
+                    break;
                 }
             }
-            this.fireEvent('tabchange', this, item);
         }
+
+        fvalue = me.formatDate(value);
+        if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
+            errors.push(format(me.disabledDatesText, fvalue));
+        }
+
+        return errors;
     },
 
-    
-    getActiveTab : function(){
-        return this.activeTab || null;
+    rawToValue: function(rawValue) {
+        return this.parseDate(rawValue) || rawValue || null;
     },
 
-    
-    getItem : function(item){
-        return this.getComponent(item);
+    valueToRaw: function(value) {
+        return this.formatDate(this.parseDate(value));
     },
 
     
-    autoScrollTabs : function(){
-        this.pos = this.tabPosition=='bottom' ? this.footer : this.header;
-        var count = this.items.length,
-            ow = this.pos.dom.offsetWidth,
-            tw = this.pos.dom.clientWidth,
-            wrap = this.stripWrap,
-            wd = wrap.dom,
-            cw = wd.offsetWidth,
-            pos = this.getScrollPos(),
-            l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
 
-        if(!this.enableTabScroll || cw < 20){ 
-            return;
-        }
-        if(count == 0 || l <= tw){
+    
+    safeParse : function(value, format) {
+        var me = this,
+            utilDate = Ext.Date,
+            parsedDate,
+            result = null;
+
+        if (utilDate.formatContainsHourInfo(format)) {
             
-            wd.scrollLeft = 0;
-            wrap.setWidth(tw);
-            if(this.scrolling){
-                this.scrolling = false;
-                this.pos.removeClass('x-tab-scrolling');
-                this.scrollLeft.hide();
-                this.scrollRight.hide();
-                
-                if(Ext.isAir || Ext.isWebKit){
-                    wd.style.marginLeft = '';
-                    wd.style.marginRight = '';
-                }
-            }
-        }else{
-            if(!this.scrolling){
-                this.pos.addClass('x-tab-scrolling');
-                
-                if(Ext.isAir || Ext.isWebKit){
-                    wd.style.marginLeft = '18px';
-                    wd.style.marginRight = '18px';
-                }
-            }
-            tw -= wrap.getMargins('lr');
-            wrap.setWidth(tw > 20 ? tw : 20);
-            if(!this.scrolling){
-                if(!this.scrollLeft){
-                    this.createScrollers();
-                }else{
-                    this.scrollLeft.show();
-                    this.scrollRight.show();
-                }
-            }
-            this.scrolling = true;
-            if(pos > (l-tw)){ 
-                wd.scrollLeft = l-tw;
-            }else{ 
-                this.scrollToTab(this.activeTab, false);
+            result = utilDate.parse(value, format);
+        } else {
+            
+            parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
+            if (parsedDate) {
+                result = utilDate.clearTime(parsedDate);
             }
-            this.updateScrollButtons();
         }
+        return result;
     },
 
     
-    createScrollers : function(){
-        this.pos.addClass('x-tab-scrolling-' + this.tabPosition);
-        var h = this.stripWrap.dom.offsetHeight;
-
-        
-        var sl = this.pos.insertFirst({
-            cls:'x-tab-scroller-left'
-        });
-        sl.setHeight(h);
-        sl.addClassOnOver('x-tab-scroller-left-over');
-        this.leftRepeater = new Ext.util.ClickRepeater(sl, {
-            interval : this.scrollRepeatInterval,
-            handler: this.onScrollLeft,
-            scope: this
-        });
-        this.scrollLeft = sl;
+    getSubmitValue: function() {
+        var format = this.submitFormat || this.format,
+            value = this.getValue();
 
-        
-        var sr = this.pos.insertFirst({
-            cls:'x-tab-scroller-right'
-        });
-        sr.setHeight(h);
-        sr.addClassOnOver('x-tab-scroller-right-over');
-        this.rightRepeater = new Ext.util.ClickRepeater(sr, {
-            interval : this.scrollRepeatInterval,
-            handler: this.onScrollRight,
-            scope: this
-        });
-        this.scrollRight = sr;
+        return value ? Ext.Date.format(value, format) : '';
     },
 
     
-    getScrollWidth : function(){
-        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
+    parseDate : function(value) {
+        if(!value || Ext.isDate(value)){
+            return value;
+        }
+
+        var me = this,
+            val = me.safeParse(value, me.format),
+            altFormats = me.altFormats,
+            altFormatsArray = me.altFormatsArray,
+            i = 0,
+            len;
+
+        if (!val && altFormats) {
+            altFormatsArray = altFormatsArray || altFormats.split('|');
+            len = altFormatsArray.length;
+            for (; i < len && !val; ++i) {
+                val = me.safeParse(value, altFormatsArray[i]);
+            }
+        }
+        return val;
     },
 
     
-    getScrollPos : function(){
-        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
+    formatDate : function(date){
+        return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date;
     },
 
-    
-    getScrollArea : function(){
-        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
+    createPicker: function() {
+        var me = this,
+            format = Ext.String.format;
+
+        return Ext.create('Ext.picker.Date', {
+            pickerField: me,
+            ownerCt: me.ownerCt,
+            renderTo: document.body,
+            floating: true,
+            hidden: true,
+            focusOnShow: true,
+            minDate: me.minValue,
+            maxDate: me.maxValue,
+            disabledDatesRE: me.disabledDatesRE,
+            disabledDatesText: me.disabledDatesText,
+            disabledDays: me.disabledDays,
+            disabledDaysText: me.disabledDaysText,
+            format: me.format,
+            showToday: me.showToday,
+            startDay: me.startDay,
+            minText: format(me.minText, me.formatDate(me.minValue)),
+            maxText: format(me.maxText, me.formatDate(me.maxValue)),
+            listeners: {
+                scope: me,
+                select: me.onSelect
+            },
+            keyNavConfig: {
+                esc: function() {
+                    me.collapse();
+                }
+            }
+        });
+    },
+
+    onSelect: function(m, d) {
+        var me = this;
+
+        me.setValue(d);
+        me.fireEvent('select', me, d);
+        me.collapse();
     },
 
     
-    getScrollAnim : function(){
-        return {duration:this.scrollDuration, callback: this.updateScrollButtons, scope: this};
+    onExpand: function() {
+        var value = this.getValue();
+        this.picker.setValue(Ext.isDate(value) ? value : new Date());
     },
 
     
-    getScrollIncrement : function(){
-        return this.scrollIncrement || (this.resizeTabs ? this.lastTabWidth+2 : 100);
+    onCollapse: function() {
+        this.focus(false, 60);
     },
 
     
+    beforeBlur : function(){
+        var me = this,
+            v = me.parseDate(me.getRawValue()),
+            focusTask = me.focusTask;
 
-    scrollToTab : function(item, animate){
-        if(!item){
-            return;
+        if (focusTask) {
+            focusTask.cancel();
         }
-        var el = this.getTabEl(item),
-            pos = this.getScrollPos(),
-            area = this.getScrollArea(),
-            left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos,
-            right = left + el.offsetWidth;
-        if(left < pos){
-            this.scrollTo(left, animate);
-        }else if(right > (pos + area)){
-            this.scrollTo(right - area, animate);
+
+        if (v) {
+            me.setValue(v);
         }
-    },
+    }
 
     
-    scrollTo : function(pos, animate){
-        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
-        if(!animate){
-            this.updateScrollButtons();
+    
+    
+    
+});
+
+
+Ext.define('Ext.form.field.Display', {
+    extend:'Ext.form.field.Base',
+    alias: 'widget.displayfield',
+    requires: ['Ext.util.Format', 'Ext.XTemplate'],
+    alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
+    fieldSubTpl: [
+        '<div id="{id}" class="{fieldCls}"></div>',
+        {
+            compiled: true,
+            disableFormats: true
         }
-    },
+    ],
 
-    onWheel : function(e){
-        var d = e.getWheelDelta()*this.wheelIncrement*-1;
-        e.stopEvent();
+    
+    fieldCls: Ext.baseCSSPrefix + 'form-display-field',
+
+    
+    htmlEncode: false,
 
-        var pos = this.getScrollPos(),
-            newpos = pos + d,
-            sw = this.getScrollWidth()-this.getScrollArea();
+    validateOnChange: false,
 
-        var s = Math.max(0, Math.min(sw, newpos));
-        if(s != pos){
-            this.scrollTo(s, false);
-        }
+    initEvents: Ext.emptyFn,
+
+    submitValue: false,
+
+    isValid: function() {
+        return true;
     },
 
-    
-    onScrollRight : function(){
-        var sw = this.getScrollWidth()-this.getScrollArea(),
-            pos = this.getScrollPos(),
-            s = Math.min(sw, pos + this.getScrollIncrement());
-        if(s != pos){
-            this.scrollTo(s, this.animScroll);
-        }
+    validate: function() {
+        return true;
     },
 
-    
-    onScrollLeft : function(){
-        var pos = this.getScrollPos(),
-            s = Math.max(0, pos - this.getScrollIncrement());
-        if(s != pos){
-            this.scrollTo(s, this.animScroll);
-        }
+    getRawValue: function() {
+        return this.rawValue;
     },
 
-    
-    updateScrollButtons : function(){
-        var pos = this.getScrollPos();
-        this.scrollLeft[pos === 0 ? 'addClass' : 'removeClass']('x-tab-scroller-left-disabled');
-        this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('x-tab-scroller-right-disabled');
+    setRawValue: function(value) {
+        var me = this;
+        value = Ext.value(value, '');
+        me.rawValue = value;
+        if (me.rendered) {
+            me.inputEl.dom.innerHTML = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
+        }
+        return value;
     },
 
     
-    beforeDestroy : function() {
-        Ext.destroy(this.leftRepeater, this.rightRepeater);
-        this.deleteMembers('strip', 'edge', 'scrollLeft', 'scrollRight', 'stripWrap');
-        this.activeTab = null;
-        Ext.TabPanel.superclass.beforeDestroy.apply(this);
+    getContentTarget: function() {
+        return this.inputEl;
     }
 
     
@@ -28654,8139 +73575,7727 @@ Ext.TabPanel = Ext.extend(Ext.Panel,  {
     
     
     
+});
+
+
+Ext.define("Ext.form.field.File", {
+    extend: 'Ext.form.field.Text',
+    alias: ['widget.filefield', 'widget.fileuploadfield'],
+    alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'],
+    uses: ['Ext.button.Button', 'Ext.layout.component.field.File'],
+
+    
+    buttonText: 'Browse...',
+
+    
+    buttonOnly: false,
+
     
+    buttonMargin: 3,
+
     
+
     
+
     
+
     
+
     
-});
-Ext.reg('tabpanel', Ext.TabPanel);
+    fieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
 
+    
+    readOnly: true,
 
-Ext.TabPanel.prototype.activate = Ext.TabPanel.prototype.setActiveTab;
+    
+    componentLayout: 'filefield',
 
+    
+    onRender: function() {
+        var me = this,
+            inputEl;
 
-Ext.TabPanel.AccessStack = function(){
-    var items = [];
-    return {
-        add : function(item){
-            items.push(item);
-            if(items.length > 10){
-                items.shift();
-            }
-        },
+        me.callParent(arguments);
 
-        remove : function(item){
-            var s = [];
-            for(var i = 0, len = items.length; i < len; i++) {
-                if(items[i] != item){
-                    s.push(items[i]);
-                }
-            }
-            items = s;
-        },
+        me.createButton();
+        me.createFileInput();
+        
+        
+        
+        if (me.disabled) {
+            me.disableItems();
+        }
 
-        next : function(){
-            return items.pop();
+        inputEl = me.inputEl;
+        inputEl.dom.removeAttribute('name'); 
+        if (me.buttonOnly) {
+            inputEl.setDisplayed(false);
         }
-    };
-};
+    },
 
-Ext.Button = Ext.extend(Ext.BoxComponent, {
     
-    hidden : false,
+    createButton: function() {
+        var me = this;
+        me.button = Ext.widget('button', Ext.apply({
+            ui: me.ui,
+            renderTo: me.bodyEl,
+            text: me.buttonText,
+            cls: Ext.baseCSSPrefix + 'form-file-btn',
+            preventDefault: false,
+            style: me.buttonOnly ? '' : 'margin-left:' + me.buttonMargin + 'px'
+        }, me.buttonConfig));
+    },
+
     
-    disabled : false,
+    createFileInput : function() {
+        var me = this;
+        me.fileInputEl = me.button.el.createChild({
+            name: me.getName(),
+            cls: Ext.baseCSSPrefix + 'form-file-input',
+            tag: 'input',
+            type: 'file',
+            size: 1
+        }).on('change', me.onFileChange, me);
+    },
+
     
-    pressed : false,
+    onFileChange: function() {
+        this.lastValue = null; 
+        Ext.form.field.File.superclass.setValue.call(this, this.fileInputEl.dom.value);
+    },
 
     
+    setValue: Ext.emptyFn,
+
+    reset : function(){
+        var me = this;
+        if (me.rendered) {
+            me.fileInputEl.remove();
+            me.createFileInput();
+            me.inputEl.dom.value = '';
+        }
+        me.callParent();
+    },
 
+    onDisable: function(){
+        this.callParent();
+        this.disableItems();
+    },
     
+    disableItems: function(){
+        var file = this.fileInputEl,
+            button = this.button;
+             
+        if (file) {
+            file.dom.disabled = true;
+        }
+        if (button) {
+            button.disable();
+        }    
+    },
+
+    onEnable: function(){
+        var me = this;
+        me.callParent();
+        me.fileInputEl.dom.disabled = false;
+        me.button.enable();
+    },
+
+    isFileUpload: function() {
+        return true;
+    },
+
+    extractFileInput: function() {
+        var fileInput = this.fileInputEl.dom;
+        this.reset();
+        return fileInput;
+    },
+
+    onDestroy: function(){
+        Ext.destroyMembers(this, 'fileInputEl', 'button');
+        this.callParent();
+    }
+
+
+});
+
+
+Ext.define('Ext.form.field.Hidden', {
+    extend:'Ext.form.field.Base',
+    alias: ['widget.hiddenfield', 'widget.hidden'],
+    alternateClassName: 'Ext.form.Hidden',
 
     
-    enableToggle : false,
+    inputType : 'hidden',
+    hideLabel: true,
     
+    initComponent: function(){
+        this.formItemCls += '-hidden';
+        this.callParent();    
+    },
     
     
-    menuAlign : 'tl-bl?',
+    isEqual: function(value1, value2) {
+        return this.isEqualAsString(value1, value2);
+    },
 
     
-    
-    
-    type : 'button',
+    initEvents: Ext.emptyFn,
+    setSize : Ext.emptyFn,
+    setWidth : Ext.emptyFn,
+    setHeight : Ext.emptyFn,
+    setPosition : Ext.emptyFn,
+    setPagePosition : Ext.emptyFn,
+    markInvalid : Ext.emptyFn,
+    clearInvalid : Ext.emptyFn
+});
 
-    
-    menuClassTarget : 'tr:nth(2)',
 
-    
-    clickEvent : 'click',
+Ext.define('Ext.picker.Color', {
+    extend: 'Ext.Component',
+    requires: 'Ext.XTemplate',
+    alias: 'widget.colorpicker',
+    alternateClassName: 'Ext.ColorPalette',
 
     
-    handleMouseEvents : true,
+    componentCls : Ext.baseCSSPrefix + 'color-picker',
 
     
-    tooltipType : 'qtip',
+    selectedCls: Ext.baseCSSPrefix + 'color-picker-selected',
 
     
-    buttonSelector : 'button:first-child',
+    value : null,
 
     
-    scale : 'small',
+    clickEvent :'click',
 
     
+    allowReselect : false,
 
     
-    iconAlign : 'left',
+    colors : [
+        '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
+        '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
+        'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
+        'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
+        'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
+    ],
 
     
-    arrowAlign : 'right',
 
     
+
+    colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/,
     
-    
-    
+    renderTpl: [
+        '<tpl for="colors">',
+            '<a href="#" class="color-{.}" hidefocus="on">',
+                '<em><span style="background:#{.}" unselectable="on">&#160;</span></em>',
+            '</a>',
+        '</tpl>'
+    ],
 
+    
     initComponent : function(){
-        Ext.Button.superclass.initComponent.call(this);
+        var me = this;
 
-        this.addEvents(
-            
-            'click',
-            
-            'toggle',
+        me.callParent(arguments);
+        me.addEvents(
             
-            'mouseover',
-            
-            'mouseout',
-            
-            'menushow',
-            
-            'menuhide',
-            
-            'menutriggerover',
-            
-            'menutriggerout'
+            'select'
         );
-        if(this.menu){
-            this.menu = Ext.menu.MenuMgr.get(this.menu);
-        }
-        if(Ext.isString(this.toggleGroup)){
-            this.enableToggle = true;
+
+        if (me.handler) {
+            me.on('select', me.handler, me.scope, true);
         }
     },
 
 
-    getTemplateArgs : function(){
-        return [this.type, 'x-btn-' + this.scale + ' x-btn-icon-' + this.scale + '-' + this.iconAlign, this.getMenuClass(), this.cls, this.id];
+    
+    onRender : function(container, position){
+        var me = this,
+            clickEvent = me.clickEvent;
+
+        Ext.apply(me.renderData, {
+            itemCls: me.itemCls,
+            colors: me.colors
+        });
+        me.callParent(arguments);
+
+        me.mon(me.el, clickEvent, me.handleClick, me, {delegate: 'a'});
+        
+        if(clickEvent != 'click'){
+            me.mon(me.el, 'click', Ext.emptyFn, me, {delegate: 'a', stopEvent: true});
+        }
     },
 
     
-    setButtonClass : function(){
-        if(this.useSetClass){
-            if(!Ext.isEmpty(this.oldCls)){
-                this.el.removeClass([this.oldCls, 'x-btn-pressed']);
-            }
-            this.oldCls = (this.iconCls || this.icon) ? (this.text ? 'x-btn-text-icon' : 'x-btn-icon') : 'x-btn-noicon';
-            this.el.addClass([this.oldCls, this.pressed ? 'x-btn-pressed' : null]);
+    afterRender : function(){
+        var me = this,
+            value;
+
+        me.callParent(arguments);
+        if (me.value) {
+            value = me.value;
+            me.value = null;
+            me.select(value, true);
         }
     },
 
     
-    getMenuClass : function(){
-        return this.menu ? (this.arrowAlign != 'bottom' ? 'x-btn-arrow' : 'x-btn-arrow-bottom') : '';
+    handleClick : function(event, target){
+        var me = this,
+            color;
+
+        event.stopEvent();
+        if (!me.disabled) {
+            color = target.className.match(me.colorRe)[1];
+            me.select(color.toUpperCase());
+        }
     },
 
     
-    onRender : function(ct, position){
-        if(!this.template){
-            if(!Ext.Button.buttonTemplate){
-                
-                Ext.Button.buttonTemplate = new Ext.Template(
-                    '<table id="{4}" cellspacing="0" class="x-btn {3}"><tbody class="{1}">',
-                    '<tr><td class="x-btn-tl"><i>&#160;</i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i>&#160;</i></td></tr>',
-                    '<tr><td class="x-btn-ml"><i>&#160;</i></td><td class="x-btn-mc"><em class="{2}" unselectable="on"><button type="{0}"></button></em></td><td class="x-btn-mr"><i>&#160;</i></td></tr>',
-                    '<tr><td class="x-btn-bl"><i>&#160;</i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i>&#160;</i></td></tr>',
-                    '</tbody></table>');
-                Ext.Button.buttonTemplate.compile();
-            }
-            this.template = Ext.Button.buttonTemplate;
-        }
+    select : function(color, suppressEvent){
 
-        var btn, targs = this.getTemplateArgs();
+        var me = this,
+            selectedCls = me.selectedCls,
+            value = me.value,
+            el;
 
-        if(position){
-            btn = this.template.insertBefore(position, targs, true);
-        }else{
-            btn = this.template.append(ct, targs, true);
+        color = color.replace('#', '');
+        if (!me.rendered) {
+            me.value = color;
+            return;
         }
-        
-        this.btnEl = btn.child(this.buttonSelector);
-        this.mon(this.btnEl, {
-            scope: this,
-            focus: this.onFocus,
-            blur: this.onBlur
-        });
 
-        this.initButtonEl(btn, this.btnEl);
 
-        Ext.ButtonToggleMgr.register(this);
+        if (color != value || me.allowReselect) {
+            el = me.el;
+
+            if (me.value) {
+                el.down('a.color-' + value).removeCls(selectedCls);
+            }
+            el.down('a.color-' + color).addCls(selectedCls);
+            me.value = color;
+            if (suppressEvent !== true) {
+                me.fireEvent('select', me, color);
+            }
+        }
     },
 
     
-    initButtonEl : function(btn, btnEl){
-        this.el = btn;
-        this.setIcon(this.icon);
-        this.setText(this.text);
-        this.setIconClass(this.iconCls);
-        if(Ext.isDefined(this.tabIndex)){
-            btnEl.dom.tabIndex = this.tabIndex;
-        }
-        if(this.tooltip){
-            this.setTooltip(this.tooltip, true);
-        }
+    getValue: function(){
+        return this.value || null;
+    }
+});
 
-        if(this.handleMouseEvents){
-            this.mon(btn, {
-                scope: this,
-                mouseover: this.onMouseOver,
-                mousedown: this.onMouseDown
-            });
 
-            
-            
-        }
 
-        if(this.menu){
-            this.mon(this.menu, {
-                scope: this,
-                show: this.onMenuShow,
-                hide: this.onMenuHide
-            });
-        }
+Ext.define('Ext.layout.component.field.HtmlEditor', {
+    extend: 'Ext.layout.component.field.Field',
+    alias: ['layout.htmleditor'],
 
-        if(this.repeat){
-            var repeater = new Ext.util.ClickRepeater(btn, Ext.isObject(this.repeat) ? this.repeat : {});
-            this.mon(repeater, 'click', this.onRepeatClick, this);
-        }else{
-            this.mon(btn, this.clickEvent, this.onClick, this);
-        }
-    },
+    type: 'htmleditor',
 
-    
-    afterRender : function(){
-        Ext.Button.superclass.afterRender.call(this);
-        this.useSetClass = true;
-        this.setButtonClass();
-        this.doc = Ext.getDoc();
-        this.doAutoWidth();
-    },
+    sizeBodyContents: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            bodyEl = owner.bodyEl,
+            toolbar = owner.getToolbar(),
+            textarea = owner.textareaEl,
+            iframe = owner.iframeEl,
+            editorHeight;
 
-    
-    setIconClass : function(cls){
-        this.iconCls = cls;
-        if(this.el){
-            this.btnEl.dom.className = '';
-            this.btnEl.addClass(['x-btn-text', cls || '']);
-            this.setButtonClass();
+        if (Ext.isNumber(width)) {
+            width -= bodyEl.getFrameWidth('lr');
         }
-        return this;
-    },
+        toolbar.setWidth(width);
+        textarea.setWidth(width);
+        iframe.setWidth(width);
 
-    
-    setTooltip : function(tooltip,  initial){
-        if(this.rendered){
-            if(!initial){
-                this.clearTip();
-            }
-            if(Ext.isObject(tooltip)){
-                Ext.QuickTips.register(Ext.apply({
-                      target: this.btnEl.id
-                }, tooltip));
-                this.tooltip = tooltip;
-            }else{
-                this.btnEl.dom[this.tooltipType] = tooltip;
-            }
-        }else{
-            this.tooltip = tooltip;
+        
+        if (Ext.isNumber(height)) {
+            editorHeight = height - toolbar.getHeight() - bodyEl.getFrameWidth('tb');
+            textarea.setHeight(editorHeight);
+            iframe.setHeight(editorHeight);
         }
-        return this;
-    },
+    }
+});
 
-    
-    clearTip : function(){
-        if(Ext.isObject(this.tooltip)){
-            Ext.QuickTips.unregister(this.btnEl);
-        }
-    },
+Ext.define('Ext.form.field.HtmlEditor', {
+    extend:'Ext.Component',
+    mixins: {
+        labelable: 'Ext.form.Labelable',
+        field: 'Ext.form.field.Field'
+    },
+    alias: 'widget.htmleditor',
+    alternateClassName: 'Ext.form.HtmlEditor',
+    requires: [
+        'Ext.tip.QuickTipManager',
+        'Ext.picker.Color',
+        'Ext.toolbar.Item',
+        'Ext.toolbar.Toolbar',
+        'Ext.util.Format',
+        'Ext.layout.component.field.HtmlEditor'
+    ],
 
-    
-    beforeDestroy : function(){
-        if(this.rendered){
-            this.clearTip();
-        }
-        if(this.menu && this.destroyMenu !== false) {
-            Ext.destroy(this.btnEl, this.menu);
+    fieldSubTpl: [
+        '<div id="{cmpId}-toolbarWrap" class="{toolbarWrapCls}"></div>',
+        '<textarea id="{cmpId}-textareaEl" name="{name}" tabIndex="-1" class="{textareaCls}" ',
+            'style="{size}" autocomplete="off"></textarea>',
+        '<iframe id="{cmpId}-iframeEl" name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
+        {
+            compiled: true,
+            disableFormats: true
         }
-        Ext.destroy(this.repeater);
-    },
+    ],
 
     
-    onDestroy : function(){
-        if(this.rendered){
-            this.doc.un('mouseover', this.monitorMouseOver, this);
-            this.doc.un('mouseup', this.onMouseUp, this);
-            delete this.doc;
-            delete this.btnEl;
-            Ext.ButtonToggleMgr.unregister(this);
-        }
-        Ext.Button.superclass.onDestroy.call(this);
-    },
-
+    enableFormat : true,
     
-    doAutoWidth : function(){
-        if(this.autoWidth !== false && this.el && this.text && this.width === undefined){
-            this.el.setWidth('auto');
-            if(Ext.isIE7 && Ext.isStrict){
-                var ib = this.btnEl;
-                if(ib && ib.getWidth() > 20){
-                    ib.clip();
-                    ib.setWidth(Ext.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
-                }
-            }
-            if(this.minWidth){
-                if(this.el.getWidth() < this.minWidth){
-                    this.el.setWidth(this.minWidth);
-                }
-            }
-        }
-    },
-
+    enableFontSize : true,
     
-    setHandler : function(handler, scope){
-        this.handler = handler;
-        this.scope = scope;
-        return this;
-    },
-
+    enableColors : true,
     
-    setText : function(text){
-        this.text = text;
-        if(this.el){
-            this.btnEl.update(text || '&#160;');
-            this.setButtonClass();
-        }
-        this.doAutoWidth();
-        return this;
-    },
-
+    enableAlignments : true,
     
-    setIcon : function(icon){
-        this.icon = icon;
-        if(this.el){
-            this.btnEl.setStyle('background-image', icon ? 'url(' + icon + ')' : '');
-            this.setButtonClass();
-        }
-        return this;
-    },
-
+    enableLists : true,
     
-    getText : function(){
-        return this.text;
-    },
+    enableSourceEdit : true,
+    
+    enableLinks : true,
+    
+    enableFont : true,
+    
+    createLinkText : 'Please enter the URL for the link:',
+    
+    defaultLinkValue : 'http:/'+'/',
+    
+    fontFamilies : [
+        'Arial',
+        'Courier New',
+        'Tahoma',
+        'Times New Roman',
+        'Verdana'
+    ],
+    defaultFont: 'tahoma',
+    
+    defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
+
+    fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
+
+    componentLayout: 'htmleditor',
 
     
-    toggle : function(state, suppressEvent){
-        state = state === undefined ? !this.pressed : !!state;
-        if(state != this.pressed){
-            if(this.rendered){
-                this.el[state ? 'addClass' : 'removeClass']('x-btn-pressed');
-            }
-            this.pressed = state;
-            if(!suppressEvent){
-                this.fireEvent('toggle', this, state);
-                if(this.toggleHandler){
-                    this.toggleHandler.call(this.scope || this, this, state);
-                }
-            }
-        }
-        return this;
-    },
+    initialized : false,
+    activated : false,
+    sourceEditMode : false,
+    iframePad:3,
+    hideMode:'offsets',
+
+    maskOnDisable: true,
 
     
-    onDisable : function(){
-        this.onDisableChange(true);
+    initComponent : function(){
+        var me = this;
+
+        me.addEvents(
+            
+            'initialize',
+            
+            'activate',
+             
+            'beforesync',
+             
+            'beforepush',
+             
+            'sync',
+             
+            'push',
+             
+            'editmodechange'
+        );
+
+        me.callParent(arguments);
+
+        
+        me.initLabelable();
+        me.initField();
     },
 
     
-    onEnable : function(){
-        this.onDisableChange(false);
-    },
+    createToolbar : function(editor){
+        var me = this,
+            items = [],
+            tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
+            baseCSSPrefix = Ext.baseCSSPrefix,
+            fontSelectItem, toolbar, undef;
 
-    onDisableChange : function(disabled){
-        if(this.el){
-            if(!Ext.isIE6 || !this.text){
-                this.el[disabled ? 'addClass' : 'removeClass'](this.disabledClass);
-            }
-            this.el.dom.disabled = disabled;
+        function btn(id, toggle, handler){
+            return {
+                itemId : id,
+                cls : baseCSSPrefix + 'btn-icon',
+                iconCls: baseCSSPrefix + 'edit-'+id,
+                enableToggle:toggle !== false,
+                scope: editor,
+                handler:handler||editor.relayBtnCmd,
+                clickEvent:'mousedown',
+                tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
+                overflowText: editor.buttonTips[id].title || undef,
+                tabIndex:-1
+            };
         }
-        this.disabled = disabled;
-    },
 
-    
-    showMenu : function(){
-        if(this.rendered && this.menu){
-            if(this.tooltip){
-                Ext.QuickTips.getQuickTip().cancelShow(this.btnEl);
-            }
-            if(this.menu.isVisible()){
-                this.menu.hide();
-            }
-            this.menu.ownerCt = this;
-            this.menu.show(this.el, this.menuAlign);
+
+        if (me.enableFont && !Ext.isSafari2) {
+            fontSelectItem = Ext.widget('component', {
+                renderTpl: [
+                    '<select id="{id}-selectEl" class="{cls}">',
+                        '<tpl for="fonts">',
+                            '<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
+                        '</tpl>',
+                    '</select>'
+                ],
+                renderData: {
+                    cls: baseCSSPrefix + 'font-select',
+                    fonts: me.fontFamilies,
+                    defaultFont: me.defaultFont
+                },
+                childEls: ['selectEl'],
+                onDisable: function() {
+                    var selectEl = this.selectEl;
+                    if (selectEl) {
+                        selectEl.dom.disabled = true;
+                    }
+                    Ext.Component.superclass.onDisable.apply(this, arguments);
+                },
+                onEnable: function() {
+                    var selectEl = this.selectEl;
+                    if (selectEl) {
+                        selectEl.dom.disabled = false;
+                    }
+                    Ext.Component.superclass.onEnable.apply(this, arguments);
+                }
+            });
+
+            items.push(
+                fontSelectItem,
+                '-'
+            );
         }
-        return this;
-    },
 
-    
-    hideMenu : function(){
-        if(this.hasVisibleMenu()){
-            this.menu.hide();
+        if (me.enableFormat) {
+            items.push(
+                btn('bold'),
+                btn('italic'),
+                btn('underline')
+            );
         }
-        return this;
-    },
 
-    
-    hasVisibleMenu : function(){
-        return this.menu && this.menu.ownerCt == this && this.menu.isVisible();
-    },
-    
-    
-    onRepeatClick : function(repeat, e){
-        this.onClick(e);
-    },
+        if (me.enableFontSize) {
+            items.push(
+                '-',
+                btn('increasefontsize', false, me.adjustFont),
+                btn('decreasefontsize', false, me.adjustFont)
+            );
+        }
 
-    
-    onClick : function(e){
-        if(e){
-            e.preventDefault();
+        if (me.enableColors) {
+            items.push(
+                '-', {
+                    itemId: 'forecolor',
+                    cls: baseCSSPrefix + 'btn-icon',
+                    iconCls: baseCSSPrefix + 'edit-forecolor',
+                    overflowText: editor.buttonTips.forecolor.title,
+                    tooltip: tipsEnabled ? editor.buttonTips.forecolor || undef : undef,
+                    tabIndex:-1,
+                    menu : Ext.widget('menu', {
+                        plain: true,
+                        items: [{
+                            xtype: 'colorpicker',
+                            allowReselect: true,
+                            focus: Ext.emptyFn,
+                            value: '000000',
+                            plain: true,
+                            clickEvent: 'mousedown',
+                            handler: function(cp, color) {
+                                me.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+                                me.deferFocus();
+                                this.up('menu').hide();
+                            }
+                        }]
+                    })
+                }, {
+                    itemId: 'backcolor',
+                    cls: baseCSSPrefix + 'btn-icon',
+                    iconCls: baseCSSPrefix + 'edit-backcolor',
+                    overflowText: editor.buttonTips.backcolor.title,
+                    tooltip: tipsEnabled ? editor.buttonTips.backcolor || undef : undef,
+                    tabIndex:-1,
+                    menu : Ext.widget('menu', {
+                        plain: true,
+                        items: [{
+                            xtype: 'colorpicker',
+                            focus: Ext.emptyFn,
+                            value: 'FFFFFF',
+                            plain: true,
+                            allowReselect: true,
+                            clickEvent: 'mousedown',
+                            handler: function(cp, color) {
+                                if (Ext.isGecko) {
+                                    me.execCmd('useCSS', false);
+                                    me.execCmd('hilitecolor', color);
+                                    me.execCmd('useCSS', true);
+                                    me.deferFocus();
+                                } else {
+                                    me.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
+                                    me.deferFocus();
+                                }
+                                this.up('menu').hide();
+                            }
+                        }]
+                    })
+                }
+            );
         }
-        if(e.button !== 0){
-            return;
+
+        if (me.enableAlignments) {
+            items.push(
+                '-',
+                btn('justifyleft'),
+                btn('justifycenter'),
+                btn('justifyright')
+            );
         }
-        if(!this.disabled){
-            if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
-                this.toggle();
+
+        if (!Ext.isSafari2) {
+            if (me.enableLinks) {
+                items.push(
+                    '-',
+                    btn('createlink', false, me.createLink)
+                );
             }
-            if(this.menu && !this.hasVisibleMenu() && !this.ignoreNextClick){
-                this.showMenu();
+
+            if (me.enableLists) {
+                items.push(
+                    '-',
+                    btn('insertorderedlist'),
+                    btn('insertunorderedlist')
+                );
             }
-            this.fireEvent('click', this, e);
-            if(this.handler){
-                
-                this.handler.call(this.scope || this, this, e);
+            if (me.enableSourceEdit) {
+                items.push(
+                    '-',
+                    btn('sourceedit', true, function(btn){
+                        me.toggleSourceEdit(!me.sourceEditMode);
+                    })
+                );
             }
         }
-    },
 
-    
-    isMenuTriggerOver : function(e, internal){
-        return this.menu && !internal;
-    },
+        
+        toolbar = Ext.widget('toolbar', {
+            renderTo: me.toolbarWrap,
+            enableOverflow: true,
+            items: items
+        });
 
-    
-    isMenuTriggerOut : function(e, internal){
-        return this.menu && !internal;
-    },
+        if (fontSelectItem) {
+            me.fontSelect = fontSelectItem.selectEl;
 
-    
-    onMouseOver : function(e){
-        if(!this.disabled){
-            var internal = e.within(this.el,  true);
-            if(!internal){
-                this.el.addClass('x-btn-over');
-                if(!this.monitoringMouseOver){
-                    this.doc.on('mouseover', this.monitorMouseOver, this);
-                    this.monitoringMouseOver = true;
-                }
-                this.fireEvent('mouseover', this, e);
-            }
-            if(this.isMenuTriggerOver(e, internal)){
-                this.fireEvent('menutriggerover', this, this.menu, e);
-            }
+            me.mon(me.fontSelect, 'change', function(){
+                me.relayCmd('fontname', me.fontSelect.dom.value);
+                me.deferFocus();
+            });
         }
-    },
 
-    
-    monitorMouseOver : function(e){
-        if(e.target != this.el.dom && !e.within(this.el)){
-            if(this.monitoringMouseOver){
-                this.doc.un('mouseover', this.monitorMouseOver, this);
-                this.monitoringMouseOver = false;
-            }
-            this.onMouseOut(e);
-        }
-    },
+        
+        me.mon(toolbar.el, 'click', function(e){
+            e.preventDefault();
+        });
 
-    
-    onMouseOut : function(e){
-        var internal = e.within(this.el) && e.target != this.el.dom;
-        this.el.removeClass('x-btn-over');
-        this.fireEvent('mouseout', this, e);
-        if(this.isMenuTriggerOut(e, internal)){
-            this.fireEvent('menutriggerout', this, this.menu, e);
-        }
+        me.toolbar = toolbar;
     },
 
-    focus : function() {
-        this.btnEl.focus();
+    onDisable: function() {
+        this.bodyEl.mask();
+        this.callParent(arguments);
     },
 
-    blur : function() {
-        this.btnEl.blur();
+    onEnable: function() {
+        this.bodyEl.unmask();
+        this.callParent(arguments);
     },
 
     
-    onFocus : function(e){
-        if(!this.disabled){
-            this.el.addClass('x-btn-focus');
+    setReadOnly: function(readOnly) {
+        var me = this,
+            textareaEl = me.textareaEl,
+            iframeEl = me.iframeEl,
+            body;
+
+        me.readOnly = readOnly;
+
+        if (textareaEl) {
+            textareaEl.dom.readOnly = readOnly;
+        }
+
+        if (me.initialized) {
+            body = me.getEditorBody();
+            if (Ext.isIE) {
+                
+                iframeEl.setDisplayed(false);
+                body.contentEditable = !readOnly;
+                iframeEl.setDisplayed(true);
+            } else {
+                me.setDesignMode(!readOnly);
+            }
+            if (body) {
+                body.style.cursor = readOnly ? 'default' : 'text';
+            }
+            me.disableItems(readOnly);
         }
     },
-    
-    onBlur : function(e){
-        this.el.removeClass('x-btn-focus');
-    },
 
     
-    getClickEl : function(e, isUp){
-       return this.el;
+    getDocMarkup: function() {
+        var me = this,
+            h = me.iframeEl.getHeight() - me.iframePad * 2;
+        return Ext.String.format('<html><head><style type="text/css">body{border:0;margin:0;padding:{0}px;height:{1}px;box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;cursor:text}</style></head><body></body></html>', me.iframePad, h);
     },
 
     
-    onMouseDown : function(e){
-        if(!this.disabled && e.button === 0){
-            this.getClickEl(e).addClass('x-btn-click');
-            this.doc.on('mouseup', this.onMouseUp, this);
-        }
-    },
-    
-    onMouseUp : function(e){
-        if(e.button === 0){
-            this.getClickEl(e, true).removeClass('x-btn-click');
-            this.doc.un('mouseup', this.onMouseUp, this);
-        }
-    },
-    
-    onMenuShow : function(e){
-        if(this.menu.ownerCt == this){
-            this.menu.ownerCt = this;
-            this.ignoreNextClick = 0;
-            this.el.addClass('x-btn-menu-active');
-            this.fireEvent('menushow', this, this.menu);
-        }
+    getEditorBody: function() {
+        var doc = this.getDoc();
+        return doc.body || doc.documentElement;
     },
+
     
-    onMenuHide : function(e){
-        if(this.menu.ownerCt == this){
-            this.el.removeClass('x-btn-menu-active');
-            this.ignoreNextClick = this.restoreClick.defer(250, this);
-            this.fireEvent('menuhide', this, this.menu);
-            delete this.menu.ownerCt;
-        }
+    getDoc: function() {
+        return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
     },
 
     
-    restoreClick : function(){
-        this.ignoreNextClick = 0;
-    }
+    getWin: function() {
+        return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
+    },
 
     
-    
-    
-    
-    
-    
-});
-Ext.reg('button', Ext.Button);
-
-
-Ext.ButtonToggleMgr = function(){
-   var groups = {};
-
-   function toggleGroup(btn, state){
-       if(state){
-           var g = groups[btn.toggleGroup];
-           for(var i = 0, l = g.length; i < l; i++){
-               if(g[i] != btn){
-                   g[i].toggle(false);
-               }
-           }
-       }
-   }
+    onRender: function() {
+        var me = this;
 
-   return {
-       register : function(btn){
-           if(!btn.toggleGroup){
-               return;
-           }
-           var g = groups[btn.toggleGroup];
-           if(!g){
-               g = groups[btn.toggleGroup] = [];
-           }
-           g.push(btn);
-           btn.on('toggle', toggleGroup);
-       },
+        me.onLabelableRender();
 
-       unregister : function(btn){
-           if(!btn.toggleGroup){
-               return;
-           }
-           var g = groups[btn.toggleGroup];
-           if(g){
-               g.remove(btn);
-               btn.un('toggle', toggleGroup);
-           }
-       },
+        me.addChildEls('toolbarWrap', 'iframeEl', 'textareaEl');
 
-       
-       getPressed : function(group){
-           var g = groups[group];
-           if(g){
-               for(var i = 0, len = g.length; i < len; i++){
-                   if(g[i].pressed === true){
-                       return g[i];
-                   }
-               }
-           }
-           return null;
-       }
-   };
-}();
+        me.callParent(arguments);
 
-Ext.SplitButton = Ext.extend(Ext.Button, {
-       
-    arrowSelector : 'em',
-    split: true,
+        me.textareaEl.dom.value = me.value || '';
 
-    
-    initComponent : function(){
-        Ext.SplitButton.superclass.initComponent.call(this);
         
-        this.addEvents("arrowclick");
+        me.monitorTask = Ext.TaskManager.start({
+            run: me.checkDesignMode,
+            scope: me,
+            interval:100
+        });
+
+        me.createToolbar(me);
+        me.disableItems(true);
     },
 
-    
-    onRender : function(){
-        Ext.SplitButton.superclass.onRender.apply(this, arguments);
-        if(this.arrowTooltip){
-            this.el.child(this.arrowSelector).dom[this.tooltipType] = this.arrowTooltip;
+    initRenderTpl: function() {
+        var me = this;
+        if (!me.hasOwnProperty('renderTpl')) {
+            me.renderTpl = me.getTpl('labelableRenderTpl');
         }
+        return me.callParent();
     },
 
-    
-    setArrowHandler : function(handler, scope){
-        this.arrowHandler = handler;
-        this.scope = scope;
+    initRenderData: function() {
+        return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
     },
 
-    getMenuClass : function(){
-        return 'x-btn-split' + (this.arrowAlign == 'bottom' ? '-bottom' : '');
+    getSubTplData: function() {
+        var cssPrefix = Ext.baseCSSPrefix;
+        return {
+            cmpId: this.id,
+            id: this.getInputId(),
+            toolbarWrapCls: cssPrefix + 'html-editor-tb',
+            textareaCls: cssPrefix + 'hidden',
+            iframeName: Ext.id(),
+            iframeSrc: Ext.SSL_SECURE_URL,
+            size: 'height:100px;'
+        };
     },
 
-    isClickOnArrow : function(e){
-       if (this.arrowAlign != 'bottom') {
-           var visBtn = this.el.child('em.x-btn-split');
-           var right = visBtn.getRegion().right - visBtn.getPadding('r');
-           return e.getPageX() > right;
-       } else {
-           return e.getPageY() > this.btnEl.getRegion().bottom;
-       }
+    getSubTplMarkup: function() {
+        var data = this.getSubTplData();
+        return this.getTpl('fieldSubTpl').apply(data);
     },
 
-    
-    onClick : function(e, t){
-        e.preventDefault();
-        if(!this.disabled){
-            if(this.isClickOnArrow(e)){
-                if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
-                    this.showMenu();
-                }
-                this.fireEvent("arrowclick", this, e);
-                if(this.arrowHandler){
-                    this.arrowHandler.call(this.scope || this, this, e);
-                }
-            }else{
-                if(this.enableToggle){
-                    this.toggle();
-                }
-                this.fireEvent("click", this, e);
-                if(this.handler){
-                    this.handler.call(this.scope || this, this, e);
-                }
-            }
-        }
+    getBodyNaturalWidth: function() {
+        return 565;
     },
 
-    
-    isMenuTriggerOver : function(e){
-        return this.menu && e.target.tagName == this.arrowSelector;
-    },
+    initFrameDoc: function() {
+        var me = this,
+            doc, task;
 
-    
-    isMenuTriggerOut : function(e, internal){
-        return this.menu && e.target.tagName != this.arrowSelector;
-    }
-});
+        Ext.TaskManager.stop(me.monitorTask);
 
-Ext.reg('splitbutton', Ext.SplitButton);
-Ext.CycleButton = Ext.extend(Ext.SplitButton, {
-    
-    
-    
-    
-    
-    
+        doc = me.getDoc();
+        me.win = me.getWin();
 
-    
-    getItemText : function(item){
-        if(item && this.showText === true){
-            var text = '';
-            if(this.prependText){
-                text += this.prependText;
-            }
-            text += item.text;
-            return text;
+        doc.open();
+        doc.write(me.getDocMarkup());
+        doc.close();
+
+        task = { 
+            run: function() {
+                var doc = me.getDoc();
+                if (doc.body || doc.readyState === 'complete') {
+                    Ext.TaskManager.stop(task);
+                    me.setDesignMode(true);
+                    Ext.defer(me.initEditor, 10, me);
+                }
+            },
+            interval : 10,
+            duration:10000,
+            scope: me
+        };
+        Ext.TaskManager.start(task);
+    },
+
+    checkDesignMode: function() {
+        var me = this,
+            doc = me.getDoc();
+        if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) {
+            me.initFrameDoc();
         }
-        return undefined;
     },
 
     
-    setActiveItem : function(item, suppressEvent){
-        if(!Ext.isObject(item)){
-            item = this.menu.getComponent(item);
-        }
-        if(item){
-            if(!this.rendered){
-                this.text = this.getItemText(item);
-                this.iconCls = item.iconCls;
-            }else{
-                var t = this.getItemText(item);
-                if(t){
-                    this.setText(t);
-                }
-                this.setIconClass(item.iconCls);
-            }
-            this.activeItem = item;
-            if(!item.checked){
-                item.setChecked(true, false);
-            }
-            if(this.forceIcon){
-                this.setIconClass(this.forceIcon);
-            }
-            if(!suppressEvent){
-                this.fireEvent('change', this, item);
+    setDesignMode: function(mode) {
+        var me = this,
+            doc = me.getDoc();
+        if (doc) {
+            if (me.readOnly) {
+                mode = false;
             }
+            doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
         }
     },
 
     
-    getActiveItem : function(){
-        return this.activeItem;
+    getDesignMode: function() {
+        var doc = this.getDoc();
+        return !doc ? '' : String(doc.designMode).toLowerCase();
+    },
+
+    disableItems: function(disabled) {
+        this.getToolbar().items.each(function(item){
+            if(item.getItemId() !== 'sourceedit'){
+                item.setDisabled(disabled);
+            }
+        });
     },
 
     
-    initComponent : function(){
-        this.addEvents(
-            
-            "change"
-        );
+    toggleSourceEdit: function(sourceEditMode) {
+        var me = this,
+            iframe = me.iframeEl,
+            textarea = me.textareaEl,
+            hiddenCls = Ext.baseCSSPrefix + 'hidden',
+            btn = me.getToolbar().getComponent('sourceedit');
 
-        if(this.changeHandler){
-            this.on('change', this.changeHandler, this.scope||this);
-            delete this.changeHandler;
+        if (!Ext.isBoolean(sourceEditMode)) {
+            sourceEditMode = !me.sourceEditMode;
         }
+        me.sourceEditMode = sourceEditMode;
 
-        this.itemCount = this.items.length;
-
-        this.menu = {cls:'x-cycle-menu', items:[]};
-        var checked = 0;
-        Ext.each(this.items, function(item, i){
-            Ext.apply(item, {
-                group: item.group || this.id,
-                itemIndex: i,
-                checkHandler: this.checkHandler,
-                scope: this,
-                checked: item.checked || false
-            });
-            this.menu.items.push(item);
-            if(item.checked){
-                checked = i;
+        if (btn.pressed !== sourceEditMode) {
+            btn.toggle(sourceEditMode);
+        }
+        if (sourceEditMode) {
+            me.disableItems(true);
+            me.syncValue();
+            iframe.addCls(hiddenCls);
+            textarea.removeCls(hiddenCls);
+            textarea.dom.removeAttribute('tabIndex');
+            textarea.focus();
+        }
+        else {
+            if (me.initialized) {
+                me.disableItems(me.readOnly);
             }
-        }, this);
-        Ext.CycleButton.superclass.initComponent.call(this);
-        this.on('click', this.toggleSelected, this);
-        this.setActiveItem(checked, true);
+            me.pushValue();
+            iframe.removeCls(hiddenCls);
+            textarea.addCls(hiddenCls);
+            textarea.dom.setAttribute('tabIndex', -1);
+            me.deferFocus();
+        }
+        me.fireEvent('editmodechange', me, sourceEditMode);
+        me.doComponentLayout();
     },
 
     
-    checkHandler : function(item, pressed){
-        if(pressed){
-            this.setActiveItem(item);
+    createLink : function() {
+        var url = prompt(this.createLinkText, this.defaultLinkValue);
+        if (url && url !== 'http:/'+'/') {
+            this.relayCmd('createlink', url);
         }
     },
 
+    clearInvalid: Ext.emptyFn,
+
     
-    toggleSelected : function(){
-        var m = this.menu;
-        m.render();
-        
-        if(!m.hasLayout){
-            m.doLayout();
-        }
-        
-        var nextIdx, checkItem;
-        for (var i = 1; i < this.itemCount; i++) {
-            nextIdx = (this.activeItem.itemIndex + i) % this.itemCount;
-            
-            checkItem = m.items.itemAt(nextIdx);
-            
-            if (!checkItem.disabled) {
-                checkItem.setChecked(true);
-                break;
-            }
+    setValue: function(value) {
+        var me = this,
+            textarea = me.textareaEl;
+        me.mixins.field.setValue.call(me, value);
+        if (value === null || value === undefined) {
+            value = '';
         }
-    }
-});
-Ext.reg('cycle', Ext.CycleButton);
-Ext.Toolbar = function(config){
-    if(Ext.isArray(config)){
-        config = {items: config, layout: 'toolbar'};
-    } else {
-        config = Ext.apply({
-            layout: 'toolbar'
-        }, config);
-        if(config.buttons) {
-            config.items = config.buttons;
+        if (textarea) {
+            textarea.dom.value = value;
         }
-    }
-    Ext.Toolbar.superclass.constructor.call(this, config);
-};
-
-(function(){
-
-var T = Ext.Toolbar;
-
-Ext.extend(T, Ext.Container, {
-
-    defaultType: 'button',
-
-    
-
-    enableOverflow : false,
+        me.pushValue();
+        return this;
+    },
 
     
-    
-
-    trackMenus : true,
-    internalDefaults: {removeMode: 'container', hideParent: true},
-    toolbarCls: 'x-toolbar',
-
-    initComponent : function(){
-        T.superclass.initComponent.call(this);
+    cleanHtml: function(html) {
+        html = String(html);
+        if (Ext.isWebKit) { 
+            html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
+        }
 
         
-        this.addEvents('overflowchange');
+        if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
+            html = html.substring(1);
+        }
+        return html;
     },
 
     
-    onRender : function(ct, position){
-        if(!this.el){
-            if(!this.autoCreate){
-                this.autoCreate = {
-                    cls: this.toolbarCls + ' x-small-editor'
-                };
+    syncValue : function(){
+        var me = this,
+            body, html, bodyStyle, match;
+        if (me.initialized) {
+            body = me.getEditorBody();
+            html = body.innerHTML;
+            if (Ext.isWebKit) {
+                bodyStyle = body.getAttribute('style'); 
+                match = bodyStyle.match(/text-align:(.*?);/i);
+                if (match && match[1]) {
+                    html = '<div style="' + match[0] + '">' + html + '</div>';
+                }
+            }
+            html = me.cleanHtml(html);
+            if (me.fireEvent('beforesync', me, html) !== false) {
+                me.textareaEl.dom.value = html;
+                me.fireEvent('sync', me, html);
             }
-            this.el = ct.createChild(Ext.apply({ id: this.id },this.autoCreate), position);
-            Ext.Toolbar.superclass.onRender.apply(this, arguments);
         }
     },
 
     
-
-    
-    lookupComponent : function(c){
-        if(Ext.isString(c)){
-            if(c == '-'){
-                c = new T.Separator();
-            }else if(c == ' '){
-                c = new T.Spacer();
-            }else if(c == '->'){
-                c = new T.Fill();
-            }else{
-                c = new T.TextItem(c);
-            }
-            this.applyDefaults(c);
-        }else{
-            if(c.isFormField || c.render){ 
-                c = this.createComponent(c);
-            }else if(c.tag){ 
-                c = new T.Item({autoEl: c});
-            }else if(c.tagName){ 
-                c = new T.Item({el:c});
-            }else if(Ext.isObject(c)){ 
-                c = c.xtype ? this.createComponent(c) : this.constructButton(c);
-            }
+    getValue : function() {
+        var me = this,
+            value;
+        if (!me.sourceEditMode) {
+            me.syncValue();
         }
-        return c;
+        value = me.rendered ? me.textareaEl.dom.value : me.value;
+        me.value = value;
+        return value;
     },
 
     
-    applyDefaults : function(c){
-        if(!Ext.isString(c)){
-            c = Ext.Toolbar.superclass.applyDefaults.call(this, c);
-            var d = this.internalDefaults;
-            if(c.events){
-                Ext.applyIf(c.initialConfig, d);
-                Ext.apply(c, d);
-            }else{
-                Ext.applyIf(c, d);
+    pushValue: function() {
+        var me = this,
+            v;
+        if(me.initialized){
+            v = me.textareaEl.dom.value || '';
+            if (!me.activated && v.length < 1) {
+                v = me.defaultValue;
+            }
+            if (me.fireEvent('beforepush', me, v) !== false) {
+                me.getEditorBody().innerHTML = v;
+                if (Ext.isGecko) {
+                    
+                    me.setDesignMode(false);  
+                    me.setDesignMode(true);
+                }
+                me.fireEvent('push', me, v);
             }
         }
-        return c;
     },
 
     
-    addSeparator : function(){
-        return this.add(new T.Separator());
+    deferFocus : function(){
+         this.focus(false, true);
     },
 
-    
-    addSpacer : function(){
-        return this.add(new T.Spacer());
+    getFocusEl: function() {
+        var me = this,
+            win = me.win;
+        return win && !me.sourceEditMode ? win : me.textareaEl;
     },
 
     
-    addFill : function(){
-        this.add(new T.Fill());
-    },
+    initEditor : function(){
+        
+        try {
+            var me = this,
+                dbody = me.getEditorBody(),
+                ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
+                doc,
+                fn;
 
-    
-    addElement : function(el){
-        return this.addItem(new T.Item({el:el}));
-    },
+            ss['background-attachment'] = 'fixed'; 
+            dbody.bgProperties = 'fixed'; 
 
-    
-    addItem : function(item){
-        return this.add.apply(this, arguments);
-    },
+            Ext.DomHelper.applyStyles(dbody, ss);
 
-    
-    addButton : function(config){
-        if(Ext.isArray(config)){
-            var buttons = [];
-            for(var i = 0, len = config.length; i < len; i++) {
-                buttons.push(this.addButton(config[i]));
-            }
-            return buttons;
-        }
-        return this.add(this.constructButton(config));
-    },
+            doc = me.getDoc();
 
-    
-    addText : function(text){
-        return this.addItem(new T.TextItem(text));
-    },
+            if (doc) {
+                try {
+                    Ext.EventManager.removeAll(doc);
+                } catch(e) {}
+            }
 
-    
-    addDom : function(config){
-        return this.add(new T.Item({autoEl: config}));
-    },
+            
+            fn = Ext.Function.bind(me.onEditorEvent, me);
+            Ext.EventManager.on(doc, {
+                mousedown: fn,
+                dblclick: fn,
+                click: fn,
+                keyup: fn,
+                buffer:100
+            });
 
-    
-    addField : function(field){
-        return this.add(field);
-    },
+            
+            
+            
+            
+            
+            fn = me.onRelayedEvent;
+            Ext.EventManager.on(doc, {
+                mousedown: fn, 
+                mousemove: fn, 
+                mouseup: fn,   
+                click: fn,     
+                dblclick: fn,  
+                scope: me
+            });
 
-    
-    insertButton : function(index, item){
-        if(Ext.isArray(item)){
-            var buttons = [];
-            for(var i = 0, len = item.length; i < len; i++) {
-               buttons.push(this.insertButton(index + i, item[i]));
+            if (Ext.isGecko) {
+                Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
+            }
+            if (me.fixKeys) {
+                Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
             }
-            return buttons;
-        }
-        return Ext.Toolbar.superclass.insert.call(this, index, item);
-    },
 
-    
-    trackMenu : function(item, remove){
-        if(this.trackMenus && item.menu){
-            var method = remove ? 'mun' : 'mon';
-            this[method](item, 'menutriggerover', this.onButtonTriggerOver, this);
-            this[method](item, 'menushow', this.onButtonMenuShow, this);
-            this[method](item, 'menuhide', this.onButtonMenuHide, this);
+            
+            Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
+            doc.editorInitialized = true;
+
+            me.initialized = true;
+            me.pushValue();
+            me.setReadOnly(me.readOnly);
+            me.fireEvent('initialize', me);
+        } catch(ex) {
+            
         }
     },
 
     
-    constructButton : function(item){
-        var b = item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
-        return b;
-    },
+    beforeDestroy : function(){
+        var me = this,
+            monitorTask = me.monitorTask,
+            doc, prop;
 
-    
-    onAdd : function(c){
-        Ext.Toolbar.superclass.onAdd.call(this);
-        this.trackMenu(c);
-        if(this.disabled){
-            c.disable();
+        if (monitorTask) {
+            Ext.TaskManager.stop(monitorTask);
+        }
+        if (me.rendered) {
+            try {
+                doc = me.getDoc();
+                if (doc) {
+                    Ext.EventManager.removeAll(doc);
+                    for (prop in doc) {
+                        if (doc.hasOwnProperty(prop)) {
+                            delete doc[prop];
+                        }
+                    }
+                }
+            } catch(e) {
+                
+            }
+            Ext.destroyMembers(me, 'tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
         }
+        me.callParent();
     },
 
     
-    onRemove : function(c){
-        Ext.Toolbar.superclass.onRemove.call(this);
-        this.trackMenu(c, true);
-    },
+    onRelayedEvent: function (event) {
+        
 
-    
-    onDisable : function(){
-        this.items.each(function(item){
-             if(item.disable){
-                 item.disable();
-             }
-        });
+        var iframeEl = this.iframeEl,
+            iframeXY = iframeEl.getXY(),
+            eventXY = event.getXY();
+
+        
+        
+        event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
+
+        event.injectEvent(iframeEl); 
+
+        event.xy = eventXY; 
     },
 
     
-    onEnable : function(){
-        this.items.each(function(item){
-             if(item.enable){
-                 item.enable();
-             }
-        });
+    onFirstFocus : function(){
+        var me = this,
+            selection, range;
+        me.activated = true;
+        me.disableItems(me.readOnly);
+        if (Ext.isGecko) { 
+            me.win.focus();
+            selection = me.win.getSelection();
+            if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
+                range = selection.getRangeAt(0);
+                range.selectNodeContents(me.getEditorBody());
+                range.collapse(true);
+                me.deferFocus();
+            }
+            try {
+                me.execCmd('useCSS', true);
+                me.execCmd('styleWithCSS', false);
+            } catch(e) {
+                
+            }
+        }
+        me.fireEvent('activate', me);
     },
 
     
-    onButtonTriggerOver : function(btn){
-        if(this.activeMenuBtn && this.activeMenuBtn != btn){
-            this.activeMenuBtn.hideMenu();
-            btn.showMenu();
-            this.activeMenuBtn = btn;
+    adjustFont: function(btn) {
+        var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1,
+            size = this.getDoc().queryCommandValue('FontSize') || '2',
+            isPxSize = Ext.isString(size) && size.indexOf('px') !== -1,
+            isSafari;
+        size = parseInt(size, 10);
+        if (isPxSize) {
+            
+            
+            if (size <= 10) {
+                size = 1 + adjust;
+            }
+            else if (size <= 13) {
+                size = 2 + adjust;
+            }
+            else if (size <= 16) {
+                size = 3 + adjust;
+            }
+            else if (size <= 18) {
+                size = 4 + adjust;
+            }
+            else if (size <= 24) {
+                size = 5 + adjust;
+            }
+            else {
+                size = 6 + adjust;
+            }
+            size = Ext.Number.constrain(size, 1, 6);
+        } else {
+            isSafari = Ext.isSafari;
+            if (isSafari) { 
+                adjust *= 2;
+            }
+            size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
         }
+        this.execCmd('FontSize', size);
     },
 
     
-    onButtonMenuShow : function(btn){
-        this.activeMenuBtn = btn;
+    onEditorEvent: function(e) {
+        this.updateToolbar();
     },
 
     
-    onButtonMenuHide : function(btn){
-        delete this.activeMenuBtn;
-    }
-});
-Ext.reg('toolbar', Ext.Toolbar);
-
+    updateToolbar: function() {
+        var me = this,
+            btns, doc, name, fontSelect;
 
-T.Item = Ext.extend(Ext.BoxComponent, {
-    hideParent: true, 
-    enable:Ext.emptyFn,
-    disable:Ext.emptyFn,
-    focus:Ext.emptyFn
-    
-});
-Ext.reg('tbitem', T.Item);
+        if (me.readOnly) {
+            return;
+        }
 
+        if (!me.activated) {
+            me.onFirstFocus();
+            return;
+        }
 
-T.Separator = Ext.extend(T.Item, {
-    onRender : function(ct, position){
-        this.el = ct.createChild({tag:'span', cls:'xtb-sep'}, position);
-    }
-});
-Ext.reg('tbseparator', T.Separator);
+        btns = me.getToolbar().items.map;
+        doc = me.getDoc();
 
+        if (me.enableFont && !Ext.isSafari2) {
+            name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
+            fontSelect = me.fontSelect.dom;
+            if (name !== fontSelect.value) {
+                fontSelect.value = name;
+            }
+        }
 
-T.Spacer = Ext.extend(T.Item, {
-    
+        function updateButtons() {
+            Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
+                btns[name].toggle(doc.queryCommandState(name));
+            });
+        }
+        if(me.enableFormat){
+            updateButtons('bold', 'italic', 'underline');
+        }
+        if(me.enableAlignments){
+            updateButtons('justifyleft', 'justifycenter', 'justifyright');
+        }
+        if(!Ext.isSafari2 && me.enableLists){
+            updateButtons('insertorderedlist', 'insertunorderedlist');
+        }
 
-    onRender : function(ct, position){
-        this.el = ct.createChild({tag:'div', cls:'xtb-spacer', style: this.width?'width:'+this.width+'px':''}, position);
-    }
-});
-Ext.reg('tbspacer', T.Spacer);
+        Ext.menu.Manager.hideAll();
 
+        me.syncValue();
+    },
 
-T.Fill = Ext.extend(T.Item, {
     
-    render : Ext.emptyFn,
-    isFill : true
-});
-Ext.reg('tbfill', T.Fill);
-
+    relayBtnCmd: function(btn) {
+        this.relayCmd(btn.getItemId());
+    },
 
-T.TextItem = Ext.extend(T.Item, {
     
-
-    constructor: function(config){
-        T.TextItem.superclass.constructor.call(this, Ext.isString(config) ? {text: config} : config);
+    relayCmd: function(cmd, value) {
+        Ext.defer(function() {
+            var me = this;
+            me.focus();
+            me.execCmd(cmd, value);
+            me.updateToolbar();
+        }, 10, this);
     },
 
     
-    onRender : function(ct, position) {
-        this.autoEl = {cls: 'xtb-text', html: this.text || ''};
-        T.TextItem.superclass.onRender.call(this, ct, position);
+    execCmd : function(cmd, value){
+        var me = this,
+            doc = me.getDoc(),
+            undef;
+        doc.execCommand(cmd, false, value === undef ? null : value);
+        me.syncValue();
     },
 
     
-    setText : function(t) {
-        if(this.rendered){
-            this.el.update(t);
-        }else{
-            this.text = t;
+    applyCommand : function(e){
+        if (e.ctrlKey) {
+            var me = this,
+                c = e.getCharCode(), cmd;
+            if (c > 0) {
+                c = String.fromCharCode(c);
+                switch (c) {
+                    case 'b':
+                        cmd = 'bold';
+                    break;
+                    case 'i':
+                        cmd = 'italic';
+                    break;
+                    case 'u':
+                        cmd = 'underline';
+                    break;
+                }
+                if (cmd) {
+                    me.win.focus();
+                    me.execCmd(cmd);
+                    me.deferFocus();
+                    e.preventDefault();
+                }
+            }
         }
-    }
-});
-Ext.reg('tbtext', T.TextItem);
-
-
-T.Button = Ext.extend(Ext.Button, {});
-T.SplitButton = Ext.extend(Ext.SplitButton, {});
-Ext.reg('tbbutton', T.Button);
-Ext.reg('tbsplit', T.SplitButton);
-
-})();
+    },
 
-Ext.ButtonGroup = Ext.extend(Ext.Panel, {
-    
-    
-    baseCls: 'x-btn-group',
     
-    layout:'table',
-    defaultType: 'button',
-    
-    frame: true,
-    internalDefaults: {removeMode: 'container', hideParent: true},
+    insertAtCursor : function(text){
+        var me = this,
+            range;
 
-    initComponent : function(){
-        this.layoutConfig = this.layoutConfig || {};
-        Ext.applyIf(this.layoutConfig, {
-            columns : this.columns
-        });
-        if(!this.title){
-            this.addClass('x-btn-group-notitle');
+        if (me.activated) {
+            me.win.focus();
+            if (Ext.isIE) {
+                range = me.getDoc().selection.createRange();
+                if (range) {
+                    range.pasteHTML(text);
+                    me.syncValue();
+                    me.deferFocus();
+                }
+            }else{
+                me.execCmd('InsertHTML', text);
+                me.deferFocus();
+            }
         }
-        this.on('afterlayout', this.onAfterLayout, this);
-        Ext.ButtonGroup.superclass.initComponent.call(this);
     },
 
-    applyDefaults : function(c){
-        c = Ext.ButtonGroup.superclass.applyDefaults.call(this, c);
-        var d = this.internalDefaults;
-        if(c.events){
-            Ext.applyIf(c.initialConfig, d);
-            Ext.apply(c, d);
-        }else{
-            Ext.applyIf(c, d);
+    
+    fixKeys: function() { 
+        if (Ext.isIE) {
+            return function(e){
+                var me = this,
+                    k = e.getKey(),
+                    doc = me.getDoc(),
+                    range, target;
+                if (k === e.TAB) {
+                    e.stopEvent();
+                    range = doc.selection.createRange();
+                    if(range){
+                        range.collapse(true);
+                        range.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
+                        me.deferFocus();
+                    }
+                }
+                else if (k === e.ENTER) {
+                    range = doc.selection.createRange();
+                    if (range) {
+                        target = range.parentElement();
+                        if(!target || target.tagName.toLowerCase() !== 'li'){
+                            e.stopEvent();
+                            range.pasteHTML('<br />');
+                            range.collapse(false);
+                            range.select();
+                        }
+                    }
+                }
+            };
         }
-        return c;
-    },
 
-    onAfterLayout : function(){
-        var bodyWidth = this.body.getFrameWidth('lr') + this.body.dom.firstChild.offsetWidth;
-        this.body.setWidth(bodyWidth);
-        this.el.setWidth(bodyWidth + this.getFrameWidth());
-    }
-    
-});
+        if (Ext.isOpera) {
+            return function(e){
+                var me = this;
+                if (e.getKey() === e.TAB) {
+                    e.stopEvent();
+                    me.win.focus();
+                    me.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
+                    me.deferFocus();
+                }
+            };
+        }
+
+        if (Ext.isWebKit) {
+            return function(e){
+                var me = this,
+                    k = e.getKey();
+                if (k === e.TAB) {
+                    e.stopEvent();
+                    me.execCmd('InsertText','\t');
+                    me.deferFocus();
+                }
+                else if (k === e.ENTER) {
+                    e.stopEvent();
+                    me.execCmd('InsertHtml','<br /><br />');
+                    me.deferFocus();
+                }
+            };
+        }
 
-Ext.reg('buttongroup', Ext.ButtonGroup);
+        return null; 
+    }(),
 
-(function() {
+    
+    getToolbar : function(){
+        return this.toolbar;
+    },
 
-var T = Ext.Toolbar;
+    
+    buttonTips : {
+        bold : {
+            title: 'Bold (Ctrl+B)',
+            text: 'Make the selected text bold.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        italic : {
+            title: 'Italic (Ctrl+I)',
+            text: 'Make the selected text italic.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        underline : {
+            title: 'Underline (Ctrl+U)',
+            text: 'Underline the selected text.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        increasefontsize : {
+            title: 'Grow Text',
+            text: 'Increase the font size.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        decreasefontsize : {
+            title: 'Shrink Text',
+            text: 'Decrease the font size.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        backcolor : {
+            title: 'Text Highlight Color',
+            text: 'Change the background color of the selected text.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        forecolor : {
+            title: 'Font Color',
+            text: 'Change the color of the selected text.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        justifyleft : {
+            title: 'Align Text Left',
+            text: 'Align text to the left.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        justifycenter : {
+            title: 'Center Text',
+            text: 'Center text in the editor.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        justifyright : {
+            title: 'Align Text Right',
+            text: 'Align text to the right.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        insertunorderedlist : {
+            title: 'Bullet List',
+            text: 'Start a bulleted list.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        insertorderedlist : {
+            title: 'Numbered List',
+            text: 'Start a numbered list.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        createlink : {
+            title: 'Hyperlink',
+            text: 'Make the selected text a hyperlink.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        },
+        sourceedit : {
+            title: 'Source Edit',
+            text: 'Switch to source editing mode.',
+            cls: Ext.baseCSSPrefix + 'html-editor-tip'
+        }
+    }
 
-Ext.PagingToolbar = Ext.extend(Ext.Toolbar, {
     
     
     
-    pageSize : 20,
     
     
-    displayMsg : 'Displaying {0} - {1} of {2}',
     
-    emptyMsg : 'No data to display',
     
-    beforePageText : 'Page',
     
-    afterPageText : 'of {0}',
     
-    firstText : 'First Page',
     
-    prevText : 'Previous Page',
     
-    nextText : 'Next Page',
     
-    lastText : 'Last Page',
     
-    refreshText : 'Refresh',
-
     
-
     
-
     
-
-    initComponent : function(){
-        var pagingItems = [this.first = new T.Button({
-            tooltip: this.firstText,
-            overflowText: this.firstText,
-            iconCls: 'x-tbar-page-first',
-            disabled: true,
-            handler: this.moveFirst,
-            scope: this
-        }), this.prev = new T.Button({
-            tooltip: this.prevText,
-            overflowText: this.prevText,
-            iconCls: 'x-tbar-page-prev',
-            disabled: true,
-            handler: this.movePrevious,
-            scope: this
-        }), '-', this.beforePageText,
-        this.inputItem = new Ext.form.NumberField({
-            cls: 'x-tbar-page-number',
-            allowDecimals: false,
-            allowNegative: false,
-            enableKeyEvents: true,
-            selectOnFocus: true,
-            submitValue: false,
-            listeners: {
-                scope: this,
-                keydown: this.onPagingKeyDown,
-                blur: this.onPagingBlur
-            }
-        }), this.afterTextItem = new T.TextItem({
-            text: String.format(this.afterPageText, 1)
-        }), '-', this.next = new T.Button({
-            tooltip: this.nextText,
-            overflowText: this.nextText,
-            iconCls: 'x-tbar-page-next',
-            disabled: true,
-            handler: this.moveNext,
-            scope: this
-        }), this.last = new T.Button({
-            tooltip: this.lastText,
-            overflowText: this.lastText,
-            iconCls: 'x-tbar-page-last',
-            disabled: true,
-            handler: this.moveLast,
-            scope: this
-        }), '-', this.refresh = new T.Button({
-            tooltip: this.refreshText,
-            overflowText: this.refreshText,
-            iconCls: 'x-tbar-loading',
-            handler: this.doRefresh,
-            scope: this
-        })];
+    
+});
 
 
-        var userItems = this.items || this.buttons || [];
-        if (this.prependButtons) {
-            this.items = userItems.concat(pagingItems);
-        }else{
-            this.items = pagingItems.concat(userItems);
-        }
-        delete this.buttons;
-        if(this.displayInfo){
-            this.items.push('->');
-            this.items.push(this.displayItem = new T.TextItem({}));
-        }
-        Ext.PagingToolbar.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'change',
-            
-            'beforechange'
-        );
-        this.on('afterlayout', this.onFirstLayout, this, {single: true});
-        this.cursor = 0;
-        this.bindStore(this.store, true);
-    },
+Ext.define('Ext.form.field.Radio', {
+    extend:'Ext.form.field.Checkbox',
+    alias: ['widget.radiofield', 'widget.radio'],
+    alternateClassName: 'Ext.form.Radio',
+    requires: ['Ext.form.RadioManager'],
 
-    
-    onFirstLayout : function(){
-        if(this.dsLoaded){
-            this.onLoad.apply(this, this.dsLoaded);
-        }
-    },
+    isRadio: true,
 
     
-    updateInfo : function(){
-        if(this.displayItem){
-            var count = this.store.getCount();
-            var msg = count == 0 ?
-                this.emptyMsg :
-                String.format(
-                    this.displayMsg,
-                    this.cursor+1, this.cursor+count, this.store.getTotalCount()
-                );
-            this.displayItem.setText(msg);
-        }
-    },
 
     
-    onLoad : function(store, r, o){
-        if(!this.rendered){
-            this.dsLoaded = [store, r, o];
-            return;
-        }
-        var p = this.getParams();
-        this.cursor = (o.params && o.params[p.start]) ? o.params[p.start] : 0;
-        var d = this.getPageData(), ap = d.activePage, ps = d.pages;
-
-        this.afterTextItem.setText(String.format(this.afterPageText, d.pages));
-        this.inputItem.setValue(ap);
-        this.first.setDisabled(ap == 1);
-        this.prev.setDisabled(ap == 1);
-        this.next.setDisabled(ap == ps);
-        this.last.setDisabled(ap == ps);
-        this.refresh.enable();
-        this.updateInfo();
-        this.fireEvent('change', this, d);
-    },
+    inputType: 'radio',
+    ariaRole: 'radio',
 
     
-    getPageData : function(){
-        var total = this.store.getTotalCount();
-        return {
-            total : total,
-            activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
-            pages :  total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
-        };
+    getGroupValue: function() {
+        var selected = this.getManager().getChecked(this.name);
+        return selected ? selected.inputValue : null;
     },
 
     
-    changePage : function(page){
-        this.doLoad(((page-1) * this.pageSize).constrain(0, this.store.getTotalCount()));
+    onBoxClick: function(e) {
+        var me = this;
+        if (!me.disabled && !me.readOnly) {
+            this.setValue(true);
+        }
     },
 
     
-    onLoadError : function(){
-        if(!this.rendered){
-            return;
+    setValue: function(v) {
+        var me = this,
+            active;
+
+        if (Ext.isBoolean(v)) {
+            me.callParent(arguments);
+        } else {
+            active = me.getManager().getWithValue(me.name, v).getAt(0);
+            if (active) {
+                active.setValue(true);
+            }
         }
-        this.refresh.enable();
+        return me;
     },
 
     
-    readPage : function(d){
-        var v = this.inputItem.getValue(), pageNum;
-        if (!v || isNaN(pageNum = parseInt(v, 10))) {
-            this.inputItem.setValue(d.activePage);
-            return false;
-        }
-        return pageNum;
+    getSubmitValue: function() {
+        return this.checked ? this.inputValue : null;
     },
 
-    onPagingFocus : function(){
-        this.inputItem.select();
+    getModelData: function() {
+        return this.getSubmitData();
     },
 
     
-    onPagingBlur : function(e){
-        this.inputItem.setValue(this.getPageData().activePage);
-    },
+    onChange: function(newVal, oldVal) {
+        var me = this;
+        me.callParent(arguments);
 
-    
-    onPagingKeyDown : function(field, e){
-        var k = e.getKey(), d = this.getPageData(), pageNum;
-        if (k == e.RETURN) {
-            e.stopEvent();
-            pageNum = this.readPage(d);
-            if(pageNum !== false){
-                pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
-                this.doLoad(pageNum * this.pageSize);
-            }
-        }else if (k == e.HOME || k == e.END){
-            e.stopEvent();
-            pageNum = k == e.HOME ? 1 : d.pages;
-            field.setValue(pageNum);
-        }else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN){
-            e.stopEvent();
-            if((pageNum = this.readPage(d))){
-                var increment = e.shiftKey ? 10 : 1;
-                if(k == e.DOWN || k == e.PAGEDOWN){
-                    increment *= -1;
-                }
-                pageNum += increment;
-                if(pageNum >= 1 & pageNum <= d.pages){
-                    field.setValue(pageNum);
+        if (newVal) {
+            this.getManager().getByName(me.name).each(function(item){
+                if (item !== me) {
+                    item.setValue(false);
                 }
-            }
+            }, me);
         }
     },
 
     
-    getParams : function(){
-        
-        return this.paramNames || this.store.paramNames;
-    },
+    getManager: function() {
+        return Ext.form.RadioManager;
+    }
+});
+
+
+Ext.define('Ext.picker.Time', {
+    extend: 'Ext.view.BoundList',
+    alias: 'widget.timepicker',
+    requires: ['Ext.data.Store', 'Ext.Date'],
 
     
-    beforeLoad : function(){
-        if(this.rendered && this.refresh){
-            this.refresh.disable();
-        }
-    },
 
     
-    doLoad : function(start){
-        var o = {}, pn = this.getParams();
-        o[pn.start] = start;
-        o[pn.limit] = this.pageSize;
-        if(this.fireEvent('beforechange', this, o) !== false){
-            this.store.load({params:o});
-        }
-    },
 
     
-    moveFirst : function(){
-        this.doLoad(0);
-    },
+    increment: 15,
 
     
-    movePrevious : function(){
-        this.doLoad(Math.max(0, this.cursor-this.pageSize));
-    },
+    format : "g:i A",
 
     
-    moveNext : function(){
-        this.doLoad(this.cursor+this.pageSize);
-    },
+    displayField: 'disp',
 
     
-    moveLast : function(){
-        var total = this.store.getTotalCount(),
-            extra = total % this.pageSize;
+    initDate: [2008,0,1],
 
-        this.doLoad(extra ? (total - extra) : total - this.pageSize);
-    },
+    componentCls: Ext.baseCSSPrefix + 'timepicker',
 
     
-    doRefresh : function(){
-        this.doLoad(this.cursor);
+    loadMask: false,
+
+    initComponent: function() {
+        var me = this,
+            dateUtil = Ext.Date,
+            clearTime = dateUtil.clearTime,
+            initDate = me.initDate;
+
+        
+        me.absMin = clearTime(new Date(initDate[0], initDate[1], initDate[2]));
+        me.absMax = dateUtil.add(clearTime(new Date(initDate[0], initDate[1], initDate[2])), 'mi', (24 * 60) - 1);
+
+        me.store = me.createStore();
+        me.updateList();
+
+        me.callParent();
     },
 
     
-    bindStore : function(store, initial){
-        var doLoad;
-        if(!initial && this.store){
-            if(store !== this.store && this.store.autoDestroy){
-                this.store.destroy();
-            }else{
-                this.store.un('beforeload', this.beforeLoad, this);
-                this.store.un('load', this.onLoad, this);
-                this.store.un('exception', this.onLoadError, this);
-            }
-            if(!store){
-                this.store = null;
-            }
-        }
-        if(store){
-            store = Ext.StoreMgr.lookup(store);
-            store.on({
-                scope: this,
-                beforeload: this.beforeLoad,
-                load: this.onLoad,
-                exception: this.onLoadError
-            });
-            doLoad = true;
-        }
-        this.store = store;
-        if(doLoad){
-            this.onLoad(store, null, {});
-        }
+    setMinValue: function(value) {
+        this.minValue = value;
+        this.updateList();
     },
 
     
-    unbind : function(store){
-        this.bindStore(null);
+    setMaxValue: function(value) {
+        this.maxValue = value;
+        this.updateList();
     },
 
     
-    bind : function(store){
-        this.bindStore(store);
+    normalizeDate: function(date) {
+        var initDate = this.initDate;
+        date.setFullYear(initDate[0], initDate[1], initDate[2]);
+        return date;
     },
 
     
-    onDestroy : function(){
-        this.bindStore(null);
-        Ext.PagingToolbar.superclass.onDestroy.call(this);
-    }
-});
-
-})();
-Ext.reg('paging', Ext.PagingToolbar);
-Ext.History = (function () {
-    var iframe, hiddenField;
-    var ready = false;
-    var currentToken;
-
-    function getHash() {
-        var href = top.location.href, i = href.indexOf("#");
-        return i >= 0 ? href.substr(i + 1) : null;
-    }
+    updateList: function() {
+        var me = this,
+            min = me.normalizeDate(me.minValue || me.absMin),
+            max = me.normalizeDate(me.maxValue || me.absMax);
 
-    function doSave() {
-        hiddenField.value = currentToken;
-    }
+        me.store.filterBy(function(record) {
+            var date = record.get('date');
+            return date >= min && date <= max;
+        });
+    },
 
-    function handleStateChange(token) {
-        currentToken = token;
-        Ext.History.fireEvent('change', token);
-    }
+    
+    createStore: function() {
+        var me = this,
+            utilDate = Ext.Date,
+            times = [],
+            min = me.absMin,
+            max = me.absMax;
 
-    function updateIFrame (token) {
-        var html = ['<html><body><div id="state">',Ext.util.Format.htmlEncode(token),'</div></body></html>'].join('');
-        try {
-            var doc = iframe.contentWindow.document;
-            doc.open();
-            doc.write(html);
-            doc.close();
-            return true;
-        } catch (e) {
-            return false;
+        while(min <= max){
+            times.push({
+                disp: utilDate.dateFormat(min, me.format),
+                date: min
+            });
+            min = utilDate.add(min, 'mi', me.increment);
         }
+
+        return Ext.create('Ext.data.Store', {
+            fields: ['disp', 'date'],
+            data: times
+        });
     }
 
-    function checkIFrame() {
-        if (!iframe.contentWindow || !iframe.contentWindow.document) {
-            setTimeout(checkIFrame, 10);
-            return;
-        }
+});
 
-        var doc = iframe.contentWindow.document;
-        var elem = doc.getElementById("state");
-        var token = elem ? elem.innerText : null;
 
-        var hash = getHash();
+Ext.define('Ext.form.field.Time', {
+    extend:'Ext.form.field.Picker',
+    alias: 'widget.timefield',
+    requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
+    alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
 
-        setInterval(function () {
+    
+    triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
 
-            doc = iframe.contentWindow.document;
-            elem = doc.getElementById("state");
+    
 
-            var newtoken = elem ? elem.innerText : null;
+    
 
-            var newHash = getHash();
+    
+    minText : "The time in this field must be equal to or after {0}",
 
-            if (newtoken !== token) {
-                token = newtoken;
-                handleStateChange(token);
-                top.location.hash = token;
-                hash = token;
-                doSave();
-            } else if (newHash !== hash) {
-                hash = newHash;
-                updateIFrame(newHash);
-            }
+    
+    maxText : "The time in this field must be equal to or before {0}",
 
-        }, 50);
+    
+    invalidText : "{0} is not a valid time",
 
-        ready = true;
+    
+    format : "g:i A",
 
-        Ext.History.fireEvent('ready', Ext.History);
-    }
+    
 
-    function startUp() {
-        currentToken = hiddenField.value ? hiddenField.value : getHash();
+    
+    altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",
 
-        if (Ext.isIE) {
-            checkIFrame();
-        } else {
-            var hash = getHash();
-            setInterval(function () {
-                var newHash = getHash();
-                if (newHash !== hash) {
-                    hash = newHash;
-                    handleStateChange(hash);
-                    doSave();
-                }
-            }, 50);
-            ready = true;
-            Ext.History.fireEvent('ready', Ext.History);
-        }
-    }
+    
+    increment: 15,
 
-    return {
-        
-        fieldId: 'x-history-field',
-        
-        iframeId: 'x-history-frame',
+    
+    pickerMaxHeight: 300,
 
-        events:{},
+    
+    selectOnTab: true,
 
-        
-        init: function (onReady, scope) {
-            if(ready) {
-                Ext.callback(onReady, scope, [this]);
-                return;
-            }
-            if(!Ext.isReady){
-                Ext.onReady(function(){
-                    Ext.History.init(onReady, scope);
-                });
-                return;
-            }
-            hiddenField = Ext.getDom(Ext.History.fieldId);
-            if (Ext.isIE) {
-                iframe = Ext.getDom(Ext.History.iframeId);
-            }
-            this.addEvents(
-                
-                'ready',
-                
-                'change'
-            );
-            if(onReady){
-                this.on('ready', onReady, scope, {single:true});
-            }
-            startUp();
-        },
+    
+    initDate: '1/1/2008',
+    initDateFormat: 'j/n/Y',
 
-        
-        add: function (token, preventDup) {
-            if(preventDup !== false){
-                if(this.getToken() == token){
-                    return true;
-                }
-            }
-            if (Ext.isIE) {
-                return updateIFrame(token);
-            } else {
-                top.location.hash = token;
-                return true;
-            }
-        },
 
-        
-        back: function(){
-            history.go(-1);
-        },
+    initComponent: function() {
+        var me = this,
+            min = me.minValue,
+            max = me.maxValue;
+        if (min) {
+            me.setMinValue(min);
+        }
+        if (max) {
+            me.setMaxValue(max);
+        }
+        this.callParent();
+    },
 
-        
-        forward: function(){
-            history.go(1);
-        },
+    initValue: function() {
+        var me = this,
+            value = me.value;
 
         
-        getToken: function() {
-            return ready ? currentToken : getHash();
+        if (Ext.isString(value)) {
+            me.value = me.rawToValue(value);
         }
-    };
-})();
-Ext.apply(Ext.History, new Ext.util.Observable());
-Ext.Tip = Ext.extend(Ext.Panel, {
-    
-    
-    
-    minWidth : 40,
+
+        me.callParent();
+    },
+
     
-    maxWidth : 300,
+    setMinValue: function(value) {
+        var me = this,
+            picker = me.picker;
+        me.setLimit(value, true);
+        if (picker) {
+            picker.setMinValue(me.minValue);
+        }
+    },
+
     
-    shadow : "sides",
+    setMaxValue: function(value) {
+        var me = this,
+            picker = me.picker;
+        me.setLimit(value, false);
+        if (picker) {
+            picker.setMaxValue(me.maxValue);
+        }
+    },
+
     
-    defaultAlign : "tl-bl?",
-    autoRender: true,
-    quickShowInterval : 250,
+    setLimit: function(value, isMin) {
+        var me = this,
+            d, val;
+        if (Ext.isString(value)) {
+            d = me.parseDate(value);
+        }
+        else if (Ext.isDate(value)) {
+            d = value;
+        }
+        if (d) {
+            val = Ext.Date.clearTime(new Date(me.initDate));
+            val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
+            me[isMin ? 'minValue' : 'maxValue'] = val;
+        }
+    },
+
+    rawToValue: function(rawValue) {
+        return this.parseDate(rawValue) || rawValue || null;
+    },
+
+    valueToRaw: function(value) {
+        return this.formatDate(this.parseDate(value));
+    },
 
     
-    frame:true,
-    hidden:true,
-    baseCls: 'x-tip',
-    floating:{shadow:true,shim:true,useDisplay:true,constrain:false},
-    autoHeight:true,
+    getErrors: function(value) {
+        var me = this,
+            format = Ext.String.format,
+            errors = me.callParent(arguments),
+            minValue = me.minValue,
+            maxValue = me.maxValue,
+            date;
 
-    closeAction: 'hide',
+        value = me.formatDate(value || me.processRawValue(me.getRawValue()));
+
+        if (value === null || value.length < 1) { 
+             return errors;
+        }
+
+        date = me.parseDate(value);
+        if (!date) {
+            errors.push(format(me.invalidText, value, me.format));
+            return errors;
+        }
+
+        if (minValue && date < minValue) {
+            errors.push(format(me.minText, me.formatDate(minValue)));
+        }
+
+        if (maxValue && date > maxValue) {
+            errors.push(format(me.maxText, me.formatDate(maxValue)));
+        }
+
+        return errors;
+    },
+
+    formatDate: function() {
+        return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
+    },
 
     
-    initComponent : function(){
-        Ext.Tip.superclass.initComponent.call(this);
-        if(this.closable && !this.title){
-            this.elements += ',header';
+    parseDate: function(value) {
+        if (!value || Ext.isDate(value)) {
+            return value;
+        }
+
+        var me = this,
+            val = me.safeParse(value, me.format),
+            altFormats = me.altFormats,
+            altFormatsArray = me.altFormatsArray,
+            i = 0,
+            len;
+
+        if (!val && altFormats) {
+            altFormatsArray = altFormatsArray || altFormats.split('|');
+            len = altFormatsArray.length;
+            for (; i < len && !val; ++i) {
+                val = me.safeParse(value, altFormatsArray[i]);
+            }
+        }
+        return val;
+    },
+
+    safeParse: function(value, format){
+        var me = this,
+            utilDate = Ext.Date,
+            parsedDate,
+            result = null;
+
+        if (utilDate.formatContainsDateInfo(format)) {
+            
+            result = utilDate.parse(value, format);
+        } else {
+            
+            parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
+            if (parsedDate) {
+                result = parsedDate;
+            }
         }
+        return result;
     },
 
     
-    afterRender : function(){
-        Ext.Tip.superclass.afterRender.call(this);
-        if(this.closable){
-            this.addTool({
-                id: 'close',
-                handler: this[this.closeAction],
-                scope: this
+    getSubmitValue: function() {
+        var me = this,
+            format = me.submitFormat || me.format,
+            value = me.getValue();
+
+        return value ? Ext.Date.format(value, format) : null;
+    },
+
+    
+    createPicker: function() {
+        var me = this,
+            picker = Ext.create('Ext.picker.Time', {
+                pickerField: me,
+                selModel: {
+                    mode: 'SINGLE'
+                },
+                floating: true,
+                hidden: true,
+                minValue: me.minValue,
+                maxValue: me.maxValue,
+                increment: me.increment,
+                format: me.format,
+                ownerCt: this.ownerCt,
+                renderTo: document.body,
+                maxHeight: me.pickerMaxHeight,
+                focusOnToFront: false
             });
-        }
+
+        me.mon(picker.getSelectionModel(), {
+            selectionchange: me.onListSelect,
+            scope: me
+        });
+
+        return picker;
     },
 
     
-    showAt : function(xy){
-        Ext.Tip.superclass.show.call(this);
-        if(this.measureWidth !== false && (!this.initialConfig || typeof this.initialConfig.width != 'number')){
-            this.doAutoWidth();
+    onExpand: function() {
+        var me = this,
+            keyNav = me.pickerKeyNav,
+            selectOnTab = me.selectOnTab,
+            picker = me.getPicker(),
+            lastSelected = picker.getSelectionModel().lastSelected,
+            itemNode;
+
+        if (!keyNav) {
+            keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
+                boundList: picker,
+                forceKeyDown: true,
+                tab: function(e) {
+                    if (selectOnTab) {
+                        if(me.picker.highlightedItem) {
+                            this.selectHighlighted(e);
+                        } else {
+                            me.collapse();
+                        }
+                        me.triggerBlur();
+                    }
+                    
+                    return true;
+                }
+            });
+            
+            if (selectOnTab) {
+                me.ignoreMonitorTab = true;
+            }
         }
-        if(this.constrainPosition){
-            xy = this.el.adjustForConstraints(xy);
+        Ext.defer(keyNav.enable, 1, keyNav); 
+
+        
+        if (lastSelected) {
+            itemNode = picker.getNode(lastSelected);
+            if (itemNode) {
+                picker.highlightItem(itemNode);
+                picker.el.scrollChildIntoView(itemNode, false);
+            }
         }
-        this.setPagePosition(xy[0], xy[1]);
     },
 
     
-    doAutoWidth : function(adjust){
-        adjust = adjust || 0;
-        var bw = this.body.getTextWidth();
-        if(this.title){
-            bw = Math.max(bw, this.header.child('span').getTextWidth(this.title));
-        }
-        bw += this.getFrameWidth() + (this.closable ? 20 : 0) + this.body.getPadding("lr") + adjust;
-        this.setWidth(bw.constrain(this.minWidth, this.maxWidth));
-        
-        
-        if(Ext.isIE7 && !this.repainted){
-            this.el.repaint();
-            this.repainted = true;
+    onCollapse: function() {
+        var me = this,
+            keyNav = me.pickerKeyNav;
+        if (keyNav) {
+            keyNav.disable();
+            me.ignoreMonitorTab = false;
         }
     },
 
     
-    showBy : function(el, pos){
-        if(!this.rendered){
-            this.render(Ext.getBody());
+    onChange: function() {
+        var me = this,
+            picker = me.picker;
+
+        me.callParent(arguments);
+        if(picker) {
+            picker.clearHighlight();
         }
-        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
     },
 
-    initDraggable : function(){
-        this.dd = new Ext.Tip.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
-        this.header.addClass('x-tip-draggable');
+    
+    onListSelect: function(list, recordArray) {
+        var me = this,
+            record = recordArray[0],
+            val = record ? record.get('date') : null;
+        me.setValue(val);
+        me.fireEvent('select', me, val);
+        me.picker.clearHighlight();
+        me.collapse();
+        me.inputEl.focus();
     }
 });
 
-Ext.reg('tip', Ext.Tip);
 
 
-Ext.Tip.DD = function(tip, config){
-    Ext.apply(this, config);
-    this.tip = tip;
-    Ext.Tip.DD.superclass.constructor.call(this, tip.el.id, 'WindowDD-'+tip.id);
-    this.setHandleElId(tip.header.id);
-    this.scroll = false;
-};
-
-Ext.extend(Ext.Tip.DD, Ext.dd.DD, {
-    moveOnly:true,
-    scroll:false,
-    headerOffsets:[100, 25],
-    startDrag : function(){
-        this.tip.el.disableShadow();
+Ext.define('Ext.grid.CellEditor', {
+    extend: 'Ext.Editor',
+    constructor: function(config) {
+        config = Ext.apply({}, config);
+        
+        if (config.field) {
+            config.field.monitorTab = false;
+        }
+        if (!Ext.isDefined(config.autoSize)) {
+            config.autoSize = {
+                width: 'boundEl'
+            };
+        }
+        this.callParent([config]);
     },
-    endDrag : function(e){
-        this.tip.el.enableShadow(true);
-    }
-});
-Ext.ToolTip = Ext.extend(Ext.Tip, {
     
     
+    onShow: function() {
+        var first = this.boundEl.first();
+        if (first) {
+            first.hide();
+        }
+        this.callParent(arguments);
+    },
     
     
-    showDelay : 500,
+    onHide: function() {
+        var first = this.boundEl.first();
+        if (first) {
+            first.show();
+        }
+        this.callParent(arguments);
+    },
     
-    hideDelay : 200,
     
-    dismissDelay : 5000,
+    afterRender: function() {
+        this.callParent(arguments);
+        var field = this.field;
+        if (field.isXType('checkboxfield')) {
+            field.mon(field.inputEl, 'mousedown', this.onCheckBoxMouseDown, this);
+            field.mon(field.inputEl, 'click', this.onCheckBoxClick, this);
+        }
+    },
     
     
-    trackMouse : false,
+    onCheckBoxMouseDown: function() {
+        this.completeEdit = Ext.emptyFn;
+    },
     
-    anchorToTarget : true,
     
-    anchorOffset : 0,
+    onCheckBoxClick: function() {
+        delete this.completeEdit;
+        this.field.focus(false, 10);
+    },
     
+    alignment: "tl-tl",
+    hideEl : false,
+    cls: Ext.baseCSSPrefix + "small-editor " + Ext.baseCSSPrefix + "grid-editor",
+    shim: false,
+    shadow: false
+});
 
-    
-    targetCounter : 0,
+Ext.define('Ext.grid.ColumnLayout', {
+    extend: 'Ext.layout.container.HBox',
+    alias: 'layout.gridcolumn',
+    type : 'column',
 
-    constrainPosition : false,
+    reserveOffset: false,
 
-    
-    initComponent : function(){
-        Ext.ToolTip.superclass.initComponent.call(this);
-        this.lastActive = new Date();
-        this.initTarget(this.target);
-        this.origAnchor = this.anchor;
-    },
+    shrinkToFit: false,
 
     
-    onRender : function(ct, position){
-        Ext.ToolTip.superclass.onRender.call(this, ct, position);
-        this.anchorCls = 'x-tip-anchor-' + this.getAnchorPosition();
-        this.anchorEl = this.el.createChild({
-            cls: 'x-tip-anchor ' + this.anchorCls
-        });
-    },
+    clearInnerCtOnLayout: true,
 
-    
-    afterRender : function(){
-        Ext.ToolTip.superclass.afterRender.call(this);
-        this.anchorEl.setStyle('z-index', this.el.getZIndex() + 1).setVisibilityMode(Ext.Element.DISPLAY);
-    },
+    beforeLayout: function() {
+        var me = this,
+            i = 0,
+            items = me.getLayoutItems(),
+            len = items.length,
+            item, returnValue,
+            s;
 
-    
-    initTarget : function(target){
-        var t;
-        if((t = Ext.get(target))){
-            if(this.target){
-                var tg = Ext.get(this.target);
-                this.mun(tg, 'mouseover', this.onTargetOver, this);
-                this.mun(tg, 'mouseout', this.onTargetOut, this);
-                this.mun(tg, 'mousemove', this.onMouseMove, this);
-            }
-            this.mon(t, {
-                mouseover: this.onTargetOver,
-                mouseout: this.onTargetOut,
-                mousemove: this.onMouseMove,
-                scope: this
-            });
-            this.target = t;
+        
+        if (!Ext.isDefined(me.availableSpaceOffset)) {
+            s = me.owner.up('tablepanel').verticalScroller;
+            me.availableSpaceOffset = s ? s.width-1 : 0;
         }
-        if(this.anchor){
-            this.anchorTarget = this.target;
+
+        returnValue = me.callParent(arguments);
+
+        
+        me.innerCt.setHeight(23);
+
+        
+        for (; i < len; i++) {
+            item = items[i];
+            item.el.setStyle({
+                height: 'auto'
+            });
+            item.titleContainer.setStyle({
+                height: 'auto',
+                paddingTop: '0'
+            });
+            if (item.componentLayout && item.componentLayout.lastComponentSize) {
+                item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
+            }
         }
+        return returnValue;
     },
 
     
-    onMouseMove : function(e){
-        var t = this.delegate ? e.getTarget(this.delegate) : this.triggerElement = true;
-        if (t) {
-            this.targetXY = e.getXY();
-            if (t === this.triggerElement) {
-                if(!this.hidden && this.trackMouse){
-                    this.setPagePosition(this.getTargetXY());
+    calculateChildBoxes: function(visibleItems, targetSize) {
+        var me = this,
+            calculations = me.callParent(arguments),
+            boxes = calculations.boxes,
+            metaData = calculations.meta,
+            len = boxes.length, i = 0, box, item;
+
+        if (targetSize.width && !me.isHeader) {
+            
+            if (me.owner.forceFit) {
+
+                for (; i < len; i++) {
+                    box = boxes[i];
+                    item = box.component;
+
+                    
+                    item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
+
+                    
+                    
+                    item.flex = box.width;
                 }
-            } else {
-                this.hide();
-                this.lastActive = new Date(0);
-                this.onTargetOver(e);
+
+                
+                calculations = me.callParent(arguments);
+            }
+            else if (metaData.tooNarrow) {
+                targetSize.width = metaData.desiredSize;
             }
-        } else if (!this.closable && this.isVisible()) {
-            this.hide();
         }
+
+        return calculations;
     },
 
-    
-    getTargetXY : function(){
-        if(this.delegate){
-            this.anchorTarget = this.triggerElement;
-        }
-        if(this.anchor){
-            this.targetCounter++;
-            var offsets = this.getOffsets(),
-                xy = (this.anchorToTarget && !this.trackMouse) ? this.el.getAlignToXY(this.anchorTarget, this.getAnchorAlign()) : this.targetXY,
-                dw = Ext.lib.Dom.getViewWidth() - 5,
-                dh = Ext.lib.Dom.getViewHeight() - 5,
-                de = document.documentElement,
-                bd = document.body,
-                scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
-                scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
-                axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
-                sz = this.getSize();
-                
-            this.anchorEl.removeClass(this.anchorCls);
+    afterLayout: function() {
+        var me = this,
+            owner = me.owner,
+            topGrid,
+            bothHeaderCts,
+            otherHeaderCt,
+            thisHeight,
+            otherHeight,
+            modifiedGrid,
+            i = 0,
+            items,
+            len,
+            headerHeight;
 
-            if(this.targetCounter < 2){
-                if(axy[0] < scrollX){
-                    if(this.anchorToTarget){
-                        this.defaultAlign = 'l-r';
-                        if(this.mouseOffset){this.mouseOffset[0] *= -1;}
-                    }
-                    this.anchor = 'left';
-                    return this.getTargetXY();
+        me.callParent(arguments);
+
+        
+        if (!me.owner.hideHeaders) {
+
+            
+            
+            if (owner.lockableInjected) {
+                topGrid = owner.up('tablepanel').up('tablepanel');
+                bothHeaderCts = topGrid.query('headercontainer:not([isHeader])');
+                otherHeaderCt = (bothHeaderCts[0] === owner) ? bothHeaderCts[1] : bothHeaderCts[0];
+
+                
+                if (!otherHeaderCt.rendered) {
+                    return;
                 }
-                if(axy[0]+sz.width > dw){
-                    if(this.anchorToTarget){
-                        this.defaultAlign = 'r-l';
-                        if(this.mouseOffset){this.mouseOffset[0] *= -1;}
-                    }
-                    this.anchor = 'right';
-                    return this.getTargetXY();
+
+                
+                otherHeight = otherHeaderCt.layout.getRenderTarget().getViewSize().height;
+                if (!otherHeight) {
+                    return;
                 }
-                if(axy[1] < scrollY){
-                    if(this.anchorToTarget){
-                        this.defaultAlign = 't-b';
-                        if(this.mouseOffset){this.mouseOffset[1] *= -1;}
-                    }
-                    this.anchor = 'top';
-                    return this.getTargetXY();
+                thisHeight = this.getRenderTarget().getViewSize().height;
+                if (!thisHeight) {
+                    return;
                 }
-                if(axy[1]+sz.height > dh){
-                    if(this.anchorToTarget){
-                        this.defaultAlign = 'b-t';
-                        if(this.mouseOffset){this.mouseOffset[1] *= -1;}
-                    }
-                    this.anchor = 'bottom';
-                    return this.getTargetXY();
+
+                
+                
+                topGrid.componentLayout.layoutBusy = true;
+
+                
+                headerHeight = thisHeight;
+
+                
+                if (thisHeight > otherHeight) {
+                    otherHeaderCt.layout.align = 'stretch';
+                    otherHeaderCt.setCalculatedSize(otherHeaderCt.getWidth(), owner.getHeight(), otherHeaderCt.ownerCt);
+                    delete otherHeaderCt.layout.align;
+                    modifiedGrid = otherHeaderCt.up('tablepanel');
+                } else if (otherHeight > thisHeight) {
+                    headerHeight = otherHeight;
+                    this.align = 'stretch';
+                    owner.setCalculatedSize(owner.getWidth(), otherHeaderCt.getHeight(), owner.ownerCt);
+                    delete this.align;
+                    modifiedGrid = owner.up('tablepanel');
                 }
+                topGrid.componentLayout.layoutBusy = false;
+
+                
+                items = bothHeaderCts[0].layout.getLayoutItems().concat(bothHeaderCts[1].layout.getLayoutItems());
+            } else {
+                headerHeight = this.getRenderTarget().getViewSize().height;
+                items = me.getLayoutItems();
             }
 
-            this.anchorCls = 'x-tip-anchor-'+this.getAnchorPosition();
-            this.anchorEl.addClass(this.anchorCls);
-            this.targetCounter = 0;
-            return axy;
-        }else{
-            var mouseOffset = this.getMouseOffset();
-            return [this.targetXY[0]+mouseOffset[0], this.targetXY[1]+mouseOffset[1]];
-        }
-    },
+            len = items.length;
+            for (; i < len; i++) {
+                items[i].setPadding(headerHeight);
+            }
 
-    getMouseOffset : function(){
-        var offset = this.anchor ? [0,0] : [15,18];
-        if(this.mouseOffset){
-            offset[0] += this.mouseOffset[0];
-            offset[1] += this.mouseOffset[1];
+            
+            if (modifiedGrid) {
+                setTimeout(function() {
+                    modifiedGrid.doLayout();
+                }, 1);
+            }
         }
-        return offset;
     },
 
     
-    getAnchorPosition : function(){
-        if(this.anchor){
-            this.tipAnchor = this.anchor.charAt(0);
-        }else{
-            var m = this.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
-            if(!m){
-               throw 'AnchorTip.defaultAlign is invalid';
+    
+    updateInnerCtSize: function(tSize, calcs) {
+        var me = this,
+            extra;
+
+        
+        if (!me.isHeader) {
+            me.tooNarrow = calcs.meta.tooNarrow;
+            extra = (me.reserveOffset ? me.availableSpaceOffset : 0);
+
+            if (calcs.meta.tooNarrow) {
+                tSize.width = calcs.meta.desiredSize + extra;
+            } else {
+                tSize.width += extra;
             }
-            this.tipAnchor = m[1].charAt(0);
         }
 
-        switch(this.tipAnchor){
-            case 't': return 'top';
-            case 'b': return 'bottom';
-            case 'r': return 'right';
-        }
-        return 'left';
+        return me.callParent(arguments);
     },
 
-    
-    getAnchorAlign : function(){
-        switch(this.anchor){
-            case 'top'  : return 'tl-bl';
-            case 'left' : return 'tl-tr';
-            case 'right': return 'tr-tl';
-            default     : return 'bl-tl';
+    doOwnerCtLayouts: function() {
+        var ownerCt = this.owner.ownerCt;
+        if (!ownerCt.componentLayout.layoutBusy) {
+            ownerCt.doComponentLayout();
         }
+    }
+});
+
+Ext.define('Ext.grid.LockingView', {
+
+    mixins: {
+        observable: 'Ext.util.Observable'
     },
 
-    
-    getOffsets : function(){
-        var offsets, 
-            ap = this.getAnchorPosition().charAt(0);
-        if(this.anchorToTarget && !this.trackMouse){
-            switch(ap){
-                case 't':
-                    offsets = [0, 9];
-                    break;
-                case 'b':
-                    offsets = [0, -13];
-                    break;
-                case 'r':
-                    offsets = [-13, 0];
-                    break;
-                default:
-                    offsets = [9, 0];
-                    break;
-            }
-        }else{
-            switch(ap){
-                case 't':
-                    offsets = [-15-this.anchorOffset, 30];
-                    break;
-                case 'b':
-                    offsets = [-19-this.anchorOffset, -13-this.el.dom.offsetHeight];
-                    break;
-                case 'r':
-                    offsets = [-15-this.el.dom.offsetWidth, -13-this.anchorOffset];
-                    break;
-                default:
-                    offsets = [25, -13-this.anchorOffset];
-                    break;
+    eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell)/,
+
+    constructor: function(config){
+        var me = this,
+            eventNames = [],
+            eventRe = me.eventRelayRe,
+            locked = config.locked.getView(),
+            normal = config.normal.getView(),
+            events,
+            event;
+
+        Ext.apply(me, {
+            lockedView: locked,
+            normalView: normal,
+            lockedGrid: config.locked,
+            normalGrid: config.normal,
+            panel: config.panel
+        });
+        me.mixins.observable.constructor.call(me, config);
+
+        
+        events = locked.events;
+        for (event in events) {
+            if (events.hasOwnProperty(event) && eventRe.test(event)) {
+                eventNames.push(event);
             }
         }
-        var mouseOffset = this.getMouseOffset();
-        offsets[0] += mouseOffset[0];
-        offsets[1] += mouseOffset[1];
+        me.relayEvents(locked, eventNames);
+        me.relayEvents(normal, eventNames);
 
-        return offsets;
+        normal.on({
+            scope: me,
+            itemmouseleave: me.onItemMouseLeave,
+            itemmouseenter: me.onItemMouseEnter
+        });
+
+        locked.on({
+            scope: me,
+            itemmouseleave: me.onItemMouseLeave,
+            itemmouseenter: me.onItemMouseEnter
+        });
     },
 
-    
-    onTargetOver : function(e){
-        if(this.disabled || e.within(this.target.dom, true)){
-            return;
-        }
-        var t = e.getTarget(this.delegate);
-        if (t) {
-            this.triggerElement = t;
-            this.clearTimer('hide');
-            this.targetXY = e.getXY();
-            this.delayShow();
-        }
+    getGridColumns: function() {
+        var cols = this.lockedGrid.headerCt.getGridColumns();
+        return cols.concat(this.normalGrid.headerCt.getGridColumns());
     },
 
-    
-    delayShow : function(){
-        if(this.hidden && !this.showTimer){
-            if(this.lastActive.getElapsed() < this.quickShowInterval){
-                this.show();
-            }else{
-                this.showTimer = this.show.defer(this.showDelay, this);
-            }
-        }else if(!this.hidden && this.autoHide !== false){
-            this.show();
-        }
+    getEl: function(column){
+        return this.getViewForColumn(column).getEl();
     },
 
-    
-    onTargetOut : function(e){
-        if(this.disabled || e.within(this.target.dom, true)){
-            return;
-        }
-        this.clearTimer('show');
-        if(this.autoHide !== false){
-            this.delayHide();
-        }
+    getViewForColumn: function(column) {
+        var view = this.lockedView,
+            inLocked;
+
+        view.headerCt.cascade(function(col){
+            if (col === column) {
+                inLocked = true;
+                return false;
+            }
+        });
+
+        return inLocked ? view : this.normalView;
     },
 
-    
-    delayHide : function(){
-        if(!this.hidden && !this.hideTimer){
-            this.hideTimer = this.hide.defer(this.hideDelay, this);
+    onItemMouseEnter: function(view, record){
+        var me = this,
+            locked = me.lockedView,
+            other = me.normalView,
+            item;
+
+        if (view.trackOver) {
+            if (view !== locked) {
+                other = locked;
+            }
+            item = other.getNode(record);
+            other.highlightItem(item);
         }
     },
 
-    
-    hide: function(){
-        this.clearTimer('dismiss');
-        this.lastActive = new Date();
-        if(this.anchorEl){
-            this.anchorEl.hide();
+    onItemMouseLeave: function(view, record){
+        var me = this,
+            locked = me.lockedView,
+            other = me.normalView;
+
+        if (view.trackOver) {
+            if (view !== locked) {
+                other = locked;
+            }
+            other.clearHighlight();
         }
-        Ext.ToolTip.superclass.hide.call(this);
-        delete this.triggerElement;
     },
 
-    
-    show : function(){
-        if(this.anchor){
-            
-            
-            this.showAt([-1000,-1000]);
-            this.origConstrainPosition = this.constrainPosition;
-            this.constrainPosition = false;
-            this.anchor = this.origAnchor;
-        }
-        this.showAt(this.getTargetXY());
+    relayFn: function(name, args){
+        args = args || [];
 
-        if(this.anchor){
-            this.syncAnchor();
-            this.anchorEl.show();
-            this.constrainPosition = this.origConstrainPosition;
-        }else{
-            this.anchorEl.hide();
-        }
+        var view = this.lockedView;
+        view[name].apply(view, args || []);
+        view = this.normalView;
+        view[name].apply(view, args || []);
     },
 
-    
-    showAt : function(xy){
-        this.lastActive = new Date();
-        this.clearTimers();
-        Ext.ToolTip.superclass.showAt.call(this, xy);
-        if(this.dismissDelay && this.autoHide !== false){
-            this.dismissTimer = this.hide.defer(this.dismissDelay, this);
-        }
-        if(this.anchor && !this.anchorEl.isVisible()){
-            this.syncAnchor();
-            this.anchorEl.show();
-        }else{
-            this.anchorEl.hide();
-        }
+    getSelectionModel: function(){
+        return this.panel.getSelectionModel();
     },
 
-    
-    syncAnchor : function(){
-        var anchorPos, targetPos, offset;
-        switch(this.tipAnchor.charAt(0)){
-            case 't':
-                anchorPos = 'b';
-                targetPos = 'tl';
-                offset = [20+this.anchorOffset, 2];
-                break;
-            case 'r':
-                anchorPos = 'l';
-                targetPos = 'tr';
-                offset = [-2, 11+this.anchorOffset];
-                break;
-            case 'b':
-                anchorPos = 't';
-                targetPos = 'bl';
-                offset = [20+this.anchorOffset, -2];
-                break;
-            default:
-                anchorPos = 'r';
-                targetPos = 'tl';
-                offset = [2, 11+this.anchorOffset];
-                break;
-        }
-        this.anchorEl.alignTo(this.el, anchorPos+'-'+targetPos, offset);
+    getStore: function(){
+        return this.panel.store;
     },
 
-    
-    setPagePosition : function(x, y){
-        Ext.ToolTip.superclass.setPagePosition.call(this, x, y);
-        if(this.anchor){
-            this.syncAnchor();
-        }
+    getNode: function(nodeInfo){
+        
+        return this.normalView.getNode(nodeInfo);
     },
 
-    
-    clearTimer : function(name){
-        name = name + 'Timer';
-        clearTimeout(this[name]);
-        delete this[name];
+    getCell: function(record, column){
+        var view = this.getViewForColumn(column),
+            row;
+
+        row = view.getNode(record);
+        return Ext.fly(row).down(column.getCellSelector());
     },
 
-    
-    clearTimers : function(){
-        this.clearTimer('show');
-        this.clearTimer('dismiss');
-        this.clearTimer('hide');
+    getRecord: function(node){
+        var result = this.lockedView.getRecord(node);
+        if (!node) {
+            result = this.normalView.getRecord(node);
+        }
+        return result;
     },
 
-    
-    onShow : function(){
-        Ext.ToolTip.superclass.onShow.call(this);
-        Ext.getDoc().on('mousedown', this.onDocMouseDown, this);
+    addElListener: function(eventName, fn, scope){
+        this.relayFn('addElListener', arguments);
     },
 
-    
-    onHide : function(){
-        Ext.ToolTip.superclass.onHide.call(this);
-        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
+    refreshNode: function(){
+        this.relayFn('refreshNode', arguments);
     },
 
-    
-    onDocMouseDown : function(e){
-        if(this.autoHide !== true && !this.closable && !e.within(this.el.dom)){
-            this.disable();
-            this.doEnable.defer(100, this);
-        }
-    },
-    
-    
-    doEnable : function(){
-        if(!this.isDestroyed){
-            this.enable();
-        }
+    refresh: function(){
+        this.relayFn('refresh', arguments);
     },
 
-    
-    onDisable : function(){
-        this.clearTimers();
-        this.hide();
+    bindStore: function(){
+        this.relayFn('bindStore', arguments);
     },
 
-    
-    adjustPosition : function(x, y){
-        if(this.contstrainPosition){
-            var ay = this.targetXY[1], h = this.getSize().height;
-            if(y <= ay && (y+h) >= ay){
-                y = ay-h-5;
-            }
-        }
-        return {x : x, y: y};
-    },
-    
-    beforeDestroy : function(){
-        this.clearTimers();
-        Ext.destroy(this.anchorEl);
-        delete this.anchorEl;
-        delete this.target;
-        delete this.anchorTarget;
-        delete this.triggerElement;
-        Ext.ToolTip.superclass.beforeDestroy.call(this);    
+    addRowCls: function(){
+        this.relayFn('addRowCls', arguments);
     },
 
-    
-    onDestroy : function(){
-        Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
-        Ext.ToolTip.superclass.onDestroy.call(this);
+    removeRowCls: function(){
+        this.relayFn('removeRowCls', arguments);
     }
+
 });
 
-Ext.reg('tooltip', Ext.ToolTip);
-Ext.QuickTip = Ext.extend(Ext.ToolTip, {
-    
-    
-    interceptTitles : false,
+Ext.define('Ext.grid.Lockable', {
 
-    
-    tagConfig : {
-        namespace : "ext",
-        attribute : "qtip",
-        width : "qwidth",
-        target : "target",
-        title : "qtitle",
-        hide : "hide",
-        cls : "qclass",
-        align : "qalign",
-        anchor : "anchor"
-    },
+    requires: ['Ext.grid.LockingView'],
 
     
-    initComponent : function(){
-        this.target = this.target || Ext.getDoc();
-        this.targets = this.targets || {};
-        Ext.QuickTip.superclass.initComponent.call(this);
-    },
+    syncRowHeight: true,
 
     
-    register : function(config){
-        var cs = Ext.isArray(config) ? config : arguments;
-        for(var i = 0, len = cs.length; i < len; i++){
-            var c = cs[i];
-            var target = c.target;
-            if(target){
-                if(Ext.isArray(target)){
-                    for(var j = 0, jlen = target.length; j < jlen; j++){
-                        this.targets[Ext.id(target[j])] = c;
-                    }
-                } else{
-                    this.targets[Ext.id(target)] = c;
-                }
-            }
-        }
-    },
 
     
-    unregister : function(el){
-        delete this.targets[Ext.id(el)];
-    },
-    
-    
-    cancelShow: function(el){
-        var at = this.activeTarget;
-        el = Ext.get(el).dom;
-        if(this.isVisible()){
-            if(at && at.el == el){
-                this.hide();
-            }
-        }else if(at && at.el == el){
-            this.clearTimer('show');
-        }
-    },
+
     
-    getTipCfg: function(e) {
-        var t = e.getTarget(), 
-            ttp, 
-            cfg;
-        if(this.interceptTitles && t.title && Ext.isString(t.title)){
-            ttp = t.title;
-            t.qtip = ttp;
-            t.removeAttribute("title");
-            e.preventDefault();
-        }else{
-            cfg = this.tagConfig;
-            ttp = t.qtip || Ext.fly(t).getAttribute(cfg.attribute, cfg.namespace);
-        }
-        return ttp;
-    },
 
     
-    onTargetOver : function(e){
-        if(this.disabled){
-            return;
-        }
-        this.targetXY = e.getXY();
-        var t = e.getTarget();
-        if(!t || t.nodeType !== 1 || t == document || t == document.body){
-            return;
-        }
-        if(this.activeTarget && ((t == this.activeTarget.el) || Ext.fly(this.activeTarget.el).contains(t))){
-            this.clearTimer('hide');
-            this.show();
-            return;
-        }
-        if(t && this.targets[t.id]){
-            this.activeTarget = this.targets[t.id];
-            this.activeTarget.el = t;
-            this.anchor = this.activeTarget.anchor;
-            if(this.anchor){
-                this.anchorTarget = t;
-            }
-            this.delayShow();
-            return;
-        }
-        var ttp, et = Ext.fly(t), cfg = this.tagConfig, ns = cfg.namespace;
-        if(ttp = this.getTipCfg(e)){
-            var autoHide = et.getAttribute(cfg.hide, ns);
-            this.activeTarget = {
-                el: t,
-                text: ttp,
-                width: et.getAttribute(cfg.width, ns),
-                autoHide: autoHide != "user" && autoHide !== 'false',
-                title: et.getAttribute(cfg.title, ns),
-                cls: et.getAttribute(cfg.cls, ns),
-                align: et.getAttribute(cfg.align, ns)
-                
-            };
-            this.anchor = et.getAttribute(cfg.anchor, ns);
-            if(this.anchor){
-                this.anchorTarget = t;
-            }
-            this.delayShow();
-        }
-    },
+    spacerHidden: true,
+
+    headerCounter: 0,
 
     
-    onTargetOut : function(e){
+    unlockText: 'Unlock',
+    lockText: 'Lock',
 
-        
-        if (this.activeTarget && e.within(this.activeTarget.el) && !this.getTipCfg(e)) {
-            return;
-        }
+    determineXTypeToCreate: function() {
+        var me = this,
+            typeToCreate;
 
-        this.clearTimer('show');
-        if(this.autoHide !== false){
-            this.delayHide();
-        }
-    },
+        if (me.subGridXType) {
+            typeToCreate = me.subGridXType;
+        } else {
+            var xtypes     = this.getXTypes().split('/'),
+                xtypesLn   = xtypes.length,
+                xtype      = xtypes[xtypesLn - 1],
+                superxtype = xtypes[xtypesLn - 2];
 
-    
-    showAt : function(xy){
-        var t = this.activeTarget;
-        if(t){
-            if(!this.rendered){
-                this.render(Ext.getBody());
-                this.activeTarget = t;
-            }
-            if(t.width){
-                this.setWidth(t.width);
-                this.body.setWidth(this.adjustBodyWidth(t.width - this.getFrameWidth()));
-                this.measureWidth = false;
-            } else{
-                this.measureWidth = true;
-            }
-            this.setTitle(t.title || '');
-            this.body.update(t.text);
-            this.autoHide = t.autoHide;
-            this.dismissDelay = t.dismissDelay || this.dismissDelay;
-            if(this.lastCls){
-                this.el.removeClass(this.lastCls);
-                delete this.lastCls;
-            }
-            if(t.cls){
-                this.el.addClass(t.cls);
-                this.lastCls = t.cls;
-            }
-            if(this.anchor){
-                this.constrainPosition = false;
-            }else if(t.align){ 
-                xy = this.el.getAlignToXY(t.el, t.align);
-                this.constrainPosition = false;
-            }else{
-                this.constrainPosition = true;
+            if (superxtype !== 'tablepanel') {
+                typeToCreate = superxtype;
+            } else {
+                typeToCreate = xtype;
             }
         }
-        Ext.QuickTip.superclass.showAt.call(this, xy);
+
+        return typeToCreate;
     },
 
     
-    hide: function(){
-        delete this.activeTarget;
-        Ext.QuickTip.superclass.hide.call(this);
-    }
-});
-Ext.reg('quicktip', Ext.QuickTip);
-Ext.QuickTips = function(){
-    var tip, locks = [];
-    return {
+    
+    injectLockable: function() {
         
-        init : function(autoRender){
-            if(!tip){
-                if(!Ext.isReady){
-                    Ext.onReady(function(){
-                        Ext.QuickTips.init(autoRender);
-                    });
-                    return;
-                }
-                tip = new Ext.QuickTip({elements:'header,body'});
-                if(autoRender !== false){
-                    tip.render(Ext.getBody());
-                }
-            }
-        },
-
+        this.lockable = true;
         
-        enable : function(){
-            if(tip){
-                locks.pop();
-                if(locks.length < 1){
-                    tip.enable();
-                }
-            }
-        },
-
         
-        disable : function(){
-            if(tip){
-                tip.disable();
-            }
-            locks.push(1);
-        },
+        this.hasView = true;
 
-        
-        isEnabled : function(){
-            return tip !== undefined && !tip.disabled;
-        },
+        var me = this,
+            
+            
+            
+            xtype = me.determineXTypeToCreate(),
+            
+            selModel = me.getSelectionModel(),
+            lockedGrid = {
+                xtype: xtype,
+                
+                enableAnimations: false,
+                scroll: false,
+                scrollerOwner: false,
+                selModel: selModel,
+                border: false,
+                cls: Ext.baseCSSPrefix + 'grid-inner-locked'
+            },
+            normalGrid = {
+                xtype: xtype,
+                enableAnimations: false,
+                scrollerOwner: false,
+                selModel: selModel,
+                border: false
+            },
+            i = 0,
+            columns,
+            lockedHeaderCt,
+            normalHeaderCt;
 
-        
-        getQuickTip : function(){
-            return tip;
-        },
+        me.addCls(Ext.baseCSSPrefix + 'grid-locked');
 
         
-        register : function(){
-            tip.register.apply(tip, arguments);
-        },
-
         
-        unregister : function(){
-            tip.unregister.apply(tip, arguments);
-        },
-
         
-        tips :function(){
-            tip.register.apply(tip, arguments);
+        Ext.copyTo(normalGrid, me, me.normalCfgCopy);
+        Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
+        for (; i < me.normalCfgCopy.length; i++) {
+            delete me[me.normalCfgCopy[i]];
+        }
+        for (i = 0; i < me.lockedCfgCopy.length; i++) {
+            delete me[me.lockedCfgCopy[i]];
         }
-    }
-}();
-Ext.slider.Tip = Ext.extend(Ext.Tip, {
-    minWidth: 10,
-    offsets : [0, -10],
-    
-    init: function(slider) {
-        slider.on({
-            scope    : this,
-            dragstart: this.onSlide,
-            drag     : this.onSlide,
-            dragend  : this.hide,
-            destroy  : this.destroy
-        });
-    },
-    
-    
-    onSlide : function(slider, e, thumb) {
-        this.show();
-        this.body.update(this.getText(thumb));
-        this.doAutoWidth();
-        this.el.alignTo(thumb.el, 'b-t?', this.offsets);
-    },
 
-    
-    getText : function(thumb) {
-        return String(thumb.value);
-    }
-});
+        me.addEvents(
+            
+            'lockcolumn',
+
+            
+            'unlockcolumn'
+        );
 
+        me.addStateEvents(['lockcolumn', 'unlockcolumn']);
 
-Ext.ux.SliderTip = Ext.slider.Tip;
-Ext.tree.TreePanel = Ext.extend(Ext.Panel, {
-    rootVisible : true,
-    animate : Ext.enableFx,
-    lines : true,
-    enableDD : false,
-    hlDrop : Ext.enableFx,
-    pathSeparator : '/',
+        me.lockedHeights = [];
+        me.normalHeights = [];
 
-    
-    bubbleEvents : [],
+        columns = me.processColumns(me.columns);
 
-    initComponent : function(){
-        Ext.tree.TreePanel.superclass.initComponent.call(this);
+        lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0);
+        lockedGrid.columns = columns.locked;
+        normalGrid.columns = columns.normal;
 
-        if(!this.eventModel){
-            this.eventModel = new Ext.tree.TreeEventModel(this);
-        }
+        me.store = Ext.StoreManager.lookup(me.store);
+        lockedGrid.store = me.store;
+        normalGrid.store = me.store;
 
         
-        var l = this.loader;
-        if(!l){
-            l = new Ext.tree.TreeLoader({
-                dataUrl: this.dataUrl,
-                requestMethod: this.requestMethod
+        normalGrid.flex = 1;
+        lockedGrid.viewConfig = me.lockedViewConfig || {};
+        lockedGrid.viewConfig.loadingUseMsg = false;
+        normalGrid.viewConfig = me.normalViewConfig || {};
+
+        Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
+        Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
+
+        me.normalGrid = Ext.ComponentManager.create(normalGrid);
+        me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
+
+        me.view = Ext.create('Ext.grid.LockingView', {
+            locked: me.lockedGrid,
+            normal: me.normalGrid,
+            panel: me
+        });
+
+        if (me.syncRowHeight) {
+            me.lockedGrid.getView().on({
+                refresh: me.onLockedGridAfterRefresh,
+                itemupdate: me.onLockedGridAfterUpdate,
+                scope: me
+            });
+
+            me.normalGrid.getView().on({
+                refresh: me.onNormalGridAfterRefresh,
+                itemupdate: me.onNormalGridAfterUpdate,
+                scope: me
             });
-        }else if(Ext.isObject(l) && !l.load){
-            l = new Ext.tree.TreeLoader(l);
         }
-        this.loader = l;
 
-        this.nodeHash = {};
+        lockedHeaderCt = me.lockedGrid.headerCt;
+        normalHeaderCt = me.normalGrid.headerCt;
 
-        
-        if(this.root){
-            var r = this.root;
-            delete this.root;
-            this.setRootNode(r);
-        }
+        lockedHeaderCt.lockedCt = true;
+        lockedHeaderCt.lockableInjected = true;
+        normalHeaderCt.lockableInjected = true;
 
+        lockedHeaderCt.on({
+            columnshow: me.onLockedHeaderShow,
+            columnhide: me.onLockedHeaderHide,
+            columnmove: me.onLockedHeaderMove,
+            sortchange: me.onLockedHeaderSortChange,
+            columnresize: me.onLockedHeaderResize,
+            scope: me
+        });
 
-        this.addEvents(
+        normalHeaderCt.on({
+            columnmove: me.onNormalHeaderMove,
+            sortchange: me.onNormalHeaderSortChange,
+            scope: me
+        });
 
-            
-           'append',
-           
-           'remove',
-           
-           'movenode',
-           
-           'insert',
-           
-           'beforeappend',
-           
-           'beforeremove',
-           
-           'beforemovenode',
-           
-            'beforeinsert',
+        me.normalGrid.on({
+            scrollershow: me.onScrollerShow,
+            scrollerhide: me.onScrollerHide,
+            scope: me
+        });
 
+        me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
+
+        me.modifyHeaderCt();
+        me.items = [me.lockedGrid, me.normalGrid];
+
+        me.relayHeaderCtEvents(lockedHeaderCt);
+        me.relayHeaderCtEvents(normalHeaderCt);
+
+        me.layout = {
+            type: 'hbox',
+            align: 'stretch'
+        };
+    },
+
+    processColumns: function(columns){
+        
+        var i = 0,
+            len = columns.length,
+            lockedWidth = 1,
+            lockedHeaders = [],
+            normalHeaders = [],
+            column;
+
+        for (; i < len; ++i) {
+            column = columns[i];
             
-            'beforeload',
-            
-            'load',
-            
-            'textchange',
-            
-            'beforeexpandnode',
-            
-            'beforecollapsenode',
-            
-            'expandnode',
-            
-            'disabledchange',
-            
-            'collapsenode',
-            
-            'beforeclick',
-            
-            'click',
-            
-            'containerclick',
-            
-            'checkchange',
-            
-            'beforedblclick',
-            
-            'dblclick',
-            
-            'containerdblclick',
-            
-            'contextmenu',
-            
-            'containercontextmenu',
-            
-            'beforechildrenrendered',
-           
-            'startdrag',
-            
-            'enddrag',
-            
-            'dragdrop',
-            
-            'beforenodedrop',
             
-            'nodedrop',
-             
-            'nodedragover'
-        );
-        if(this.singleExpand){
-            this.on('beforeexpandnode', this.restrictExpand, this);
+            column.processed = true;
+            if (column.locked) {
+                if (!column.hidden) {
+                    lockedWidth += column.width || Ext.grid.header.Container.prototype.defaultWidth;
+                }
+                lockedHeaders.push(column);
+            } else {
+                normalHeaders.push(column);
+            }
+            if (!column.headerId) {
+                column.headerId = (column.initialConfig || column).id || ('L' + (++this.headerCounter));
+            }
         }
+        return {
+            lockedWidth: lockedWidth,
+            locked: lockedHeaders,
+            normal: normalHeaders
+        };
     },
 
     
-    proxyNodeEvent : function(ename, a1, a2, a3, a4, a5, a6){
-        if(ename == 'collapse' || ename == 'expand' || ename == 'beforecollapse' || ename == 'beforeexpand' || ename == 'move' || ename == 'beforemove'){
-            ename = ename+'node';
-        }
-        
-        return this.fireEvent(ename, a1, a2, a3, a4, a5, a6);
+    onLockedGridAfterLayout: function() {
+        var me         = this,
+            lockedView = me.lockedGrid.getView();
+        lockedView.on({
+            beforerefresh: me.destroySpacer,
+            scope: me
+        });
     },
 
-
     
-    getRootNode : function(){
-        return this.root;
+    onLockedHeaderMove: function() {
+        if (this.syncRowHeight) {
+            this.onNormalGridAfterRefresh();
+        }
     },
 
     
-    setRootNode : function(node){
-        this.destroyRoot();
-        if(!node.render){ 
-            node = this.loader.createNode(node);
-        }
-        this.root = node;
-        node.ownerTree = this;
-        node.isRoot = true;
-        this.registerNode(node);
-        if(!this.rootVisible){
-            var uiP = node.attributes.uiProvider;
-            node.ui = uiP ? new uiP(node) : new Ext.tree.RootTreeNodeUI(node);
+    onNormalHeaderMove: function() {
+        if (this.syncRowHeight) {
+            this.onLockedGridAfterRefresh();
         }
-        if(this.innerCt){
-            this.clearInnerCt();
-            this.renderRoot();
-        }
-        return node;
-    },
-    
-    clearInnerCt : function(){
-        this.innerCt.update('');    
     },
+
     
     
-    renderRoot : function(){
-        this.root.render();
-        if(!this.rootVisible){
-            this.root.renderChildren();
+    getSpacerEl: function() {
+        var me   = this,
+            w,
+            view,
+            el;
+
+        if (!me.spacerEl) {
+            
+            
+            w    = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0);
+            view = me.lockedGrid.getView();
+            el   = view.el;
+
+            me.spacerEl = Ext.DomHelper.append(el, {
+                cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
+                style: 'height: ' + w + 'px;'
+            }, true);
+        }
+        return me.spacerEl;
+    },
+
+    destroySpacer: function() {
+        var me = this;
+        if (me.spacerEl) {
+            me.spacerEl.destroy();
+            delete me.spacerEl;
         }
     },
 
     
-    getNodeById : function(id){
-        return this.nodeHash[id];
+    onLockedGridAfterRefresh: function() {
+        var me     = this,
+            view   = me.lockedGrid.getView(),
+            el     = view.el,
+            rowEls = el.query(view.getItemSelector()),
+            ln     = rowEls.length,
+            i = 0;
+
+        
+        me.lockedHeights = [];
+
+        for (; i < ln; i++) {
+            me.lockedHeights[i] = rowEls[i].clientHeight;
+        }
+        me.syncRowHeights();
     },
 
     
-    registerNode : function(node){
-        this.nodeHash[node.id] = node;
+    onNormalGridAfterRefresh: function() {
+        var me     = this,
+            view   = me.normalGrid.getView(),
+            el     = view.el,
+            rowEls = el.query(view.getItemSelector()),
+            ln     = rowEls.length,
+            i = 0;
+
+        
+        me.normalHeights = [];
+
+        for (; i < ln; i++) {
+            me.normalHeights[i] = rowEls[i].clientHeight;
+        }
+        me.syncRowHeights();
     },
 
     
-    unregisterNode : function(node){
-        delete this.nodeHash[node.id];
+    onLockedGridAfterUpdate: function(record, index, node) {
+        this.lockedHeights[index] = node.clientHeight;
+        this.syncRowHeights();
     },
 
     
-    toString : function(){
-        return '[Tree'+(this.id?' '+this.id:'')+']';
+    onNormalGridAfterUpdate: function(record, index, node) {
+        this.normalHeights[index] = node.clientHeight;
+        this.syncRowHeights();
     },
 
     
-    restrictExpand : function(node){
-        var p = node.parentNode;
-        if(p){
-            if(p.expandedChild && p.expandedChild.parentNode == p){
-                p.expandedChild.collapse();
+    
+    syncRowHeights: function() {
+        var me = this,
+            lockedHeights = me.lockedHeights,
+            normalHeights = me.normalHeights,
+            calcHeights   = [],
+            ln = lockedHeights.length,
+            i  = 0,
+            lockedView, normalView,
+            lockedRowEls, normalRowEls,
+            vertScroller = me.getVerticalScroller(),
+            scrollTop;
+
+        
+        
+        if (lockedHeights.length && normalHeights.length) {
+            lockedView = me.lockedGrid.getView();
+            normalView = me.normalGrid.getView();
+            lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
+            normalRowEls = normalView.el.query(normalView.getItemSelector());
+
+            
+            for (; i < ln; i++) {
+                
+                if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
+                    if (lockedHeights[i] > normalHeights[i]) {
+                        Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
+                    } else if (lockedHeights[i] < normalHeights[i]) {
+                        Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
+                    }
+                }
             }
-            p.expandedChild = node;
+
+            
+            me.normalGrid.invalidateScroller();
+
+            
+            
+            if (vertScroller && vertScroller.setViewScrollTop) {
+                vertScroller.setViewScrollTop(me.virtualScrollTop);
+            } else {
+                
+                
+                
+                scrollTop = normalView.el.dom.scrollTop;
+                normalView.el.dom.scrollTop = scrollTop;
+                lockedView.el.dom.scrollTop = scrollTop;
+            }
+
+            
+            me.lockedHeights = [];
+            me.normalHeights = [];
         }
     },
 
     
-    getChecked : function(a, startNode){
-        startNode = startNode || this.root;
-        var r = [];
-        var f = function(){
-            if(this.attributes.checked){
-                r.push(!a ? this : (a == 'id' ? this.id : this.attributes[a]));
-            }
-        };
-        startNode.cascade(f);
-        return r;
+    onScrollerShow: function(scroller, direction) {
+        if (direction === 'horizontal') {
+            this.spacerHidden = false;
+            this.getSpacerEl().removeCls(Ext.baseCSSPrefix + 'hidden');
+        }
     },
 
     
-    getLoader : function(){
-        return this.loader;
+    onScrollerHide: function(scroller, direction) {
+        if (direction === 'horizontal') {
+            this.spacerHidden = true;
+            if (this.spacerEl) {
+                this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
+            }
+        }
     },
 
+
     
-    expandAll : function(){
-        this.root.expand(true);
+    modifyHeaderCt: function() {
+        var me = this;
+        me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
+        me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
     },
 
-    
-    collapseAll : function(){
-        this.root.collapse(true);
+    onUnlockMenuClick: function() {
+        this.unlock();
     },
 
-    
-    getSelectionModel : function(){
-        if(!this.selModel){
-            this.selModel = new Ext.tree.DefaultSelectionModel();
-        }
-        return this.selModel;
+    onLockMenuClick: function() {
+        this.lock();
     },
 
-    
-    expandPath : function(path, attr, callback){
-        if(Ext.isEmpty(path)){
-            if(callback){
-                callback(false, undefined);
-            }
-            return;
-        }
-        attr = attr || 'id';
-        var keys = path.split(this.pathSeparator);
-        var curNode = this.root;
-        if(curNode.attributes[attr] != keys[1]){ 
-            if(callback){
-                callback(false, null);
-            }
-            return;
-        }
-        var index = 1;
-        var f = function(){
-            if(++index == keys.length){
-                if(callback){
-                    callback(true, curNode);
-                }
-                return;
-            }
-            var c = curNode.findChild(attr, keys[index]);
-            if(!c){
-                if(callback){
-                    callback(false, curNode);
-                }
-                return;
-            }
-            curNode = c;
-            c.expand(false, false, f);
+    getMenuItems: function(locked) {
+        var me            = this,
+            unlockText    = me.unlockText,
+            lockText      = me.lockText,
+            unlockCls     = Ext.baseCSSPrefix + 'hmenu-unlock',
+            lockCls       = Ext.baseCSSPrefix + 'hmenu-lock',
+            unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
+            lockHandler   = Ext.Function.bind(me.onLockMenuClick, me);
+
+        
+        return function() {
+            var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
+            o.push('-',{
+                cls: unlockCls,
+                text: unlockText,
+                handler: unlockHandler,
+                disabled: !locked
+            });
+            o.push({
+                cls: lockCls,
+                text: lockText,
+                handler: lockHandler,
+                disabled: locked
+            });
+            return o;
         };
-        curNode.expand(false, false, f);
     },
 
     
-    selectPath : function(path, attr, callback){
-        if(Ext.isEmpty(path)){
-            if(callback){
-                callback(false, undefined);
-            }
-            return;
+    
+    lock: function(activeHd, toIdx) {
+        var me         = this,
+            normalGrid = me.normalGrid,
+            lockedGrid = me.lockedGrid,
+            normalHCt  = normalGrid.headerCt,
+            lockedHCt  = lockedGrid.headerCt;
+
+        activeHd = activeHd || normalHCt.getMenu().activeHeader;
+
+        
+        
+        if (activeHd.flex) {
+            activeHd.width = activeHd.getWidth();
+            delete activeHd.flex;
         }
-        attr = attr || 'id';
-        var keys = path.split(this.pathSeparator),
-            v = keys.pop();
-        if(keys.length > 1){
-            var f = function(success, node){
-                if(success && node){
-                    var n = node.findChild(attr, v);
-                    if(n){
-                        n.select();
-                        if(callback){
-                            callback(true, n);
-                        }
-                    }else if(callback){
-                        callback(false, n);
-                    }
-                }else{
-                    if(callback){
-                        callback(false, n);
-                    }
-                }
-            };
-            this.expandPath(keys.join(this.pathSeparator), attr, f);
-        }else{
-            this.root.select();
-            if(callback){
-                callback(true, this.root);
-            }
+
+        normalHCt.remove(activeHd, false);
+        lockedHCt.suspendLayout = true;
+        activeHd.locked = true;
+        if (Ext.isDefined(toIdx)) {
+            lockedHCt.insert(toIdx, activeHd);
+        } else {
+            lockedHCt.add(activeHd);
         }
+        lockedHCt.suspendLayout = false;
+        me.syncLockedSection();
+
+        me.fireEvent('lockcolumn', me, activeHd);
     },
 
-    
-    getTreeEl : function(){
-        return this.body;
+    syncLockedSection: function() {
+        var me = this;
+        me.syncLockedWidth();
+        me.lockedGrid.getView().refresh();
+        me.normalGrid.getView().refresh();
     },
 
     
-    onRender : function(ct, position){
-        Ext.tree.TreePanel.superclass.onRender.call(this, ct, position);
-        this.el.addClass('x-tree');
-        this.innerCt = this.body.createChild({tag:'ul',
-               cls:'x-tree-root-ct ' +
-               (this.useArrows ? 'x-tree-arrows' : this.lines ? 'x-tree-lines' : 'x-tree-no-lines')});
+    
+    syncLockedWidth: function() {
+        var me = this,
+            width = me.lockedGrid.headerCt.getFullWidth(true);
+        me.lockedGrid.setWidth(width+1); 
+        me.doComponentLayout();
     },
 
-    
-    initEvents : function(){
-        Ext.tree.TreePanel.superclass.initEvents.call(this);
+    onLockedHeaderResize: function() {
+        this.syncLockedWidth();
+    },
 
-        if(this.containerScroll){
-            Ext.dd.ScrollManager.register(this.body);
-        }
-        if((this.enableDD || this.enableDrop) && !this.dropZone){
-           
-             this.dropZone = new Ext.tree.TreeDropZone(this, this.dropConfig || {
-               ddGroup: this.ddGroup || 'TreeDD', appendOnly: this.ddAppendOnly === true
-           });
-        }
-        if((this.enableDD || this.enableDrag) && !this.dragZone){
-           
-            this.dragZone = new Ext.tree.TreeDragZone(this, this.dragConfig || {
-               ddGroup: this.ddGroup || 'TreeDD',
-               scroll: this.ddScroll
-           });
-        }
-        this.getSelectionModel().init(this);
+    onLockedHeaderHide: function() {
+        this.syncLockedWidth();
     },
 
-    
-    afterRender : function(){
-        Ext.tree.TreePanel.superclass.afterRender.call(this);
-        this.renderRoot();
+    onLockedHeaderShow: function() {
+        this.syncLockedWidth();
     },
 
-    beforeDestroy : function(){
-        if(this.rendered){
-            Ext.dd.ScrollManager.unregister(this.body);
-            Ext.destroy(this.dropZone, this.dragZone);
+    onLockedHeaderSortChange: function(headerCt, header, sortState) {
+        if (sortState) {
+            
+            
+            this.normalGrid.headerCt.clearOtherSortStates(null, true);
         }
-        this.destroyRoot();
-        Ext.destroy(this.loader);
-        this.nodeHash = this.root = this.loader = null;
-        Ext.tree.TreePanel.superclass.beforeDestroy.call(this);
     },
-    
-    
-    destroyRoot : function(){
-        if(this.root && this.root.destroy){
-            this.root.destroy(true);
+
+    onNormalHeaderSortChange: function(headerCt, header, sortState) {
+        if (sortState) {
+            
+            
+            this.lockedGrid.headerCt.clearOtherSortStates(null, true);
         }
-    }
+    },
 
     
     
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    unlock: function(activeHd, toIdx) {
+        var me         = this,
+            normalGrid = me.normalGrid,
+            lockedGrid = me.lockedGrid,
+            normalHCt  = normalGrid.headerCt,
+            lockedHCt  = lockedGrid.headerCt;
 
+        if (!Ext.isDefined(toIdx)) {
+            toIdx = 0;
+        }
+        activeHd = activeHd || lockedHCt.getMenu().activeHeader;
 
+        lockedHCt.remove(activeHd, false);
+        me.syncLockedWidth();
+        me.lockedGrid.getView().refresh();
+        activeHd.locked = false;
+        normalHCt.insert(toIdx, activeHd);
+        me.normalGrid.getView().refresh();
 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-});
+        me.fireEvent('unlockcolumn', me, activeHd);
+    },
 
-Ext.tree.TreePanel.nodeTypes = {};
+    applyColumnsState: function (columns) {
+        var me = this,
+            lockedGrid = me.lockedGrid,
+            lockedHeaderCt = lockedGrid.headerCt,
+            normalHeaderCt = me.normalGrid.headerCt,
+            lockedCols = lockedHeaderCt.items,
+            normalCols = normalHeaderCt.items,
+            existing,
+            locked = [],
+            normal = [],
+            lockedDefault,
+            lockedWidth = 1;
+
+        Ext.each(columns, function (col) {
+            function matches (item) {
+                return item.headerId == col.id;
+            }
+
+            lockedDefault = true;
+            if (!(existing = lockedCols.findBy(matches))) {
+                existing = normalCols.findBy(matches);
+                lockedDefault = false;
+            }
+
+            if (existing) {
+                if (existing.applyColumnState) {
+                    existing.applyColumnState(col);
+                }
+                if (!Ext.isDefined(existing.locked)) {
+                    existing.locked = lockedDefault;
+                }
+                if (existing.locked) {
+                    locked.push(existing);
+                    if (!existing.hidden && Ext.isNumber(existing.width)) {
+                        lockedWidth += existing.width;
+                    }
+                } else {
+                    normal.push(existing);
+                }
+            }
+        });
 
-Ext.reg('treepanel', Ext.tree.TreePanel);Ext.tree.TreeEventModel = function(tree){
-    this.tree = tree;
-    this.tree.on('render', this.initEvents, this);
-};
+        
+        if (locked.length + normal.length == lockedCols.getCount() + normalCols.getCount()) {
+            lockedHeaderCt.removeAll(false);
+            normalHeaderCt.removeAll(false);
 
-Ext.tree.TreeEventModel.prototype = {
-    initEvents : function(){
-        var t = this.tree;
+            lockedHeaderCt.add(locked);
+            normalHeaderCt.add(normal);
 
-        if(t.trackMouseOver !== false){
-            t.mon(t.innerCt, {
-                scope: this,
-                mouseover: this.delegateOver,
-                mouseout: this.delegateOut
-            });
+            lockedGrid.setWidth(lockedWidth);
         }
-        t.mon(t.getTreeEl(), {
-            scope: this,
-            click: this.delegateClick,
-            dblclick: this.delegateDblClick,
-            contextmenu: this.delegateContextMenu
-        });
     },
 
-    getNode : function(e){
-        var t;
-        if(t = e.getTarget('.x-tree-node-el', 10)){
-            var id = Ext.fly(t, '_treeEvents').getAttribute('tree-node-id', 'ext');
-            if(id){
-                return this.tree.getNodeById(id);
-            }
-        }
-        return null;
-    },
+    getColumnsState: function () {
+        var me = this,
+            locked = me.lockedGrid.headerCt.getColumnsState(),
+            normal = me.normalGrid.headerCt.getColumnsState();
 
-    getNodeTarget : function(e){
-        var t = e.getTarget('.x-tree-node-icon', 1);
-        if(!t){
-            t = e.getTarget('.x-tree-node-el', 6);
-        }
-        return t;
+        return locked.concat(normal);
     },
 
-    delegateOut : function(e, t){
-        if(!this.beforeEvent(e)){
-            return;
-        }
-        if(e.getTarget('.x-tree-ec-icon', 1)){
-            var n = this.getNode(e);
-            this.onIconOut(e, n);
-            if(n == this.lastEcOver){
-                delete this.lastEcOver;
-            }
-        }
-        if((t = this.getNodeTarget(e)) && !e.within(t, true)){
-            this.onNodeOut(e, this.getNode(e));
+    
+    reconfigureLockable: function(store, columns) {
+        var me = this,
+            lockedGrid = me.lockedGrid,
+            normalGrid = me.normalGrid;
+
+        if (columns) {
+            lockedGrid.headerCt.suspendLayout = true;
+            normalGrid.headerCt.suspendLayout = true;
+            lockedGrid.headerCt.removeAll();
+            normalGrid.headerCt.removeAll();
+
+            columns = me.processColumns(columns);
+            lockedGrid.setWidth(columns.lockedWidth);
+            lockedGrid.headerCt.add(columns.locked);
+            normalGrid.headerCt.add(columns.normal);
+        }
+
+        if (store) {
+            store = Ext.data.StoreManager.lookup(store);
+            me.store = store;
+            lockedGrid.bindStore(store);
+            normalGrid.bindStore(store);
+        } else {
+            lockedGrid.getView().refresh();
+            normalGrid.getView().refresh();
         }
-    },
 
-    delegateOver : function(e, t){
-        if(!this.beforeEvent(e)){
-            return;
+        if (columns) {
+            lockedGrid.headerCt.suspendLayout = false;
+            normalGrid.headerCt.suspendLayout = false;
+            lockedGrid.headerCt.forceComponentLayout();
+            normalGrid.headerCt.forceComponentLayout();
         }
-        if(Ext.isGecko && !this.trackingDoc){ 
-            Ext.getBody().on('mouseover', this.trackExit, this);
-            this.trackingDoc = true;
-        }
-        if(this.lastEcOver){ 
-            this.onIconOut(e, this.lastEcOver);
-            delete this.lastEcOver;
-        }
-        if(e.getTarget('.x-tree-ec-icon', 1)){
-            this.lastEcOver = this.getNode(e);
-            this.onIconOver(e, this.lastEcOver);
-        }
-        if(t = this.getNodeTarget(e)){
-            this.onNodeOver(e, this.getNode(e));
+    }
+});
+
+
+Ext.define('Ext.grid.Scroller', {
+    extend: 'Ext.Component',
+    alias: 'widget.gridscroller',
+    weight: 110,
+    baseCls: Ext.baseCSSPrefix + 'scroller',
+    focusable: false,
+    reservedSpace: 0,
+
+    renderTpl: [
+        '<div class="' + Ext.baseCSSPrefix + 'scroller-ct" id="{baseId}_ct">',
+            '<div class="' + Ext.baseCSSPrefix + 'stretcher" id="{baseId}_stretch"></div>',
+        '</div>'
+    ],
+
+    initComponent: function() {
+        var me       = this,
+            dock     = me.dock,
+            cls      = Ext.baseCSSPrefix + 'scroller-vertical';
+
+        me.offsets = {bottom: 0};
+        me.scrollProp = 'scrollTop';
+        me.vertical = true;
+        me.sizeProp = 'width';
+
+        if (dock === 'top' || dock === 'bottom') {
+            cls = Ext.baseCSSPrefix + 'scroller-horizontal';
+            me.sizeProp = 'height';
+            me.scrollProp = 'scrollLeft';
+            me.vertical = false;
+            me.weight += 5;
         }
+
+        me.cls += (' ' + cls);
+
+        Ext.applyIf(me.renderSelectors, {
+            stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher',
+            scrollEl: '.' + Ext.baseCSSPrefix + 'scroller-ct'
+        });
+        me.callParent();
+    },
+    
+    ensureDimension: function(){
+        var me = this,
+            sizeProp = me.sizeProp;
+            
+        me[sizeProp] = me.scrollerSize = Ext.getScrollbarSize()[sizeProp];  
     },
 
-    trackExit : function(e){
-        if(this.lastOverNode){
-            if(this.lastOverNode.ui && !e.within(this.lastOverNode.ui.getEl())){
-                this.onNodeOut(e, this.lastOverNode);
-            }
-            delete this.lastOverNode;
-            Ext.getBody().un('mouseover', this.trackExit, this);
-            this.trackingDoc = false;
-        }
+    initRenderData: function () {
+        var me = this,
+            ret = me.callParent(arguments) || {};
 
+        ret.baseId = me.id;
+
+        return ret;
     },
 
-    delegateClick : function(e, t){
-        if(this.beforeEvent(e)){
-            if(e.getTarget('input[type=checkbox]', 1)){
-                this.onCheckboxClick(e, this.getNode(e));
-            }else if(e.getTarget('.x-tree-ec-icon', 1)){
-                this.onIconClick(e, this.getNode(e));
-            }else if(this.getNodeTarget(e)){
-                this.onNodeClick(e, this.getNode(e));
-            }
-        }else{
-            this.checkContainerEvent(e, 'click');
-        }
+    afterRender: function() {
+        var me = this;
+        me.callParent();
+        
+        me.mon(me.scrollEl, 'scroll', me.onElScroll, me);
+        Ext.cache[me.el.id].skipGarbageCollection = true;
     },
 
-    delegateDblClick : function(e, t){
-        if(this.beforeEvent(e)){
-            if(this.getNodeTarget(e)){
-                this.onNodeDblClick(e, this.getNode(e));
-            }
-        }else{
-            this.checkContainerEvent(e, 'dblclick');
-        }
+    onAdded: function(container) {
+        
+        this.ownerGrid = container;
+        this.callParent(arguments);
     },
 
-    delegateContextMenu : function(e, t){
-        if(this.beforeEvent(e)){
-            if(this.getNodeTarget(e)){
-                this.onNodeContextMenu(e, this.getNode(e));
+    getSizeCalculation: function() {
+        var me     = this,
+            owner  = me.getPanel(),
+            width  = 1,
+            height = 1,
+            view, tbl;
+
+        if (!me.vertical) {
+            
+            
+            var items  = owner.query('tableview'),
+                center = items[1] || items[0];
+
+            if (!center) {
+                return false;
             }
-        }else{
-            this.checkContainerEvent(e, 'contextmenu');
-        }
-    },
-    
-    checkContainerEvent: function(e, type){
-        if(this.disabled){
-            e.stopEvent();
-            return false;
+            
+            
+            
+            width = center.headerCt.getFullWidth();
+
+            if (Ext.isIEQuirks) {
+                width--;
+            }
+        } else {
+            view = owner.down('tableview:not([lockableInjected])');
+            if (!view || !view.el) {
+                return false;
+            }
+            tbl = view.el.child('table', true);
+            if (!tbl) {
+                return false;
+            }
+
+            
+            
+            height = tbl.offsetHeight;
         }
-        this.onContainerEvent(e, type);    
+        if (isNaN(width)) {
+            width = 1;
+        }
+        if (isNaN(height)) {
+            height = 1;
+        }
+        return {
+            width: width,
+            height: height
+        };
     },
 
-    onContainerEvent: function(e, type){
-        this.tree.fireEvent('container' + type, this.tree, e);
-    },
+    invalidate: function(firstPass) {
+        var me = this,
+            stretchEl = me.stretchEl;
 
-    onNodeClick : function(e, node){
-        node.ui.onClick(e);
-    },
+        if (!stretchEl || !me.ownerCt) {
+            return;
+        }
 
-    onNodeOver : function(e, node){
-        this.lastOverNode = node;
-        node.ui.onOver(e);
-    },
+        var size  = me.getSizeCalculation(),
+            scrollEl = me.scrollEl,
+            elDom = scrollEl.dom,
+            reservedSpace = me.reservedSpace,
+            pos,
+            extra = 5;
 
-    onNodeOut : function(e, node){
-        node.ui.onOut(e);
-    },
+        if (size) {
+            stretchEl.setSize(size);
 
-    onIconOver : function(e, node){
-        node.ui.addClass('x-tree-ec-over');
-    },
+            size = me.el.getSize(true);
 
-    onIconOut : function(e, node){
-        node.ui.removeClass('x-tree-ec-over');
-    },
+            if (me.vertical) {
+                size.width += extra;
+                size.height -= reservedSpace;
+                pos = 'left';
+            } else {
+                size.width -= reservedSpace;
+                size.height += extra;
+                pos = 'top';
+            }
 
-    onIconClick : function(e, node){
-        node.ui.ecClick(e);
-    },
+            scrollEl.setSize(size);
+            elDom.style[pos] = (-extra) + 'px';
 
-    onCheckboxClick : function(e, node){
-        node.ui.onCheckChange(e);
+            
+            
+            elDom.scrollTop = elDom.scrollTop;
+        }
     },
 
-    onNodeDblClick : function(e, node){
-        node.ui.onDblClick(e);
+    afterComponentLayout: function() {
+        this.callParent(arguments);
+        this.invalidate();
     },
 
-    onNodeContextMenu : function(e, node){
-        node.ui.onContextMenu(e);
-    },
+    restoreScrollPos: function () {
+        var me = this,
+            el = this.scrollEl,
+            elDom = el && el.dom;
 
-    beforeEvent : function(e){
-        var node = this.getNode(e);
-        if(this.disabled || !node || !node.ui){
-            e.stopEvent();
-            return false;
+        if (me._scrollPos !== null && elDom) {
+            elDom[me.scrollProp] = me._scrollPos;
+            me._scrollPos = null;
         }
-        return true;
     },
 
-    disable: function(){
-        this.disabled = true;
+    setReservedSpace: function (reservedSpace) {
+        var me = this;
+        if (me.reservedSpace !== reservedSpace) {
+            me.reservedSpace = reservedSpace;
+            me.invalidate();
+        }
     },
 
-    enable: function(){
-        this.disabled = false;
-    }
-};
-Ext.tree.DefaultSelectionModel = Ext.extend(Ext.util.Observable, {
-    
-    constructor : function(config){
-        this.selNode = null;
-   
-        this.addEvents(
-            
-            'selectionchange',
-
-            
-            'beforeselect'
-        );
+    saveScrollPos: function () {
+        var me = this,
+            el = this.scrollEl,
+            elDom = el && el.dom;
 
-        Ext.apply(this, config);
-        Ext.tree.DefaultSelectionModel.superclass.constructor.call(this);    
-    },
-    
-    init : function(tree){
-        this.tree = tree;
-        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
-        tree.on('click', this.onNodeClick, this);
-    },
-    
-    onNodeClick : function(node, e){
-        this.select(node);
+        me._scrollPos = elDom ? elDom[me.scrollProp] : null;
     },
+
     
-    
-    select : function(node,  selectNextNode){
-        
-        if (!Ext.fly(node.ui.wrap).isVisible() && selectNextNode) {
-            return selectNextNode.call(this, node);
-        }
-        var last = this.selNode;
-        if(node == last){
-            node.ui.onSelectedChange(true);
-        }else if(this.fireEvent('beforeselect', this, node, last) !== false){
-            if(last && last.ui){
-                last.ui.onSelectedChange(false);
-            }
-            this.selNode = node;
-            node.ui.onSelectedChange(true);
-            this.fireEvent('selectionchange', this, node, last);
+    setScrollTop: function(scrollTop) {
+        var el = this.scrollEl,
+            elDom = el && el.dom;
+
+        if (elDom) {
+            return elDom.scrollTop = Ext.Number.constrain(scrollTop, 0, elDom.scrollHeight - elDom.clientHeight);
         }
-        return node;
-    },
-    
-    
-    unselect : function(node, silent){
-        if(this.selNode == node){
-            this.clearSelections(silent);
-        }    
     },
+
     
-    
-    clearSelections : function(silent){
-        var n = this.selNode;
-        if(n){
-            n.ui.onSelectedChange(false);
-            this.selNode = null;
-            if(silent !== true){
-                this.fireEvent('selectionchange', this, null);
-            }
+    setScrollLeft: function(scrollLeft) {
+        var el = this.scrollEl,
+            elDom = el && el.dom;
+
+        if (elDom) {
+            return elDom.scrollLeft = Ext.Number.constrain(scrollLeft, 0, elDom.scrollWidth - elDom.clientWidth);
         }
-        return n;
     },
+
     
-    
-    getSelectedNode : function(){
-        return this.selNode;    
+    scrollByDeltaY: function(delta) {
+        var el = this.scrollEl,
+            elDom = el && el.dom;
+
+        if (elDom) {
+            return this.setScrollTop(elDom.scrollTop + delta);
+        }
     },
+
     
-    
-    isSelected : function(node){
-        return this.selNode == node;  
+    scrollByDeltaX: function(delta) {
+        var el = this.scrollEl,
+            elDom = el && el.dom;
+
+        if (elDom) {
+            return this.setScrollLeft(elDom.scrollLeft + delta);
+        }
     },
 
+
     
-    selectPrevious : function( s){
-        if(!(s = s || this.selNode || this.lastSelNode)){
-            return null;
-        }
-        
-        var ps = s.previousSibling;
-        if(ps){
-            if(!ps.isExpanded() || ps.childNodes.length < 1){
-                return this.select(ps, this.selectPrevious);
-            } else{
-                var lc = ps.lastChild;
-                while(lc && lc.isExpanded() && Ext.fly(lc.ui.wrap).isVisible() && lc.childNodes.length > 0){
-                    lc = lc.lastChild;
-                }
-                return this.select(lc, this.selectPrevious);
-            }
-        } else if(s.parentNode && (this.tree.rootVisible || !s.parentNode.isRoot)){
-            return this.select(s.parentNode, this.selectPrevious);
-        }
-        return null;
+    scrollToTop : function(){
+        this.setScrollTop(0);
     },
 
     
-    selectNext : function( s){
-        if(!(s = s || this.selNode || this.lastSelNode)){
-            return null;
-        }
-        
-        if(s.firstChild && s.isExpanded() && Ext.fly(s.ui.wrap).isVisible()){
-             return this.select(s.firstChild, this.selectNext);
-         }else if(s.nextSibling){
-             return this.select(s.nextSibling, this.selectNext);
-         }else if(s.parentNode){
-            var newS = null;
-            s.parentNode.bubble(function(){
-                if(this.nextSibling){
-                    newS = this.getOwnerTree().selModel.select(this.nextSibling, this.selectNext);
-                    return false;
-                }
-            });
-            return newS;
-         }
-        return null;
+    onElScroll: function(event, target) {
+        this.fireEvent('bodyscroll', event, target);
     },
 
-    onKeyDown : function(e){
-        var s = this.selNode || this.lastSelNode;
-        
-        var sm = this;
-        if(!s){
-            return;
+    getPanel: function() {
+        var me = this;
+        if (!me.panel) {
+            me.panel = this.up('[scrollerOwner]');
         }
-        var k = e.getKey();
-        switch(k){
-             case e.DOWN:
-                 e.stopEvent();
-                 this.selectNext();
-             break;
-             case e.UP:
-                 e.stopEvent();
-                 this.selectPrevious();
-             break;
-             case e.RIGHT:
-                 e.preventDefault();
-                 if(s.hasChildNodes()){
-                     if(!s.isExpanded()){
-                         s.expand();
-                     }else if(s.firstChild){
-                         this.select(s.firstChild, e);
-                     }
-                 }
-             break;
-             case e.LEFT:
-                 e.preventDefault();
-                 if(s.hasChildNodes() && s.isExpanded()){
-                     s.collapse();
-                 }else if(s.parentNode && (this.tree.rootVisible || s.parentNode != this.tree.getRootNode())){
-                     this.select(s.parentNode, e);
-                 }
-             break;
-        };
+        return me.panel;
     }
 });
 
 
-Ext.tree.MultiSelectionModel = Ext.extend(Ext.util.Observable, {
-    
-    constructor : function(config){
-        this.selNodes = [];
-        this.selMap = {};
-        this.addEvents(
-            
-            'selectionchange'
-        );
-        Ext.apply(this, config);
-        Ext.tree.MultiSelectionModel.superclass.constructor.call(this);    
-    },
+
+Ext.define('Ext.grid.PagingScroller', {
+    extend: 'Ext.grid.Scroller',
+    alias: 'widget.paginggridscroller',
     
-    init : function(tree){
-        this.tree = tree;
-        tree.mon(tree.getTreeEl(), 'keydown', this.onKeyDown, this);
-        tree.on('click', this.onNodeClick, this);
-    },
     
-    onNodeClick : function(node, e){
-        if(e.ctrlKey && this.isSelected(node)){
-            this.unselect(node);
-        }else{
-            this.select(node, e, e.ctrlKey);
-        }
-    },
     
     
-    select : function(node, e, keepExisting){
-        if(keepExisting !== true){
-            this.clearSelections(true);
-        }
-        if(this.isSelected(node)){
-            this.lastSelNode = node;
-            return node;
-        }
-        this.selNodes.push(node);
-        this.selMap[node.id] = node;
-        this.lastSelNode = node;
-        node.ui.onSelectedChange(true);
-        this.fireEvent('selectionchange', this, this.selNodes);
-        return node;
-    },
     
     
-    unselect : function(node){
-        if(this.selMap[node.id]){
-            node.ui.onSelectedChange(false);
-            var sn = this.selNodes;
-            var index = sn.indexOf(node);
-            if(index != -1){
-                this.selNodes.splice(index, 1);
-            }
-            delete this.selMap[node.id];
-            this.fireEvent('selectionchange', this, this.selNodes);
-        }
-    },
     
+    percentageFromEdge: 0.35,
+
     
-    clearSelections : function(suppressEvent){
-        var sn = this.selNodes;
-        if(sn.length > 0){
-            for(var i = 0, len = sn.length; i < len; i++){
-                sn[i].ui.onSelectedChange(false);
+    scrollToLoadBuffer: 200,
+
+    activePrefetch: true,
+
+    chunkSize: 50,
+    snapIncrement: 25,
+
+    syncScroll: true,
+
+    initComponent: function() {
+        var me = this,
+            ds = me.store;
+
+        ds.on('guaranteedrange', me.onGuaranteedRange, me);
+        me.callParent(arguments);
+    },
+
+    onGuaranteedRange: function(range, start, end) {
+        var me = this,
+            ds = me.store,
+            rs;
+        
+        if (range.length && me.visibleStart < range[0].index) {
+            return;
+        }
+
+        ds.loadRecords(range);
+
+        if (!me.firstLoad) {
+            if (me.rendered) {
+                me.invalidate();
+            } else {
+                me.on('afterrender', me.invalidate, me, {single: true});
             }
-            this.selNodes = [];
-            this.selMap = {};
-            if(suppressEvent !== true){
-                this.fireEvent('selectionchange', this, this.selNodes);
+            me.firstLoad = true;
+        } else {
+            
+            
+            if (me.scrollEl && me.scrollEl.dom && me.scrollEl.dom.scrollHeight) {
+                me.syncTo();
             }
         }
     },
-    
-    
-    isSelected : function(node){
-        return this.selMap[node.id] ? true : false;  
+
+    syncTo: function() {
+        var me            = this,
+            pnl           = me.getPanel(),
+            store         = pnl.store,
+            scrollerElDom = this.scrollEl.dom,
+            rowOffset     = me.visibleStart - store.guaranteedStart,
+            scrollBy      = rowOffset * me.rowHeight,
+            scrollHeight  = scrollerElDom.scrollHeight,
+            clientHeight  = scrollerElDom.clientHeight,
+            scrollTop     = scrollerElDom.scrollTop,
+            useMaximum;
+            
+
+        
+        
+        if (Ext.isIE9 && Ext.isStrict) {
+            clientHeight = scrollerElDom.offsetHeight + 2;
+        }
+
+        
+        
+        useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
+        this.setViewScrollTop(scrollBy, useMaximum);
     },
-    
-    
-    getSelectedNodes : function(){
-        return this.selNodes.concat([]);
+
+    getPageData : function(){
+        var panel = this.getPanel(),
+            store = panel.store,
+            totalCount = store.getTotalCount();
+
+        return {
+            total : totalCount,
+            currentPage : store.currentPage,
+            pageCount: Math.ceil(totalCount / store.pageSize),
+            fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
+            toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
+        };
     },
 
-    onKeyDown : Ext.tree.DefaultSelectionModel.prototype.onKeyDown,
+    onElScroll: function(e, t) {
+        var me = this,
+            panel = me.getPanel(),
+            store = panel.store,
+            pageSize = store.pageSize,
+            guaranteedStart = store.guaranteedStart,
+            guaranteedEnd = store.guaranteedEnd,
+            totalCount = store.getTotalCount(),
+            numFromEdge = Math.ceil(me.percentageFromEdge * pageSize),
+            position = t.scrollTop,
+            visibleStart = Math.floor(position / me.rowHeight),
+            view = panel.down('tableview'),
+            viewEl = view.el,
+            visibleHeight = viewEl.getHeight(),
+            visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
+            visibleEnd = visibleStart + visibleAhead,
+            prevPage = Math.floor(visibleStart / pageSize),
+            nextPage = Math.floor(visibleEnd / pageSize) + 2,
+            lastPage = Math.ceil(totalCount / pageSize),
+            snap = me.snapIncrement,
+            requestStart = Math.floor(visibleStart / snap) * snap,
+            requestEnd = requestStart + pageSize - 1,
+            activePrefetch = me.activePrefetch;
+
+        me.visibleStart = visibleStart;
+        me.visibleEnd = visibleEnd;
+        
+        
+        me.syncScroll = true;
+        if (totalCount >= pageSize) {
+            
+            if (requestEnd > totalCount - 1) {
+                me.cancelLoad();
+                if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
+                    me.syncScroll = true;
+                }
+                store.guaranteeRange(totalCount - pageSize, totalCount - 1);
+            
+            } else if (visibleStart <= guaranteedStart || visibleEnd > guaranteedEnd) {
+                if (visibleStart <= guaranteedStart) {
+                    
+                    requestStart -= snap;
+                    requestEnd -= snap;
+                    
+                    if (requestStart < 0) {
+                        requestStart = 0;
+                        requestEnd = pageSize;
+                    }
+                }
+                if (store.rangeSatisfied(requestStart, requestEnd)) {
+                    me.cancelLoad();
+                    store.guaranteeRange(requestStart, requestEnd);
+                } else {
+                    store.mask();
+                    me.attemptLoad(requestStart, requestEnd);
+                }
+                
+                me.syncScroll = false;
+            } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
+                me.syncScroll = true;
+                store.prefetchPage(prevPage);
+            } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
+                me.syncScroll = true;
+                store.prefetchPage(nextPage);
+            }
+        }
 
-    selectNext : Ext.tree.DefaultSelectionModel.prototype.selectNext,
+        if (me.syncScroll) {
+            me.syncTo();
+        }
+    },
 
-    selectPrevious : Ext.tree.DefaultSelectionModel.prototype.selectPrevious
-});
-Ext.data.Tree = function(root){
-   this.nodeHash = {};
-   
-   this.root = null;
-   if(root){
-       this.setRootNode(root);
-   }
-   this.addEvents(
-       
-       "append",
-       
-       "remove",
-       
-       "move",
-       
-       "insert",
-       
-       "beforeappend",
-       
-       "beforeremove",
-       
-       "beforemove",
-       
-       "beforeinsert"
-   );
+    getSizeCalculation: function() {
+        
+        
+        var me     = this,
+            owner  = me.ownerGrid,
+            view   = owner.getView(),
+            store  = me.store,
+            dock   = me.dock,
+            elDom  = me.el.dom,
+            width  = 1,
+            height = 1;
 
-    Ext.data.Tree.superclass.constructor.call(this);
-};
+        if (!me.rowHeight) {
+            me.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
+        }
 
-Ext.extend(Ext.data.Tree, Ext.util.Observable, {
-    
-    pathSeparator: "/",
+        
+        height = store[(!store.remoteFilter && store.isFiltered()) ? 'getCount' : 'getTotalCount']() * me.rowHeight;
 
-    
-    proxyNodeEvent : function(){
-        return this.fireEvent.apply(this, arguments);
+        if (isNaN(width)) {
+            width = 1;
+        }
+        if (isNaN(height)) {
+            height = 1;
+        }
+        return {
+            width: width,
+            height: height
+        };
     },
 
-    
-    getRootNode : function(){
-        return this.root;
+    attemptLoad: function(start, end) {
+        var me = this;
+        if (!me.loadTask) {
+            me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
+        }
+        me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
     },
 
-    
-    setRootNode : function(node){
-        this.root = node;
-        node.ownerTree = this;
-        node.isRoot = true;
-        this.registerNode(node);
-        return node;
+    cancelLoad: function() {
+        if (this.loadTask) {
+            this.loadTask.cancel();
+        }
     },
 
-    
-    getNodeById : function(id){
-        return this.nodeHash[id];
+    doAttemptLoad:  function(start, end) {
+        var store = this.getPanel().store;
+        store.guaranteeRange(start, end);
     },
 
-    
-    registerNode : function(node){
-        this.nodeHash[node.id] = node;
-    },
+    setViewScrollTop: function(scrollTop, useMax) {
+        var me = this,
+            owner = me.getPanel(),
+            items = owner.query('tableview'),
+            i = 0,
+            len = items.length,
+            center,
+            centerEl,
+            calcScrollTop,
+            maxScrollTop,
+            scrollerElDom = me.el.dom;
 
-    
-    unregisterNode : function(node){
-        delete this.nodeHash[node.id];
-    },
+        owner.virtualScrollTop = scrollTop;
 
-    toString : function(){
-        return "[Tree"+(this.id?" "+this.id:"")+"]";
+        center = items[1] || items[0];
+        centerEl = center.el.dom;
+
+        maxScrollTop = ((owner.store.pageSize * me.rowHeight) - centerEl.clientHeight);
+        calcScrollTop = (scrollTop % ((owner.store.pageSize * me.rowHeight) + 1));
+        if (useMax) {
+            calcScrollTop = maxScrollTop;
+        }
+        if (calcScrollTop > maxScrollTop) {
+            
+            return;
+            
+        }
+        for (; i < len; i++) {
+            items[i].el.dom.scrollTop = calcScrollTop;
+        }
     }
 });
 
 
-Ext.data.Node = function(attributes){
-    
-    this.attributes = attributes || {};
-    this.leaf = this.attributes.leaf;
+Ext.define('Ext.panel.Table', {
+    extend: 'Ext.panel.Panel',
+
+    alias: 'widget.tablepanel',
+
+    uses: [
+        'Ext.selection.RowModel',
+        'Ext.grid.Scroller',
+        'Ext.grid.header.Container',
+        'Ext.grid.Lockable'
+    ],
+
+    extraBaseCls: Ext.baseCSSPrefix + 'grid',
+    extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
+
+    layout: 'fit',
     
-    this.id = this.attributes.id;
-    if(!this.id){
-        this.id = Ext.id(null, "xnode-");
-        this.attributes.id = this.id;
-    }
+    hasView: false,
+
     
-    this.childNodes = [];
-    if(!this.childNodes.indexOf){ 
-        this.childNodes.indexOf = function(o){
-            for(var i = 0, len = this.length; i < len; i++){
-                if(this[i] == o){
-                    return i;
-                }
-            }
-            return -1;
-        };
-    }
     
-    this.parentNode = null;
+    viewType: null,
+
     
-    this.firstChild = null;
+
     
-    this.lastChild = null;
+
     
-    this.previousSibling = null;
+    selType: 'rowmodel',
+
     
-    this.nextSibling = null;
 
-    this.addEvents({
-       
-       "append" : true,
-       
-       "remove" : true,
-       
-       "move" : true,
-       
-       "insert" : true,
-       
-       "beforeappend" : true,
-       
-       "beforeremove" : true,
-       
-       "beforemove" : true,
-       
-       "beforeinsert" : true
-   });
-    this.listeners = this.attributes.listeners;
-    Ext.data.Node.superclass.constructor.call(this);
-};
+    
 
-Ext.extend(Ext.data.Node, Ext.util.Observable, {
     
-    fireEvent : function(evtName){
-        
-        if(Ext.data.Node.superclass.fireEvent.apply(this, arguments) === false){
-            return false;
-        }
-        
-        var ot = this.getOwnerTree();
-        if(ot){
-            if(ot.proxyNodeEvent.apply(ot, arguments) === false){
-                return false;
-            }
-        }
-        return true;
-    },
 
     
-    isLeaf : function(){
-        return this.leaf === true;
-    },
 
     
-    setFirstChild : function(node){
-        this.firstChild = node;
-    },
+    scrollDelta: 40,
 
     
-    setLastChild : function(node){
-        this.lastChild = node;
-    },
+    scroll: true,
 
+    
 
     
-    isLast : function(){
-       return (!this.parentNode ? true : this.parentNode.lastChild == this);
-    },
 
     
-    isFirst : function(){
-       return (!this.parentNode ? true : this.parentNode.firstChild == this);
-    },
 
     
-    hasChildNodes : function(){
-        return !this.isLeaf() && this.childNodes.length > 0;
-    },
 
     
-    isExpandable : function(){
-        return this.attributes.expandable || this.hasChildNodes();
-    },
 
+     deferRowRender: true,
+     
     
-    appendChild : function(node){
-        var multi = false;
-        if(Ext.isArray(node)){
-            multi = node;
-        }else if(arguments.length > 1){
-            multi = arguments;
-        }
-        
-        if(multi){
-            for(var i = 0, len = multi.length; i < len; i++) {
-                this.appendChild(multi[i]);
-            }
-        }else{
-            if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
-                return false;
-            }
-            var index = this.childNodes.length;
-            var oldParent = node.parentNode;
-            
-            if(oldParent){
-                if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
-                    return false;
-                }
-                oldParent.removeChild(node);
-            }
-            index = this.childNodes.length;
-            if(index === 0){
-                this.setFirstChild(node);
-            }
-            this.childNodes.push(node);
-            node.parentNode = this;
-            var ps = this.childNodes[index-1];
-            if(ps){
-                node.previousSibling = ps;
-                ps.nextSibling = node;
-            }else{
-                node.previousSibling = null;
-            }
-            node.nextSibling = null;
-            this.setLastChild(node);
-            node.setOwnerTree(this.getOwnerTree());
-            this.fireEvent("append", this.ownerTree, this, node, index);
-            if(oldParent){
-                node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
-            }
-            return node;
-        }
-    },
+    sortableColumns: true,
 
     
-    removeChild : function(node, destroy){
-        var index = this.childNodes.indexOf(node);
-        if(index == -1){
-            return false;
-        }
-        if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
-            return false;
-        }
+    enableLocking: false,
 
-        
-        this.childNodes.splice(index, 1);
+    verticalScrollDock: 'right',
+    verticalScrollerType: 'gridscroller',
 
-        
-        if(node.previousSibling){
-            node.previousSibling.nextSibling = node.nextSibling;
-        }
-        if(node.nextSibling){
-            node.nextSibling.previousSibling = node.previousSibling;
-        }
+    horizontalScrollerPresentCls: Ext.baseCSSPrefix + 'horizontal-scroller-present',
+    verticalScrollerPresentCls: Ext.baseCSSPrefix + 'vertical-scroller-present',
 
-        
-        if(this.firstChild == node){
-            this.setFirstChild(node.nextSibling);
-        }
-        if(this.lastChild == node){
-            this.setLastChild(node.previousSibling);
-        }
+    
+    
+    scrollerOwner: true,
 
-        this.fireEvent("remove", this.ownerTree, this, node);
-        if(destroy){
-            node.destroy(true);
-        }else{
-            node.clear();
-        }
-        return node;
-    },
+    invalidateScrollerOnRefresh: true,
 
     
-    clear : function(destroy){
-        
-        this.setOwnerTree(null, destroy);
-        this.parentNode = this.previousSibling = this.nextSibling = null;
-        if(destroy){
-            this.firstChild = this.lastChild = null;
-        }
-    },
+    enableColumnMove: true,
 
     
-    destroy : function( silent){
-        
-        if(silent === true){
-            this.purgeListeners();
-            this.clear(true);
-            Ext.each(this.childNodes, function(n){
-                n.destroy(true);
-            });
-            this.childNodes = null;
-        }else{
-            this.remove(true);
-        }
-    },
+    enableColumnResize: true,
 
     
-    insertBefore : function(node, refNode){
-        if(!refNode){ 
-            return this.appendChild(node);
-        }
-        
-        if(node == refNode){
-            return false;
-        }
+    enableColumnHide: true,
 
-        if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
-            return false;
+    initComponent: function() {
+
+        var me          = this,
+            scroll      = me.scroll,
+            vertical    = false,
+            horizontal  = false,
+            headerCtCfg = me.columns || me.colModel,
+            i           = 0,
+            view,
+            border = me.border;
+
+        if (me.hideHeaders) {
+            border = false;
         }
-        var index = this.childNodes.indexOf(refNode);
-        var oldParent = node.parentNode;
-        var refIndex = index;
 
         
-        if(oldParent == this && this.childNodes.indexOf(node) < index){
-            refIndex--;
-        }
+        me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
 
         
-        if(oldParent){
-            if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
-                return false;
+        
+        if (headerCtCfg instanceof Ext.grid.header.Container) {
+            me.headerCt = headerCtCfg;
+            me.headerCt.border = border;
+            me.columns = me.headerCt.items.items;
+        } else {
+            if (Ext.isArray(headerCtCfg)) {
+                headerCtCfg = {
+                    items: headerCtCfg,
+                    border: border
+                };
             }
-            oldParent.removeChild(node);
-        }
-        if(refIndex === 0){
-            this.setFirstChild(node);
-        }
-        this.childNodes.splice(refIndex, 0, node);
-        node.parentNode = this;
-        var ps = this.childNodes[refIndex-1];
-        if(ps){
-            node.previousSibling = ps;
-            ps.nextSibling = node;
-        }else{
-            node.previousSibling = null;
-        }
-        node.nextSibling = refNode;
-        refNode.previousSibling = node;
-        node.setOwnerTree(this.getOwnerTree());
-        this.fireEvent("insert", this.ownerTree, this, node, refNode);
-        if(oldParent){
-            node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
-        }
-        return node;
-    },
-
-    
-    remove : function(destroy){
-        if (this.parentNode) {
-            this.parentNode.removeChild(this, destroy);
-        }
-        return this;
-    },
+            Ext.apply(headerCtCfg, {
+                forceFit: me.forceFit,
+                sortable: me.sortableColumns,
+                enableColumnMove: me.enableColumnMove,
+                enableColumnResize: me.enableColumnResize,
+                enableColumnHide: me.enableColumnHide,
+                border:  border
+            });
+            me.columns = headerCtCfg.items;
 
-    
-    removeAll : function(destroy){
-        var cn = this.childNodes,
-            n;
-        while((n = cn[0])){
-            this.removeChild(n, destroy);
+             
+             
+             if (me.enableLocking || Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
+                 me.self.mixin('lockable', Ext.grid.Lockable);
+                 me.injectLockable();
+             }
         }
-        return this;
-    },
 
-    
-    item : function(index){
-        return this.childNodes[index];
-    },
+        me.addEvents(
+            
+            'reconfigure',
+            
+            'viewready',
+            
+            'scrollerhide',
+            
+            'scrollershow'
+        );
 
-    
-    replaceChild : function(newChild, oldChild){
-        var s = oldChild ? oldChild.nextSibling : null;
-        this.removeChild(oldChild);
-        this.insertBefore(newChild, s);
-        return oldChild;
-    },
+        me.bodyCls = me.bodyCls || '';
+        me.bodyCls += (' ' + me.extraBodyCls);
+        
+        me.cls = me.cls || '';
+        me.cls += (' ' + me.extraBaseCls);
 
-    
-    indexOf : function(child){
-        return this.childNodes.indexOf(child);
-    },
+        
+        delete me.autoScroll;
 
-    
-    getOwnerTree : function(){
         
-        if(!this.ownerTree){
-            var p = this;
-            while(p){
-                if(p.ownerTree){
-                    this.ownerTree = p.ownerTree;
-                    break;
-                }
-                p = p.parentNode;
+        
+        if (!me.hasView) {
+
+            
+            
+            if (!me.headerCt) {
+                me.headerCt = Ext.create('Ext.grid.header.Container', headerCtCfg);
             }
-        }
-        return this.ownerTree;
-    },
 
-    
-    getDepth : function(){
-        var depth = 0;
-        var p = this;
-        while(p.parentNode){
-            ++depth;
-            p = p.parentNode;
-        }
-        return depth;
-    },
+            
+            me.columns = me.headerCt.items.items;
 
-    
-    setOwnerTree : function(tree, destroy){
-        
-        if(tree != this.ownerTree){
-            if(this.ownerTree){
-                this.ownerTree.unregisterNode(this);
+            if (me.hideHeaders) {
+                me.headerCt.height = 0;
+                me.headerCt.border = false;
+                me.headerCt.addCls(Ext.baseCSSPrefix + 'grid-header-ct-hidden');
+                me.addCls(Ext.baseCSSPrefix + 'grid-header-hidden');
+                
+                
+                if (Ext.isIEQuirks) {
+                    me.headerCt.style = {
+                        display: 'none'
+                    };
+                }
             }
-            this.ownerTree = tree;
+
             
-            if(destroy !== true){
-                Ext.each(this.childNodes, function(n){
-                    n.setOwnerTree(tree);
-                });
+            if (scroll === true || scroll === 'both') {
+                vertical = horizontal = true;
+            } else if (scroll === 'horizontal') {
+                horizontal = true;
+            } else if (scroll === 'vertical') {
+                vertical = true;
+            
+            } else {
+                me.headerCt.availableSpaceOffset = 0;
             }
-            if(tree){
-                tree.registerNode(this);
+
+            if (vertical) {
+                me.verticalScroller = Ext.ComponentManager.create(me.initVerticalScroller());
+                me.mon(me.verticalScroller, {
+                    bodyscroll: me.onVerticalScroll,
+                    scope: me
+                });
             }
-        }
-    },
 
-    
-    setId: function(id){
-        if(id !== this.id){
-            var t = this.ownerTree;
-            if(t){
-                t.unregisterNode(this);
+            if (horizontal) {
+                me.horizontalScroller = Ext.ComponentManager.create(me.initHorizontalScroller());
+                me.mon(me.horizontalScroller, {
+                    bodyscroll: me.onHorizontalScroll,
+                    scope: me
+                });
             }
-            this.id = this.attributes.id = id;
-            if(t){
-                t.registerNode(this);
+
+            me.headerCt.on('resize', me.onHeaderResize, me);
+            me.relayHeaderCtEvents(me.headerCt);
+            me.features = me.features || [];
+            if (!Ext.isArray(me.features)) {
+                me.features = [me.features];
             }
-            this.onIdChange(id);
-        }
-    },
+            me.dockedItems = me.dockedItems || [];
+            me.dockedItems.unshift(me.headerCt);
+            me.viewConfig = me.viewConfig || {};
+            me.viewConfig.invalidateScrollerOnRefresh = me.invalidateScrollerOnRefresh;
 
-    
-    onIdChange: Ext.emptyFn,
+            
+            
+            view = me.getView();
 
-    
-    getPath : function(attr){
-        attr = attr || "id";
-        var p = this.parentNode;
-        var b = [this.attributes[attr]];
-        while(p){
-            b.unshift(p.attributes[attr]);
-            p = p.parentNode;
+            view.on({
+                afterrender: function () {
+                    
+                    view.el.scroll = Ext.Function.bind(me.elScroll, me);
+                    
+                    
+                    me.mon(view.el, {
+                        mousewheel: me.onMouseWheel,
+                        scope: me
+                    });
+                },
+                single: true
+            });
+            me.items = [view];
+            me.hasView = true;
+
+            me.mon(view.store, {
+                load: me.onStoreLoad,
+                scope: me
+            });
+            me.mon(view, {
+                viewReady: me.onViewReady,
+                resize: me.onViewResize,
+                refresh: {
+                    fn: me.onViewRefresh,
+                    scope: me,
+                    buffer: 50
+                },
+                scope: me
+            });
+            this.relayEvents(view, [
+                
+                'beforeitemmousedown',
+                
+                'beforeitemmouseup',
+                
+                'beforeitemmouseenter',
+                
+                'beforeitemmouseleave',
+                
+                'beforeitemclick',
+                
+                'beforeitemdblclick',
+                
+                'beforeitemcontextmenu',
+                
+                'itemmousedown',
+                
+                'itemmouseup',
+                
+                'itemmouseenter',
+                
+                'itemmouseleave',
+                
+                'itemclick',
+                
+                'itemdblclick',
+                
+                'itemcontextmenu',
+                
+                'beforecontainermousedown',
+                
+                'beforecontainermouseup',
+                
+                'beforecontainermouseover',
+                
+                'beforecontainermouseout',
+                
+                'beforecontainerclick',
+                
+                'beforecontainerdblclick',
+                
+                'beforecontainercontextmenu',
+                
+                'containermouseup',
+                
+                'containermouseover',
+                
+                'containermouseout',
+                
+                'containerclick',
+                
+                'containerdblclick',
+                
+                'containercontextmenu',
+                
+                'selectionchange',
+                
+                'beforeselect',
+                
+                'select',
+                
+                'beforedeselect',
+                
+                'deselect'
+            ]);
         }
-        var sep = this.getOwnerTree().pathSeparator;
-        return sep + b.join(sep);
-    },
 
+        me.callParent(arguments);
+    },
     
-    bubble : function(fn, scope, args){
-        var p = this;
-        while(p){
-            if(fn.apply(scope || p, args || [p]) === false){
-                break;
-            }
-            p = p.parentNode;
+    onRender: function(){
+        var vScroll = this.verticalScroller,
+            hScroll = this.horizontalScroller;
+
+        if (vScroll) {
+            vScroll.ensureDimension();
+        }
+        if (hScroll) {
+            hScroll.ensureDimension();
         }
+        this.callParent(arguments);    
     },
 
     
-    cascade : function(fn, scope, args){
-        if(fn.apply(scope || this, args || [this]) !== false){
-            var cs = this.childNodes;
-            for(var i = 0, len = cs.length; i < len; i++) {
-                cs[i].cascade(fn, scope, args);
+    initStateEvents: function(){
+        var events = this.stateEvents;
+        
+        Ext.each(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange'], function(event){
+            if (Ext.Array.indexOf(events, event)) {
+                events.push(event);
             }
-        }
+        });
+        this.callParent();
     },
 
     
-    eachChild : function(fn, scope, args){
-        var cs = this.childNodes;
-        for(var i = 0, len = cs.length; i < len; i++) {
-            if(fn.apply(scope || this, args || [cs[i]]) === false){
-                break;
-            }
-        }
+    initHorizontalScroller: function () {
+        var me = this,
+            ret = {
+                xtype: 'gridscroller',
+                dock: 'bottom',
+                section: me,
+                store: me.store
+            };
+
+        return ret;
     },
 
     
-    findChild : function(attribute, value, deep){
-        return this.findChildBy(function(){
-            return this.attributes[attribute] == value;
-        }, null, deep);
+    initVerticalScroller: function () {
+        var me = this,
+            ret = me.verticalScroller || {};
+
+        Ext.applyIf(ret, {
+            xtype: me.verticalScrollerType,
+            dock: me.verticalScrollDock,
+            store: me.store
+        });
+
+        return ret;
     },
 
-    
-    findChildBy : function(fn, scope, deep){
-        var cs = this.childNodes,
-            len = cs.length,
-            i = 0,
-            n,
-            res;
-        for(; i < len; i++){
-            n = cs[i];
-            if(fn.call(scope || n, n) === true){
-                return n;
-            }else if (deep){
-                res = n.findChildBy(fn, scope, deep);
-                if(res != null){
-                    return res;
-                }
-            }
+    relayHeaderCtEvents: function (headerCt) {
+        this.relayEvents(headerCt, [
             
-        }
-        return null;
+            'columnresize',
+            
+            'columnmove',
+            
+            'columnhide',
+            
+            'columnshow',
+            
+            'sortchange'
+        ]);
     },
 
-    
-    sort : function(fn, scope){
-        var cs = this.childNodes;
-        var len = cs.length;
-        if(len > 0){
-            var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
-            cs.sort(sortFn);
-            for(var i = 0; i < len; i++){
-                var n = cs[i];
-                n.previousSibling = cs[i-1];
-                n.nextSibling = cs[i+1];
-                if(i === 0){
-                    this.setFirstChild(n);
-                }
-                if(i == len-1){
-                    this.setLastChild(n);
-                }
-            }
-        }
-    },
+    getState: function(){
+        var me = this,
+            state = me.callParent(),
+            sorter = me.store.sorters.first();
 
-    
-    contains : function(node){
-        return node.isAncestor(this);
-    },
+        state.columns = (me.headerCt || me).getColumnsState();
 
-    
-    isAncestor : function(node){
-        var p = this.parentNode;
-        while(p){
-            if(p == node){
-                return true;
-            }
-            p = p.parentNode;
+        if (sorter) {
+            state.sort = {
+                property: sorter.property,
+                direction: sorter.direction
+            };
         }
-        return false;
+
+        return state;
     },
 
-    toString : function(){
-        return "[Node"+(this.id?" "+this.id:"")+"]";
-    }
-});
-Ext.tree.TreeNode = function(attributes){
-    attributes = attributes || {};
-    if(Ext.isString(attributes)){
-        attributes = {text: attributes};
-    }
-    this.childrenRendered = false;
-    this.rendered = false;
-    Ext.tree.TreeNode.superclass.constructor.call(this, attributes);
-    this.expanded = attributes.expanded === true;
-    this.isTarget = attributes.isTarget !== false;
-    this.draggable = attributes.draggable !== false && attributes.allowDrag !== false;
-    this.allowChildren = attributes.allowChildren !== false && attributes.allowDrop !== false;
+    applyState: function(state) {
+        var me = this,
+            sorter = state.sort,
+            store = me.store,
+            columns = state.columns;
 
-    
-    this.text = attributes.text;
-    
-    this.disabled = attributes.disabled === true;
-    
-    this.hidden = attributes.hidden === true;
+        delete state.columns;
 
-    this.addEvents(
-        
-        'textchange',
-        
-        'beforeexpand',
-        
-        'beforecollapse',
         
-        'expand',
         
-        'disabledchange',
-        
-        'collapse',
-        
-        'beforeclick',
-        
-        'click',
-        
-        'checkchange',
-        
-        'beforedblclick',
-        
-        'dblclick',
-        
-        'contextmenu',
-        
-        'beforechildrenrendered'
-    );
-
-    var uiClass = this.attributes.uiProvider || this.defaultUI || Ext.tree.TreeNodeUI;
-
-    
-    this.ui = new uiClass(this);
-};
-Ext.extend(Ext.tree.TreeNode, Ext.data.Node, {
-    preventHScroll : true,
-    
-    isExpanded : function(){
-        return this.expanded;
-    },
+        me.callParent(arguments);
 
+        if (columns) {
+            (me.headerCt || me).applyColumnsState(columns);
+        }
 
-    getUI : function(){
-        return this.ui;
+        if (sorter) {
+            if (store.remoteSort) {
+                store.sorters.add(Ext.create('Ext.util.Sorter', {
+                    property: sorter.property,
+                    direction: sorter.direction
+                }));
+            }
+            else {
+                store.sort(sorter.property, sorter.direction);
+            }
+        }
     },
 
-    getLoader : function(){
-        var owner;
-        return this.loader || ((owner = this.getOwnerTree()) && owner.loader ? owner.loader : (this.loader = new Ext.tree.TreeLoader()));
+    
+    getStore: function(){
+        return this.store;
     },
 
     
-    setFirstChild : function(node){
-        var of = this.firstChild;
-        Ext.tree.TreeNode.superclass.setFirstChild.call(this, node);
-        if(this.childrenRendered && of && node != of){
-            of.renderIndent(true, true);
-        }
-        if(this.rendered){
-            this.renderIndent(true, true);
+    getView: function() {
+        var me = this,
+            sm;
+
+        if (!me.view) {
+            sm = me.getSelectionModel();
+            me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
+                deferInitialRefresh: me.deferRowRender,
+                xtype: me.viewType,
+                store: me.store,
+                headerCt: me.headerCt,
+                selModel: sm,
+                features: me.features,
+                panel: me
+            }));
+            me.mon(me.view, {
+                uievent: me.processEvent,
+                scope: me
+            });
+            sm.view = me.view;
+            me.headerCt.view = me.view;
+            me.relayEvents(me.view, ['cellclick', 'celldblclick']);
         }
+        return me.view;
     },
 
     
-    setLastChild : function(node){
-        var ol = this.lastChild;
-        Ext.tree.TreeNode.superclass.setLastChild.call(this, node);
-        if(this.childrenRendered && ol && node != ol){
-            ol.renderIndent(true, true);
-        }
-        if(this.rendered){
-            this.renderIndent(true, true);
-        }
-    },
+    setAutoScroll: Ext.emptyFn,
 
     
     
-    appendChild : function(n){
-        if(!n.render && !Ext.isArray(n)){
-            n = this.getLoader().createNode(n);
-        }
-        var node = Ext.tree.TreeNode.superclass.appendChild.call(this, n);
-        if(node && this.childrenRendered){
-            node.render();
-        }
-        this.ui.updateExpandIcon();
-        return node;
-    },
-
     
-    removeChild : function(node, destroy){
-        this.ownerTree.getSelectionModel().unselect(node);
-        Ext.tree.TreeNode.superclass.removeChild.apply(this, arguments);
+    elScroll: function(direction, distance, animate) {
+        var me = this,
+            scroller;
+
+        if (direction === "up" || direction === "left") {
+            distance = -distance;
+        }
         
-        if(!destroy){
+        if (direction === "down" || direction === "up") {
+            scroller = me.getVerticalScroller();
             
-            if(node.ui.rendered){
-                node.ui.remove();
-            }
-            if(this.childNodes.length < 1){
-                this.collapse(false, false);
-            }else{
-                this.ui.updateExpandIcon();
+            
+            if (scroller) {
+                scroller.scrollByDeltaY(distance);
             }
-            if(!this.firstChild && !this.isHiddenRoot()){
-                this.childrenRendered = false;
+        } else {
+            scroller = me.getHorizontalScroller();
+            
+            
+            if (scroller) {
+                scroller.scrollByDeltaX(distance);
             }
         }
-        return node;
     },
 
     
-    insertBefore : function(node, refNode){
-        if(!node.render){
-            node = this.getLoader().createNode(node);
-        }
-        var newNode = Ext.tree.TreeNode.superclass.insertBefore.call(this, node, refNode);
-        if(newNode && refNode && this.childrenRendered){
-            node.render();
-        }
-        this.ui.updateExpandIcon();
-        return newNode;
-    },
+    processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
+        var me = this,
+            header;
 
-    
-    setText : function(text){
-        var oldText = this.text;
-        this.text = this.attributes.text = text;
-        if(this.rendered){ 
-            this.ui.onTextChange(this, text, oldText);
+        if (cellIndex !== -1) {
+            header = me.headerCt.getGridColumns()[cellIndex];
+            return header.processEvent.apply(header, arguments);
         }
-        this.fireEvent('textchange', this, text, oldText);
     },
 
     
-    select : function(){
-        var t = this.getOwnerTree();
-        if(t){
-            t.getSelectionModel().select(this);
+    determineScrollbars: function() {
+        
+        if (this.determineScrollbarsRunning) {
+            return;
         }
-    },
+        this.determineScrollbarsRunning = true;
+        var me = this,
+            view = me.view,
+            box,
+            tableEl,
+            scrollWidth,
+            clientWidth,
+            scrollHeight,
+            clientHeight,
+            verticalScroller = me.verticalScroller,
+            horizontalScroller = me.horizontalScroller,
+            curScrollbars = (verticalScroller   && verticalScroller.ownerCt === me ? 1 : 0) |
+                            (horizontalScroller && horizontalScroller.ownerCt === me ? 2 : 0),
+            reqScrollbars = 0; 
 
-    
-    unselect : function(silent){
-        var t = this.getOwnerTree();
-        if(t){
-            t.getSelectionModel().unselect(this, silent);
-        }
-    },
+        
+        if (!me.collapsed && view && view.viewReady) {
 
-    
-    isSelected : function(){
-        var t = this.getOwnerTree();
-        return t ? t.getSelectionModel().isSelected(this) : false;
-    },
+            
+            
+            box = view.el.getSize();
 
-    
-    expand : function(deep, anim, callback, scope){
-        if(!this.expanded){
-            if(this.fireEvent('beforeexpand', this, deep, anim) === false){
-                return;
+            clientWidth  = box.width  + ((curScrollbars & 1) ? verticalScroller.width : 0);
+            clientHeight = box.height + ((curScrollbars & 2) ? horizontalScroller.height : 0);
+
+            
+            
+
+            scrollWidth = (me.headerCt.query('[flex]').length && !me.headerCt.layout.tooNarrow) ? 0 : me.headerCt.getFullWidth();
+
+            
+            if (verticalScroller && verticalScroller.el) {
+                scrollHeight = verticalScroller.getSizeCalculation().height;
+            } else {
+                tableEl = view.el.child('table', true);
+                scrollHeight = tableEl ? tableEl.offsetHeight : 0;
             }
-            if(!this.childrenRendered){
-                this.renderChildren();
+
+            
+            
+            if (scrollHeight > clientHeight) {
+                reqScrollbars = 1;
+
+                
+                if (horizontalScroller && ((clientWidth - scrollWidth) < verticalScroller.width)) {
+                    reqScrollbars = 3;
+                }
             }
-            this.expanded = true;
-            if(!this.isHiddenRoot() && (this.getOwnerTree().animate && anim !== false) || anim){
-                this.ui.animExpand(function(){
-                    this.fireEvent('expand', this);
-                    this.runCallback(callback, scope || this, [this]);
-                    if(deep === true){
-                        this.expandChildNodes(true);
+
+            
+            else {
+                
+                
+                if (scrollWidth > clientWidth) {
+                    reqScrollbars = 2;
+
+                    
+                    if (verticalScroller && ((clientHeight - scrollHeight) < horizontalScroller.height)) {
+                        reqScrollbars = 3;
                     }
-                }.createDelegate(this));
-                return;
-            }else{
-                this.ui.expand();
-                this.fireEvent('expand', this);
-                this.runCallback(callback, scope || this, [this]);
+                }
             }
-        }else{
-           this.runCallback(callback, scope || this, [this]);
-        }
-        if(deep === true){
-            this.expandChildNodes(true);
-        }
-    },
 
-    runCallback : function(cb, scope, args){
-        if(Ext.isFunction(cb)){
-            cb.apply(scope, args);
-        }
-    },
+            
+            if (reqScrollbars !== curScrollbars) {
 
-    isHiddenRoot : function(){
-        return this.isRoot && !this.getOwnerTree().rootVisible;
-    },
+                
+                me.suspendLayout = true;
+                if (reqScrollbars & 1) {
+                    me.showVerticalScroller();
+                } else {
+                    me.hideVerticalScroller();
+                }
+                if (reqScrollbars & 2) {
+                    me.showHorizontalScroller();
+                } else {
+                    me.hideHorizontalScroller();
+                }
+                me.suspendLayout = false;
 
-    
-    collapse : function(deep, anim, callback, scope){
-        if(this.expanded && !this.isHiddenRoot()){
-            if(this.fireEvent('beforecollapse', this, deep, anim) === false){
-                return;
-            }
-            this.expanded = false;
-            if((this.getOwnerTree().animate && anim !== false) || anim){
-                this.ui.animCollapse(function(){
-                    this.fireEvent('collapse', this);
-                    this.runCallback(callback, scope || this, [this]);
-                    if(deep === true){
-                        this.collapseChildNodes(true);
-                    }
-                }.createDelegate(this));
-                return;
-            }else{
-                this.ui.collapse();
-                this.fireEvent('collapse', this);
-                this.runCallback(callback, scope || this, [this]);
-            }
-        }else if(!this.expanded){
-            this.runCallback(callback, scope || this, [this]);
-        }
-        if(deep === true){
-            var cs = this.childNodes;
-            for(var i = 0, len = cs.length; i < len; i++) {
-               cs[i].collapse(true, false);
+                
+                me.doComponentLayout();
+                
+                me.getLayout().layout();
             }
         }
+        delete me.determineScrollbarsRunning;
     },
 
-    
-    delayedExpand : function(delay){
-        if(!this.expandProcId){
-            this.expandProcId = this.expand.defer(delay, this);
-        }
+    onViewResize: function() {
+        this.determineScrollbars();
     },
 
-    
-    cancelExpand : function(){
-        if(this.expandProcId){
-            clearTimeout(this.expandProcId);
-        }
-        this.expandProcId = false;
+    afterComponentLayout: function() {
+        this.callParent(arguments);
+        this.determineScrollbars();
+        this.invalidateScroller();
     },
 
-    
-    toggle : function(){
-        if(this.expanded){
-            this.collapse();
-        }else{
-            this.expand();
+    onHeaderResize: function() {
+        if (!this.componentLayout.layoutBusy && this.view && this.view.rendered) {
+            this.determineScrollbars();
+            this.invalidateScroller();
         }
     },
 
-    
-    ensureVisible : function(callback, scope){
-        var tree = this.getOwnerTree();
-        tree.expandPath(this.parentNode ? this.parentNode.getPath() : this.getPath(), false, function(){
-            var node = tree.getNodeById(this.id);  
-            tree.getTreeEl().scrollChildIntoView(node.ui.anchor);
-            this.runCallback(callback, scope || this, [this]);
-        }.createDelegate(this));
-    },
-
-    
-    expandChildNodes : function(deep){
-        var cs = this.childNodes;
-        for(var i = 0, len = cs.length; i < len; i++) {
-               cs[i].expand(deep);
+    afterCollapse: function() {
+        var me = this;
+        if (me.verticalScroller) {
+            me.verticalScroller.saveScrollPos();
         }
-    },
-
-    
-    collapseChildNodes : function(deep){
-        var cs = this.childNodes;
-        for(var i = 0, len = cs.length; i < len; i++) {
-               cs[i].collapse(deep);
+        if (me.horizontalScroller) {
+            me.horizontalScroller.saveScrollPos();
         }
+        me.callParent(arguments);
     },
 
-    
-    disable : function(){
-        this.disabled = true;
-        this.unselect();
-        if(this.rendered && this.ui.onDisableChange){ 
-            this.ui.onDisableChange(this, true);
+    afterExpand: function() {
+        var me = this;
+        me.callParent(arguments);
+        if (me.verticalScroller) {
+            me.verticalScroller.restoreScrollPos();
+        }
+        if (me.horizontalScroller) {
+            me.horizontalScroller.restoreScrollPos();
         }
-        this.fireEvent('disabledchange', this, true);
     },
 
     
-    enable : function(){
-        this.disabled = false;
-        if(this.rendered && this.ui.onDisableChange){ 
-            this.ui.onDisableChange(this, false);
+    hideHorizontalScroller: function() {
+        var me = this;
+
+        if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
+            me.verticalScroller.setReservedSpace(0);
+            me.removeDocked(me.horizontalScroller, false);
+            me.removeCls(me.horizontalScrollerPresentCls);
+            me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
         }
-        this.fireEvent('disabledchange', this, false);
+
     },
 
     
-    renderChildren : function(suppressEvent){
-        if(suppressEvent !== false){
-            this.fireEvent('beforechildrenrendered', this);
+    showHorizontalScroller: function() {
+        var me = this;
+
+        if (me.verticalScroller) {
+            me.verticalScroller.setReservedSpace(Ext.getScrollbarSize().height - 1);
         }
-        var cs = this.childNodes;
-        for(var i = 0, len = cs.length; i < len; i++){
-            cs[i].render(true);
+        if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
+            me.addDocked(me.horizontalScroller);
+            me.addCls(me.horizontalScrollerPresentCls);
+            me.fireEvent('scrollershow', me.horizontalScroller, 'horizontal');
         }
-        this.childrenRendered = true;
     },
 
     
-    sort : function(fn, scope){
-        Ext.tree.TreeNode.superclass.sort.apply(this, arguments);
-        if(this.childrenRendered){
-            var cs = this.childNodes;
-            for(var i = 0, len = cs.length; i < len; i++){
-                cs[i].render(true);
-            }
-        }
-    },
+    hideVerticalScroller: function() {
+        var me = this;
 
-    
-    render : function(bulkRender){
-        this.ui.render(bulkRender);
-        if(!this.rendered){
-            
-            this.getOwnerTree().registerNode(this);
-            this.rendered = true;
-            if(this.expanded){
-                this.expanded = false;
-                this.expand(false, false);
-            }
+        me.setHeaderReserveOffset(false);
+        if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
+            me.removeDocked(me.verticalScroller, false);
+            me.removeCls(me.verticalScrollerPresentCls);
+            me.fireEvent('scrollerhide', me.verticalScroller, 'vertical');
         }
     },
 
     
-    renderIndent : function(deep, refresh){
-        if(refresh){
-            this.ui.childIndent = null;
-        }
-        this.ui.renderIndent();
-        if(deep === true && this.childrenRendered){
-            var cs = this.childNodes;
-            for(var i = 0, len = cs.length; i < len; i++){
-                cs[i].renderIndent(true, refresh);
-            }
-        }
-    },
-
-    beginUpdate : function(){
-        this.childrenRendered = false;
-    },
+    showVerticalScroller: function() {
+        var me = this;
 
-    endUpdate : function(){
-        if(this.expanded && this.rendered){
-            this.renderChildren();
+        me.setHeaderReserveOffset(true);
+        if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
+            me.addDocked(me.verticalScroller);
+            me.addCls(me.verticalScrollerPresentCls);
+            me.fireEvent('scrollershow', me.verticalScroller, 'vertical');
         }
     },
 
-    
-    destroy : function(silent){
-        if(silent === true){
-            this.unselect(true);
+    setHeaderReserveOffset: function (reserveOffset) {
+        var headerCt = this.headerCt,
+            layout = headerCt.layout;
+
+        
+        if (layout && layout.reserveOffset !== reserveOffset) {
+            layout.reserveOffset = reserveOffset;
+            if (!this.suspendLayout) {
+                headerCt.doLayout();
+            }
         }
-        Ext.tree.TreeNode.superclass.destroy.call(this, silent);
-        Ext.destroy(this.ui, this.loader);
-        this.ui = this.loader = null;
     },
 
     
-    onIdChange : function(id){
-        this.ui.onIdChange(id);
-    }
-});
+    invalidateScroller: function() {
+        var me = this,
+            vScroll = me.verticalScroller,
+            hScroll = me.horizontalScroller;
 
-Ext.tree.TreePanel.nodeTypes.node = Ext.tree.TreeNode;
- Ext.tree.AsyncTreeNode = function(config){
-    this.loaded = config && config.loaded === true;
-    this.loading = false;
-    Ext.tree.AsyncTreeNode.superclass.constructor.apply(this, arguments);
-    
-    this.addEvents('beforeload', 'load');
-    
-    
-};
-Ext.extend(Ext.tree.AsyncTreeNode, Ext.tree.TreeNode, {
-    expand : function(deep, anim, callback, scope){
-        if(this.loading){ 
-            var timer;
-            var f = function(){
-                if(!this.loading){ 
-                    clearInterval(timer);
-                    this.expand(deep, anim, callback, scope);
-                }
-            }.createDelegate(this);
-            timer = setInterval(f, 200);
-            return;
+        if (vScroll) {
+            vScroll.invalidate();
         }
-        if(!this.loaded){
-            if(this.fireEvent("beforeload", this) === false){
-                return;
-            }
-            this.loading = true;
-            this.ui.beforeLoad(this);
-            var loader = this.loader || this.attributes.loader || this.getOwnerTree().getLoader();
-            if(loader){
-                loader.load(this, this.loadComplete.createDelegate(this, [deep, anim, callback, scope]), this);
-                return;
-            }
+        if (hScroll) {
+            hScroll.invalidate();
         }
-        Ext.tree.AsyncTreeNode.superclass.expand.call(this, deep, anim, callback, scope);
-    },
-    
-    
-    isLoading : function(){
-        return this.loading;  
-    },
-    
-    loadComplete : function(deep, anim, callback, scope){
-        this.loading = false;
-        this.loaded = true;
-        this.ui.afterLoad(this);
-        this.fireEvent("load", this);
-        this.expand(deep, anim, callback, scope);
-    },
-    
-    
-    isLoaded : function(){
-        return this.loaded;
     },
+
     
-    hasChildNodes : function(){
-        if(!this.isLeaf() && !this.loaded){
-            return true;
-        }else{
-            return Ext.tree.AsyncTreeNode.superclass.hasChildNodes.call(this);
-        }
+    onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
+        this.view.refresh();
     },
 
     
-    reload : function(callback, scope){
-        this.collapse(false, false);
-        while(this.firstChild){
-            this.removeChild(this.firstChild).destroy();
-        }
-        this.childrenRendered = false;
-        this.loaded = false;
-        if(this.isHiddenRoot()){
-            this.expanded = false;
-        }
-        this.expand(false, false, callback, scope);
-    }
-});
-
-Ext.tree.TreePanel.nodeTypes.async = Ext.tree.AsyncTreeNode;
-Ext.tree.TreeNodeUI = function(node){
-    this.node = node;
-    this.rendered = false;
-    this.animating = false;
-    this.wasLeaf = true;
-    this.ecc = 'x-tree-ec-icon x-tree-elbow';
-    this.emptyIcon = Ext.BLANK_IMAGE_URL;
-};
+    onHeaderHide: function(headerCt, header) {
+        this.invalidateScroller();
+    },
 
-Ext.tree.TreeNodeUI.prototype = {
-    
-    removeChild : function(node){
-        if(this.rendered){
-            this.ctNode.removeChild(node.ui.getEl());
-        }
+    onHeaderShow: function(headerCt, header) {
+        this.invalidateScroller();
     },
 
-    
-    beforeLoad : function(){
-         this.addClass("x-tree-node-loading");
+    getVerticalScroller: function() {
+        return this.getScrollerOwner().down('gridscroller[dock=' + this.verticalScrollDock + ']');
     },
 
-    
-    afterLoad : function(){
-         this.removeClass("x-tree-node-loading");
+    getHorizontalScroller: function() {
+        return this.getScrollerOwner().down('gridscroller[dock=bottom]');
     },
 
-    
-    onTextChange : function(node, text, oldText){
-        if(this.rendered){
-            this.textNode.innerHTML = text;
+    onMouseWheel: function(e) {
+        var me = this,
+            vertScroller = me.getVerticalScroller(),
+            horizScroller = me.getHorizontalScroller(),
+            scrollDelta = -me.scrollDelta,
+            deltas = e.getWheelDeltas(),
+            deltaX = scrollDelta * deltas.x,
+            deltaY = scrollDelta * deltas.y,
+            vertScrollerEl, horizScrollerEl,
+            vertScrollerElDom, horizScrollerElDom,
+            horizontalCanScrollLeft, horizontalCanScrollRight,
+            verticalCanScrollDown, verticalCanScrollUp;
+
+        
+        if (horizScroller) {
+            horizScrollerEl = horizScroller.scrollEl;
+            if (horizScrollerEl) {
+                horizScrollerElDom = horizScrollerEl.dom;
+                horizontalCanScrollRight = horizScrollerElDom.scrollLeft !== horizScrollerElDom.scrollWidth - horizScrollerElDom.clientWidth;
+                horizontalCanScrollLeft  = horizScrollerElDom.scrollLeft !== 0;
+            }
+        }
+        if (vertScroller) {
+            vertScrollerEl = vertScroller.scrollEl;
+            if (vertScrollerEl) {
+                vertScrollerElDom = vertScrollerEl.dom;
+                verticalCanScrollDown = vertScrollerElDom.scrollTop !== vertScrollerElDom.scrollHeight - vertScrollerElDom.clientHeight;
+                verticalCanScrollUp   = vertScrollerElDom.scrollTop !== 0;
+            }
         }
-    },
 
-    
-    onDisableChange : function(node, state){
-        this.disabled = state;
-        if (this.checkbox) {
-            this.checkbox.disabled = state;
+        if (horizScroller) {
+            if ((deltaX < 0 && horizontalCanScrollLeft) || (deltaX > 0 && horizontalCanScrollRight)) {
+                e.stopEvent();
+                horizScroller.scrollByDeltaX(deltaX);
+            }
         }
-        if(state){
-            this.addClass("x-tree-node-disabled");
-        }else{
-            this.removeClass("x-tree-node-disabled");
+        if (vertScroller) {
+            if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
+                e.stopEvent();
+                vertScroller.scrollByDeltaY(deltaY);
+            }
         }
     },
 
     
-    onSelectedChange : function(state){
-        if(state){
-            this.focus();
-            this.addClass("x-tree-selected");
-        }else{
-            
-            this.removeClass("x-tree-selected");
+    onViewReady: function() {
+        var me = this;
+        me.fireEvent('viewready', me);
+        if (me.deferRowRender) {
+            me.determineScrollbars();
+            me.invalidateScroller();
         }
     },
 
     
-    onMove : function(tree, node, oldParent, newParent, index, refNode){
-        this.childIndent = null;
-        if(this.rendered){
-            var targetNode = newParent.ui.getContainer();
-            if(!targetNode){
-                this.holder = document.createElement("div");
-                this.holder.appendChild(this.wrap);
-                return;
-            }
-            var insertBefore = refNode ? refNode.ui.getEl() : null;
-            if(insertBefore){
-                targetNode.insertBefore(this.wrap, insertBefore);
-            }else{
-                targetNode.appendChild(this.wrap);
+    onViewRefresh: function() {
+        var me = this;
+
+        
+        if (!me.rendering) {
+            this.determineScrollbars();
+            if (this.invalidateScrollerOnRefresh) {
+                this.invalidateScroller();
             }
-            this.node.renderIndent(true, oldParent != newParent);
         }
     },
 
+    
+    setScrollTop: function(top) {
+        var me               = this,
+            rootCmp          = me.getScrollerOwner(),
+            verticalScroller = me.getVerticalScroller();
 
-    addClass : function(cls){
-        if(this.elNode){
-            Ext.fly(this.elNode).addClass(cls);
+        rootCmp.virtualScrollTop = top;
+        if (verticalScroller) {
+            verticalScroller.setScrollTop(top);
         }
     },
 
-
-    removeClass : function(cls){
-        if(this.elNode){
-            Ext.fly(this.elNode).removeClass(cls);
+    getScrollerOwner: function() {
+        var rootCmp = this;
+        if (!this.scrollerOwner) {
+            rootCmp = this.up('[scrollerOwner]');
         }
+        return rootCmp;
     },
 
     
-    remove : function(){
-        if(this.rendered){
-            this.holder = document.createElement("div");
-            this.holder.appendChild(this.wrap);
-        }
-    },
+    scrollByDeltaY: function(deltaY) {
+        var verticalScroller = this.getVerticalScroller();
 
-    
-    fireEvent : function(){
-        return this.node.fireEvent.apply(this.node, arguments);
+        if (verticalScroller) {
+            verticalScroller.scrollByDeltaY(deltaY);
+        }
     },
 
     
-    initEvents : function(){
-        this.node.on("move", this.onMove, this);
+    scrollByDeltaX: function(deltaX) {
+        var horizontalScroller = this.getHorizontalScroller();
 
-        if(this.node.disabled){
-            this.onDisableChange(this.node, true);
-        }
-        if(this.node.hidden){
-            this.hide();
-        }
-        var ot = this.node.getOwnerTree();
-        var dd = ot.enableDD || ot.enableDrag || ot.enableDrop;
-        if(dd && (!this.node.isRoot || ot.rootVisible)){
-            Ext.dd.Registry.register(this.elNode, {
-                node: this.node,
-                handles: this.getDDHandles(),
-                isHandle: false
-            });
+        if (horizontalScroller) {
+            horizontalScroller.scrollByDeltaX(deltaX);
         }
     },
 
     
-    getDDHandles : function(){
-        return [this.iconNode, this.textNode, this.elNode];
-    },
-
+    getLhsMarker: function() {
+        var me = this;
 
-    hide : function(){
-        this.node.hidden = true;
-        if(this.wrap){
-            this.wrap.style.display = "none";
+        if (!me.lhsMarker) {
+            me.lhsMarker = Ext.DomHelper.append(me.el, {
+                cls: Ext.baseCSSPrefix + 'grid-resize-marker'
+            }, true);
         }
+        return me.lhsMarker;
     },
 
+    
+    getRhsMarker: function() {
+        var me = this;
 
-    show : function(){
-        this.node.hidden = false;
-        if(this.wrap){
-            this.wrap.style.display = "";
+        if (!me.rhsMarker) {
+            me.rhsMarker = Ext.DomHelper.append(me.el, {
+                cls: Ext.baseCSSPrefix + 'grid-resize-marker'
+            }, true);
         }
+        return me.rhsMarker;
     },
 
     
-    onContextMenu : function(e){
-        if (this.node.hasListener("contextmenu") || this.node.getOwnerTree().hasListener("contextmenu")) {
-            e.preventDefault();
-            this.focus();
-            this.fireEvent("contextmenu", this.node, e);
+    getSelectionModel: function(){
+        if (!this.selModel) {
+            this.selModel = {};
         }
-    },
 
-    
-    onClick : function(e){
-        if(this.dropping){
-            e.stopEvent();
-            return;
+        var mode = 'SINGLE',
+            type;
+        if (this.simpleSelect) {
+            mode = 'SIMPLE';
+        } else if (this.multiSelect) {
+            mode = 'MULTI';
         }
-        if(this.fireEvent("beforeclick", this.node, e) !== false){
-            var a = e.getTarget('a');
-            if(!this.disabled && this.node.attributes.href && a){
-                this.fireEvent("click", this.node, e);
-                return;
-            }else if(a && e.ctrlKey){
-                e.stopEvent();
-            }
-            e.preventDefault();
-            if(this.disabled){
-                return;
-            }
 
-            if(this.node.attributes.singleClickExpand && !this.animating && this.node.isExpandable()){
-                this.node.toggle();
-            }
+        Ext.applyIf(this.selModel, {
+            allowDeselect: this.allowDeselect,
+            mode: mode
+        });
 
-            this.fireEvent("click", this.node, e);
-        }else{
-            e.stopEvent();
+        if (!this.selModel.events) {
+            type = this.selModel.selType || this.selType;
+            this.selModel = Ext.create('selection.' + type, this.selModel);
         }
-    },
 
-    
-    onDblClick : function(e){
-        e.preventDefault();
-        if(this.disabled){
-            return;
+        if (!this.selModel.hasRelaySetup) {
+            this.relayEvents(this.selModel, [
+                'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
+            ]);
+            this.selModel.hasRelaySetup = true;
         }
-        if(this.fireEvent("beforedblclick", this.node, e) !== false){
-            if(this.checkbox){
-                this.toggleCheck();
-            }
-            if(!this.animating && this.node.isExpandable()){
-                this.node.toggle();
-            }
-            this.fireEvent("dblclick", this.node, e);
+
+        
+        
+        if (this.disableSelection) {
+            this.selModel.locked = true;
         }
+        return this.selModel;
     },
 
-    onOver : function(e){
-        this.addClass('x-tree-node-over');
-    },
+    onVerticalScroll: function(event, target) {
+        var owner = this.getScrollerOwner(),
+            items = owner.query('tableview'),
+            i = 0,
+            len = items.length;
 
-    onOut : function(e){
-        this.removeClass('x-tree-node-over');
+        for (; i < len; i++) {
+            items[i].el.dom.scrollTop = target.scrollTop;
+        }
     },
 
-    
-    onCheckChange : function(){
-        var checked = this.checkbox.checked;
-        
-        this.checkbox.defaultChecked = checked;
-        this.node.attributes.checked = checked;
-        this.fireEvent('checkchange', this.node, checked);
-    },
+    onHorizontalScroll: function(event, target) {
+        var owner = this.getScrollerOwner(),
+            items = owner.query('tableview'),
+            center = items[1] || items[0];
 
-    
-    ecClick : function(e){
-        if(!this.animating && this.node.isExpandable()){
-            this.node.toggle();
-        }
+        center.el.dom.scrollLeft = target.scrollLeft;
+        this.headerCt.el.dom.scrollLeft = target.scrollLeft;
     },
 
     
-    startDrop : function(){
-        this.dropping = true;
-    },
+    onStoreLoad: Ext.emptyFn,
 
-    
-    endDrop : function(){
-       setTimeout(function(){
-           this.dropping = false;
-       }.createDelegate(this), 50);
+    getEditorParent: function() {
+        return this.body;
     },
 
+    bindStore: function(store) {
+        var me = this;
+        me.store = store;
+        me.getView().bindStore(store);
+    },
     
-    expand : function(){
-        this.updateExpandIcon();
-        this.ctNode.style.display = "";
+    beforeDestroy: function(){
+        
+        
+        
+        Ext.destroy(this.horizontalScroller, this.verticalScroller);
+        this.callParent();
     },
 
     
-    focus : function(){
-        if(!this.node.preventHScroll){
-            try{this.anchor.focus();
-            }catch(e){}
-        }else{
-            try{
-                var noscroll = this.node.getOwnerTree().getTreeEl().dom;
-                var l = noscroll.scrollLeft;
-                this.anchor.focus();
-                noscroll.scrollLeft = l;
-            }catch(e){}
+    reconfigure: function(store, columns) {
+        var me = this,
+            headerCt = me.headerCt;
+
+        if (me.lockable) {
+            me.reconfigureLockable(store, columns);
+        } else {
+            if (columns) {
+                headerCt.suspendLayout = true;
+                headerCt.removeAll();
+                headerCt.add(columns);
+            }
+            if (store) {
+                store = Ext.StoreManager.lookup(store);
+                me.bindStore(store);
+            } else {
+                me.getView().refresh();
+            }
+            if (columns) {
+                headerCt.suspendLayout = false;
+                me.forceComponentLayout();
+            }
         }
-    },
+        me.fireEvent('reconfigure', me);
+    }
+});
 
+Ext.define('Ext.view.Table', {
+    extend: 'Ext.view.View',
+    alias: 'widget.tableview',
+    uses: [
+        'Ext.view.TableChunker',
+        'Ext.util.DelayedTask',
+        'Ext.util.MixedCollection'
+    ],
 
-    toggleCheck : function(value){
-        var cb = this.checkbox;
-        if(cb){
-            cb.checked = (value === undefined ? !cb.checked : value);
-            this.onCheckChange();
-        }
-    },
+    baseCls: Ext.baseCSSPrefix + 'grid-view',
 
     
-    blur : function(){
-        try{
-            this.anchor.blur();
-        }catch(e){}
-    },
-
+    itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
     
-    animExpand : function(callback){
-        var ct = Ext.get(this.ctNode);
-        ct.stopFx();
-        if(!this.node.isExpandable()){
-            this.updateExpandIcon();
-            this.ctNode.style.display = "";
-            Ext.callback(callback);
-            return;
-        }
-        this.animating = true;
-        this.updateExpandIcon();
-
-        ct.slideIn('t', {
-           callback : function(){
-               this.animating = false;
-               Ext.callback(callback);
-            },
-            scope: this,
-            duration: this.node.ownerTree.duration || .25
-        });
-    },
+    cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
 
-    
-    highlight : function(){
-        var tree = this.node.getOwnerTree();
-        Ext.fly(this.wrap).highlight(
-            tree.hlColor || "C3DAF9",
-            {endColor: tree.hlBaseColor}
-        );
-    },
+    selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
+    selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
+    focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
+    overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
+    altRowCls:   Ext.baseCSSPrefix + 'grid-row-alt',
+    rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
+    cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
 
     
-    collapse : function(){
-        this.updateExpandIcon();
-        this.ctNode.style.display = "none";
-    },
+    trackOver: true,
 
     
-    animCollapse : function(callback){
-        var ct = Ext.get(this.ctNode);
-        ct.enableDisplayMode('block');
-        ct.stopFx();
+    getRowClass: null,
 
-        this.animating = true;
-        this.updateExpandIcon();
+    initComponent: function() {
+        var me = this;
 
-        ct.slideOut('t', {
-            callback : function(){
-               this.animating = false;
-               Ext.callback(callback);
-            },
-            scope: this,
-            duration: this.node.ownerTree.duration || .25
+        me.scrollState = {};
+        me.selModel.view = me;
+        me.headerCt.view = me;
+        me.initFeatures();
+        me.tpl = '<div></div>';
+        me.callParent();
+        me.mon(me.store, {
+            load: me.onStoreLoad,
+            scope: me
         });
+
+        
+        
+        
+        
+        
+        
+        
+        
+        
     },
 
     
-    getContainer : function(){
-        return this.ctNode;
+    onStoreLoad: function(){
+        var me = this;
+
+        if (me.invalidateScrollerOnRefresh) {
+            if (Ext.isGecko) {
+                if (!me.scrollToTopTask) {
+                    me.scrollToTopTask = Ext.create('Ext.util.DelayedTask', me.scrollToTop, me);
+                }
+                me.scrollToTopTask.delay(1);
+            } else {
+                me    .scrollToTop();
+            }
+        }
     },
 
+    
+    scrollToTop: Ext.emptyFn,
 
-    getEl : function(){
-        return this.wrap;
+    
+    addElListener: function(eventName, fn, scope){
+        this.mon(this, eventName, fn, scope, {
+            element: 'el'
+        });
     },
 
     
-    appendDDGhost : function(ghostNode){
-        ghostNode.appendChild(this.elNode.cloneNode(true));
+    getGridColumns: function() {
+        return this.headerCt.getGridColumns();
     },
 
     
-    getDDRepairXY : function(){
-        return Ext.lib.Dom.getXY(this.iconNode);
+    getHeaderAtIndex: function(index) {
+        return this.headerCt.getHeaderAtIndex(index);
     },
 
     
-    onRender : function(){
-        this.render();
+    getCell: function(record, column) {
+        var row = this.getNode(record);
+        return Ext.fly(row).down(column.getCellSelector());
     },
 
     
-    render : function(bulkRender){
-        var n = this.node, a = n.attributes;
-        var targetNode = n.parentNode ?
-              n.parentNode.ui.getContainer() : n.ownerTree.innerCt.dom;
-
-        if(!this.rendered){
-            this.rendered = true;
-
-            this.renderElements(n, a, targetNode, bulkRender);
-
-            if(a.qtip){
-               if(this.textNode.setAttributeNS){
-                   this.textNode.setAttributeNS("ext", "qtip", a.qtip);
-                   if(a.qtipTitle){
-                       this.textNode.setAttributeNS("ext", "qtitle", a.qtipTitle);
-                   }
-               }else{
-                   this.textNode.setAttribute("ext:qtip", a.qtip);
-                   if(a.qtipTitle){
-                       this.textNode.setAttribute("ext:qtitle", a.qtipTitle);
-                   }
-               }
-            }else if(a.qtipCfg){
-                a.qtipCfg.target = Ext.id(this.textNode);
-                Ext.QuickTips.register(a.qtipCfg);
-            }
-            this.initEvents();
-            if(!this.node.expanded){
-                this.updateExpandIcon(true);
-            }
-        }else{
-            if(bulkRender === true) {
-                targetNode.appendChild(this.wrap);
-            }
+    getFeature: function(id) {
+        var features = this.featuresMC;
+        if (features) {
+            return features.get(id);
         }
     },
 
     
-    renderElements : function(n, a, targetNode, bulkRender){
-        
-        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
-
-        var cb = Ext.isBoolean(a.checked),
-            nel,
-            href = a.href ? a.href : Ext.isGecko ? "" : "#",
-            buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
-            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
-            '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
-            '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
-            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
-            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
-             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
-            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
-            "</li>"].join('');
+    initFeatures: function() {
+        var me = this,
+            i = 0,
+            features,
+            len;
 
-        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
-            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
-        }else{
-            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
-        }
+        me.features = me.features || [];
+        features = me.features;
+        len = features.length;
 
-        this.elNode = this.wrap.childNodes[0];
-        this.ctNode = this.wrap.childNodes[1];
-        var cs = this.elNode.childNodes;
-        this.indentNode = cs[0];
-        this.ecNode = cs[1];
-        this.iconNode = cs[2];
-        var index = 3;
-        if(cb){
-            this.checkbox = cs[3];
+        me.featuresMC = Ext.create('Ext.util.MixedCollection');
+        for (; i < len; i++) {
             
-            this.checkbox.defaultChecked = this.checkbox.checked;
-            index++;
+            if (!features[i].isFeature) {
+                features[i] = Ext.create('feature.' + features[i].ftype, features[i]);
+            }
+            
+            features[i].view = me;
+            me.featuresMC.add(features[i]);
         }
-        this.anchor = cs[index];
-        this.textNode = cs[index].firstChild;
     },
 
+    
+    attachEventsForFeatures: function() {
+        var features = this.features,
+            ln       = features.length,
+            i        = 0;
 
-    getAnchor : function(){
-        return this.anchor;
+        for (; i < ln; i++) {
+            if (features[i].isFeature) {
+                features[i].attachEvents();
+            }
+        }
     },
 
+    afterRender: function() {
+        var me = this;
 
-    getTextEl : function(){
-        return this.textNode;
+        me.callParent();
+        me.mon(me.el, {
+            scroll: me.fireBodyScroll,
+            scope: me
+        });
+        me.el.unselectable();
+        me.attachEventsForFeatures();
     },
 
-
-    getIconEl : function(){
-        return this.iconNode;
+    fireBodyScroll: function(e, t) {
+        this.fireEvent('bodyscroll', e, t);
     },
 
+    
+    
+    prepareData: function(data, idx, record) {
+        var me       = this,
+            orig     = me.headerCt.prepareData(data, idx, record, me, me.ownerCt),
+            features = me.features,
+            ln       = features.length,
+            i        = 0,
+            node, feature;
+
+        for (; i < ln; i++) {
+            feature = features[i];
+            if (feature.isFeature) {
+                Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, me));
+            }
+        }
 
-    isChecked : function(){
-        return this.checkbox ? this.checkbox.checked : false;
+        return orig;
     },
 
     
-    updateExpandIcon : function(){
-        if(this.rendered){
-            var n = this.node,
-                c1,
-                c2,
-                cls = n.isLast() ? "x-tree-elbow-end" : "x-tree-elbow",
-                hasChild = n.hasChildNodes();
-            if(hasChild || n.attributes.expandable){
-                if(n.expanded){
-                    cls += "-minus";
-                    c1 = "x-tree-node-collapsed";
-                    c2 = "x-tree-node-expanded";
-                }else{
-                    cls += "-plus";
-                    c1 = "x-tree-node-expanded";
-                    c2 = "x-tree-node-collapsed";
-                }
-                if(this.wasLeaf){
-                    this.removeClass("x-tree-node-leaf");
-                    this.wasLeaf = false;
-                }
-                if(this.c1 != c1 || this.c2 != c2){
-                    Ext.fly(this.elNode).replaceClass(c1, c2);
-                    this.c1 = c1; this.c2 = c2;
-                }
-            }else{
-                if(!this.wasLeaf){
-                    Ext.fly(this.elNode).replaceClass("x-tree-node-expanded", "x-tree-node-collapsed");
-                    delete this.c1;
-                    delete this.c2;
-                    this.wasLeaf = true;
-                }
+    collectData: function(records, startIndex) {
+        var preppedRecords = this.callParent(arguments),
+            headerCt  = this.headerCt,
+            fullWidth = headerCt.getFullWidth(),
+            features  = this.features,
+            ln = features.length,
+            o = {
+                rows: preppedRecords,
+                fullWidth: fullWidth
+            },
+            i  = 0,
+            feature,
+            j = 0,
+            jln,
+            rowParams;
+
+        jln = preppedRecords.length;
+        
+        
+        if (this.getRowClass) {
+            for (; j < jln; j++) {
+                rowParams = {};
+                preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
             }
-            var ecc = "x-tree-ec-icon "+cls;
-            if(this.ecc != ecc){
-                this.ecNode.className = ecc;
-                this.ecc = ecc;
+        }
+        
+        
+        for (; i < ln; i++) {
+            feature = features[i];
+            if (feature.isFeature && feature.collectData && !feature.disabled) {
+                o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
+                break;
             }
         }
+        return o;
     },
 
     
-    onIdChange: function(id){
-        if(this.rendered){
-            this.elNode.setAttribute('ext:tree-node-id', id);
-        }
-    },
-
     
-    getChildIndent : function(){
-        if(!this.childIndent){
-            var buf = [],
-                p = this.node;
-            while(p){
-                if(!p.isRoot || (p.isRoot && p.ownerTree.rootVisible)){
-                    if(!p.isLast()) {
-                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-elbow-line" />');
-                    } else {
-                        buf.unshift('<img src="'+this.emptyIcon+'" class="x-tree-icon" />');
-                    }
+    onHeaderResize: function(header, w, suppressFocus) {
+        var me = this,
+            el = me.el;
+
+        if (el) {
+            me.saveScrollState();
+            
+            
+            
+
+            
+            
+            
+            if (Ext.isIE6 || Ext.isIE7) {
+                if (header.el.hasCls(Ext.baseCSSPrefix + 'column-header-first')) {
+                    w += 1;
                 }
-                p = p.parentNode;
             }
-            this.childIndent = buf.join("");
-        }
-        return this.childIndent;
-    },
-
-    
-    renderIndent : function(){
-        if(this.rendered){
-            var indent = "",
-                p = this.node.parentNode;
-            if(p){
-                indent = p.ui.getChildIndent();
+            el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
+            el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(me.headerCt.getFullWidth());
+            me.restoreScrollState();
+            if (!me.ignoreTemplate) {
+                me.setNewTemplate();
             }
-            if(this.indentMarkup != indent){ 
-                this.indentNode.innerHTML = indent;
-                this.indentMarkup = indent;
+            if (!suppressFocus) {
+                me.el.focus();
             }
-            this.updateExpandIcon();
         }
     },
 
-    destroy : function(){
-        if(this.elNode){
-            Ext.dd.Registry.unregister(this.elNode.id);
-        }
-
-        Ext.each(['textnode', 'anchor', 'checkbox', 'indentNode', 'ecNode', 'iconNode', 'elNode', 'ctNode', 'wrap', 'holder'], function(el){
-            if(this[el]){
-                Ext.fly(this[el]).remove();
-                delete this[el];
-            }
-        }, this);
-        delete this.node;
-    }
-};
-
-
-Ext.tree.RootTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
     
-    render : function(){
-        if(!this.rendered){
-            var targetNode = this.node.ownerTree.innerCt.dom;
-            this.node.expanded = true;
-            targetNode.innerHTML = '<div class="x-tree-root-node"></div>';
-            this.wrap = this.ctNode = targetNode.firstChild;
-        }
-    },
-    collapse : Ext.emptyFn,
-    expand : Ext.emptyFn
-});
-Ext.tree.TreeLoader = function(config){
-    this.baseParams = {};
-    Ext.apply(this, config);
-
-    this.addEvents(
+    onHeaderShow: function(headerCt, header, suppressFocus) {
+        var me = this;
+        me.ignoreTemplate = true;
         
-        "beforeload",
+        if (header.oldWidth) {
+            me.onHeaderResize(header, header.oldWidth, suppressFocus);
+            delete header.oldWidth;
         
-        "load",
         
-        "loadexception"
-    );
-    Ext.tree.TreeLoader.superclass.constructor.call(this);
-    if(Ext.isString(this.paramOrder)){
-        this.paramOrder = this.paramOrder.split(/[\s,|]/);
-    }
-};
-
-Ext.extend(Ext.tree.TreeLoader, Ext.util.Observable, {
-    
-    
-    
-    
-    
-    
-    
-    uiProviders : {},
-
-    
-    clearOnLoad : true,
+        
+        } else if (header.width && !header.flex) {
+            me.onHeaderResize(header, header.width, suppressFocus);
+        }
+        delete me.ignoreTemplate;
+        me.setNewTemplate();
+    },
 
     
-    paramOrder: undefined,
+    onHeaderHide: function(headerCt, header, suppressFocus) {
+        this.onHeaderResize(header, 0, suppressFocus);
+    },
 
     
-    paramsAsHash: false,
+    setNewTemplate: function() {
+        var me = this,
+            columns = me.headerCt.getColumnsForTpl(true);
 
-    
-    nodeParameter: 'node',
+        me.tpl = me.getTableChunker().getTableTpl({
+            columns: columns,
+            features: me.features
+        });
+    },
 
     
-    directFn : undefined,
+    getTableChunker: function() {
+        return this.chunker || Ext.view.TableChunker;
+    },
 
     
-    load : function(node, callback, scope){
-        if(this.clearOnLoad){
-            while(node.firstChild){
-                node.removeChild(node.firstChild);
-            }
-        }
-        if(this.doPreload(node)){ 
-            this.runCallback(callback, scope || node, [node]);
-        }else if(this.directFn || this.dataUrl || this.url){
-            this.requestData(node, callback, scope || node);
+    addRowCls: function(rowInfo, cls) {
+        var row = this.getNode(rowInfo);
+        if (row) {
+            Ext.fly(row).addCls(cls);
         }
     },
 
-    doPreload : function(node){
-        if(node.attributes.children){
-            if(node.childNodes.length < 1){ 
-                var cs = node.attributes.children;
-                node.beginUpdate();
-                for(var i = 0, len = cs.length; i < len; i++){
-                    var cn = node.appendChild(this.createNode(cs[i]));
-                    if(this.preloadChildren){
-                        this.doPreload(cn);
-                    }
-                }
-                node.endUpdate();
-            }
-            return true;
+    
+    removeRowCls: function(rowInfo, cls) {
+        var row = this.getNode(rowInfo);
+        if (row) {
+            Ext.fly(row).removeCls(cls);
         }
-        return false;
     },
 
-    getParams: function(node){
-        var bp = Ext.apply({}, this.baseParams),
-            np = this.nodeParameter,
-            po = this.paramOrder;
-
-        np && (bp[ np ] = node.id);
+    
+    onRowSelect : function(rowIdx) {
+        this.addRowCls(rowIdx, this.selectedItemCls);
+    },
 
-        if(this.directFn){
-            var buf = [node.id];
-            if(po){
-                
-                if(np && po.indexOf(np) > -1){
-                    buf = [];
-                }
+    
+    onRowDeselect : function(rowIdx) {
+        var me = this;
 
-                for(var i = 0, len = po.length; i < len; i++){
-                    buf.push(bp[ po[i] ]);
-                }
-            }else if(this.paramsAsHash){
-                buf = [bp];
-            }
-            return buf;
-        }else{
-            return bp;
-        }
+        me.removeRowCls(rowIdx, me.selectedItemCls);
+        me.removeRowCls(rowIdx, me.focusedItemCls);
     },
 
-    requestData : function(node, callback, scope){
-        if(this.fireEvent("beforeload", this, node, callback) !== false){
-            if(this.directFn){
-                var args = this.getParams(node);
-                args.push(this.processDirectResponse.createDelegate(this, [{callback: callback, node: node, scope: scope}], true));
-                this.directFn.apply(window, args);
-            }else{
-                this.transId = Ext.Ajax.request({
-                    method:this.requestMethod,
-                    url: this.dataUrl||this.url,
-                    success: this.handleResponse,
-                    failure: this.handleFailure,
-                    scope: this,
-                    argument: {callback: callback, node: node, scope: scope},
-                    params: this.getParams(node)
-                });
-            }
-        }else{
-            
-            
-            this.runCallback(callback, scope || node, []);
+    onCellSelect: function(position) {
+        var cell = this.getCellByPosition(position);
+        if (cell) {
+            cell.addCls(this.selectedCellCls);
         }
     },
 
-    processDirectResponse: function(result, response, args){
-        if(response.status){
-            this.handleResponse({
-                responseData: Ext.isArray(result) ? result : null,
-                responseText: result,
-                argument: args
-            });
-        }else{
-            this.handleFailure({
-                argument: args
-            });
+    onCellDeselect: function(position) {
+        var cell = this.getCellByPosition(position);
+        if (cell) {
+            cell.removeCls(this.selectedCellCls);
         }
-    },
 
-    
-    runCallback: function(cb, scope, args){
-        if(Ext.isFunction(cb)){
-            cb.apply(scope, args);
-        }
     },
 
-    isLoading : function(){
-        return !!this.transId;
+    onCellFocus: function(position) {
+        
+        this.focusCell(position);
     },
 
-    abort : function(){
-        if(this.isLoading()){
-            Ext.Ajax.abort(this.transId);
+    getCellByPosition: function(position) {
+        var row    = position.row,
+            column = position.column,
+            store  = this.store,
+            node   = this.getNode(row),
+            header = this.headerCt.getHeaderAtIndex(column),
+            cellSelector,
+            cell = false;
+
+        if (header && node) {
+            cellSelector = header.getCellSelector();
+            cell = Ext.fly(node).down(cellSelector);
         }
+        return cell;
     },
 
     
-    createNode : function(attr){
-        
-        if(this.baseAttrs){
-            Ext.applyIf(attr, this.baseAttrs);
-        }
-        if(this.applyLoader !== false && !attr.loader){
-            attr.loader = this;
-        }
-        if(Ext.isString(attr.uiProvider)){
-           attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
-        }
-        if(attr.nodeType){
-            return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
-        }else{
-            return attr.leaf ?
-                        new Ext.tree.TreeNode(attr) :
-                        new Ext.tree.AsyncTreeNode(attr);
-        }
-    },
+    
+    onRowFocus: function(rowIdx, highlight, supressFocus) {
+        var me = this,
+            row = me.getNode(rowIdx);
 
-    processResponse : function(response, node, callback, scope){
-        var json = response.responseText;
-        try {
-            var o = response.responseData || Ext.decode(json);
-            node.beginUpdate();
-            for(var i = 0, len = o.length; i < len; i++){
-                var n = this.createNode(o[i]);
-                if(n){
-                    node.appendChild(n);
-                }
+        if (highlight) {
+            me.addRowCls(rowIdx, me.focusedItemCls);
+            if (!supressFocus) {
+                me.focusRow(rowIdx);
             }
-            node.endUpdate();
-            this.runCallback(callback, scope || node, [node]);
-        }catch(e){
-            this.handleFailure(response);
+            
+        } else {
+            me.removeRowCls(rowIdx, me.focusedItemCls);
         }
     },
 
-    handleResponse : function(response){
-        this.transId = false;
-        var a = response.argument;
-        this.processResponse(response, a.node, a.callback, a.scope);
-        this.fireEvent("load", this, a.node, response);
-    },
-
-    handleFailure : function(response){
-        this.transId = false;
-        var a = response.argument;
-        this.fireEvent("loadexception", this, a.node, response);
-        this.runCallback(a.callback, a.scope || a.node, [a.node]);
-    },
-
-    destroy : function(){
-        this.abort();
-        this.purgeListeners();
-    }
-});
-Ext.tree.TreeFilter = function(tree, config){
-    this.tree = tree;
-    this.filtered = {};
-    Ext.apply(this, config);
-};
+    
+    focusRow: function(rowIdx) {
+        var me         = this,
+            row        = me.getNode(rowIdx),
+            el         = me.el,
+            adjustment = 0,
+            panel      = me.ownerCt,
+            rowRegion,
+            elRegion,
+            record;
 
-Ext.tree.TreeFilter.prototype = {
-    clearBlank:false,
-    reverse:false,
-    autoClear:false,
-    remove:false,
+        if (row && el) {
+            elRegion  = el.getRegion();
+            rowRegion = Ext.fly(row).getRegion();
+            
+            if (rowRegion.top < elRegion.top) {
+                adjustment = rowRegion.top - elRegion.top;
+            
+            } else if (rowRegion.bottom > elRegion.bottom) {
+                adjustment = rowRegion.bottom - elRegion.bottom;
+            }
+            record = me.getRecord(row);
+            rowIdx = me.store.indexOf(record);
 
-     
-    filter : function(value, attr, startNode){
-        attr = attr || "text";
-        var f;
-        if(typeof value == "string"){
-            var vlen = value.length;
-            
-            if(vlen == 0 && this.clearBlank){
-                this.clear();
-                return;
+            if (adjustment) {
+                
+                panel.scrollByDeltaY(adjustment);
             }
-            value = value.toLowerCase();
-            f = function(n){
-                return n.attributes[attr].substr(0, vlen).toLowerCase() == value;
-            };
-        }else if(value.exec){ 
-            f = function(n){
-                return value.test(n.attributes[attr]);
-            };
-        }else{
-            throw 'Illegal filter type, must be string or regex';
+            me.fireEvent('rowfocus', record, row, rowIdx);
         }
-        this.filterBy(f, null, startNode);
-       },
+    },
 
-    
-    filterBy : function(fn, scope, startNode){
-        startNode = startNode || this.tree.root;
-        if(this.autoClear){
-            this.clear();
-        }
-        var af = this.filtered, rv = this.reverse;
-        var f = function(n){
-            if(n == startNode){
-                return true;
-            }
-            if(af[n.id]){
-                return false;
+    focusCell: function(position) {
+        var me          = this,
+            cell        = me.getCellByPosition(position),
+            el          = me.el,
+            adjustmentY = 0,
+            adjustmentX = 0,
+            elRegion    = el.getRegion(),
+            panel       = me.ownerCt,
+            cellRegion,
+            record;
+
+        if (cell) {
+            cellRegion = cell.getRegion();
+            
+            if (cellRegion.top < elRegion.top) {
+                adjustmentY = cellRegion.top - elRegion.top;
+            
+            } else if (cellRegion.bottom > elRegion.bottom) {
+                adjustmentY = cellRegion.bottom - elRegion.bottom;
             }
-            var m = fn.call(scope || n, n);
-            if(!m || rv){
-                af[n.id] = n;
-                n.ui.hide();
-                return false;
+
+            
+            if (cellRegion.left < elRegion.left) {
+                adjustmentX = cellRegion.left - elRegion.left;
+            
+            } else if (cellRegion.right > elRegion.right) {
+                adjustmentX = cellRegion.right - elRegion.right;
             }
-            return true;
-        };
-        startNode.cascade(f);
-        if(this.remove){
-           for(var id in af){
-               if(typeof id != "function"){
-                   var n = af[id];
-                   if(n && n.parentNode){
-                       n.parentNode.removeChild(n);
-                   }
-               }
-           }
-        }
-    },
 
-    
-    clear : function(){
-        var t = this.tree;
-        var af = this.filtered;
-        for(var id in af){
-            if(typeof id != "function"){
-                var n = af[id];
-                if(n){
-                    n.ui.show();
-                }
+            if (adjustmentY) {
+                
+                panel.scrollByDeltaY(adjustmentY);
             }
+            if (adjustmentX) {
+                panel.scrollByDeltaX(adjustmentX);
+            }
+            el.focus();
+            me.fireEvent('cellfocus', record, cell, position);
         }
-        this.filtered = {};
-    }
-};
+    },
 
-Ext.tree.TreeSorter = function(tree, config){
-    
-    
-    
     
+    scrollByDelta: function(delta, dir) {
+        dir = dir || 'scrollTop';
+        var elDom = this.el.dom;
+        elDom[dir] = (elDom[dir] += delta);
+    },
+
+    onUpdate: function(ds, index) {
+        this.callParent(arguments);
+    },
+
     
+    saveScrollState: function() {
+        if (this.rendered) {
+            var dom = this.el.dom, 
+                state = this.scrollState;
+            
+            state.left = dom.scrollLeft;
+            state.top = dom.scrollTop;
+        }
+    },
+
     
+    restoreScrollState: function() {
+        if (this.rendered) {
+            var dom = this.el.dom, 
+                state = this.scrollState, 
+                headerEl = this.headerCt.el.dom;
+            
+            headerEl.scrollLeft = dom.scrollLeft = state.left;
+            dom.scrollTop = state.top;
+        }
+    },
 
-    Ext.apply(this, config);
-    tree.on("beforechildrenrendered", this.doSort, this);
-    tree.on("append", this.updateSort, this);
-    tree.on("insert", this.updateSort, this);
-    tree.on("textchange", this.updateSortParent, this);
+    
+    refresh: function() {
+        this.setNewTemplate();
+        this.callParent(arguments);
+    },
 
-    var dsc = this.dir && this.dir.toLowerCase() == "desc";
-    var p = this.property || "text";
-    var sortType = this.sortType;
-    var fs = this.folderSort;
-    var cs = this.caseSensitive === true;
-    var leafAttr = this.leafAttr || 'leaf';
+    processItemEvent: function(record, row, rowIndex, e) {
+        var me = this,
+            cell = e.getTarget(me.cellSelector, row),
+            cellIndex = cell ? cell.cellIndex : -1,
+            map = me.statics().EventMap,
+            selModel = me.getSelectionModel(),
+            type = e.type,
+            result;
 
-    this.sortFn = function(n1, n2){
-        if(fs){
-            if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
-                return 1;
-            }
-            if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
-                return -1;
+        if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
+            
+            cell = me.getCellByPosition(selModel.getCurrentPosition());
+            if (cell) {
+                cell = cell.dom;
+                cellIndex = cell.cellIndex;
             }
         }
-        var v1 = sortType ? sortType(n1) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
-        var v2 = sortType ? sortType(n2) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
-        if(v1 < v2){
-            return dsc ? +1 : -1;
-        }else if(v1 > v2){
-            return dsc ? -1 : +1;
-        }else{
-            return 0;
+
+        result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
+
+        if (result === false || me.callParent(arguments) === false) {
+            return false;
         }
-    };
-};
 
-Ext.tree.TreeSorter.prototype = {
-    doSort : function(node){
-        node.sort(this.sortFn);
-    },
+        
+        if (type == 'mouseover' || type == 'mouseout') {
+            return true;
+        }
 
-    compareNodes : function(n1, n2){
-        return (n1.text.toUpperCase() > n2.text.toUpperCase() ? 1 : -1);
+        return !(
+            
+            (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
+            (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
+            (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
+            (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
+        );
     },
 
-    updateSort : function(tree, node){
-        if(node.childrenRendered){
-            this.doSort.defer(1, this, [node]);
+    processSpecialEvent: function(e) {
+        var me = this,
+            map = me.statics().EventMap,
+            features = me.features,
+            ln = features.length,
+            type = e.type,
+            i, feature, prefix, featureTarget,
+            beforeArgs, args,
+            panel = me.ownerCt;
+
+        me.callParent(arguments);
+
+        if (type == 'mouseover' || type == 'mouseout') {
+            return;
         }
-    },
 
-    updateSortParent : function(node){
-        var p = node.parentNode;
-        if(p && p.childrenRendered){
-            this.doSort.defer(1, this, [p]);
+        for (i = 0; i < ln; i++) {
+            feature = features[i];
+            if (feature.hasFeatureEvent) {
+                featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
+                if (featureTarget) {
+                    prefix = feature.eventPrefix;
+                    
+                    
+                    beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e);
+                    args = feature.getFireEventArgs(prefix + type, me, featureTarget, e);
+
+                    if (
+                        
+                        (me.fireEvent.apply(me, beforeArgs) === false) ||
+                        
+                        (panel.fireEvent.apply(panel, beforeArgs) === false) ||
+                        
+                        (me.fireEvent.apply(me, args) === false) ||
+                        
+                        (panel.fireEvent.apply(panel, args) === false)
+                    ) {
+                        return false;
+                    }
+                }
+            }
         }
-    }
-};
-if(Ext.dd.DropZone){
-    
-Ext.tree.TreeDropZone = function(tree, config){
-    
-    this.allowParentInsert = config.allowParentInsert || false;
-    
-    this.allowContainerDrop = config.allowContainerDrop || false;
-    
-    this.appendOnly = config.appendOnly || false;
+        return true;
+    },
 
-    Ext.tree.TreeDropZone.superclass.constructor.call(this, tree.getTreeEl(), config);
-    
-    this.tree = tree;
-    
-    this.dragOverData = {};
-    
-    this.lastInsertClass = "x-tree-no-status";
-};
+    onCellMouseDown: Ext.emptyFn,
+    onCellMouseUp: Ext.emptyFn,
+    onCellClick: Ext.emptyFn,
+    onCellDblClick: Ext.emptyFn,
+    onCellContextMenu: Ext.emptyFn,
+    onCellKeyDown: Ext.emptyFn,
+    onBeforeCellMouseDown: Ext.emptyFn,
+    onBeforeCellMouseUp: Ext.emptyFn,
+    onBeforeCellClick: Ext.emptyFn,
+    onBeforeCellDblClick: Ext.emptyFn,
+    onBeforeCellContextMenu: Ext.emptyFn,
+    onBeforeCellKeyDown: Ext.emptyFn,
 
-Ext.extend(Ext.tree.TreeDropZone, Ext.dd.DropZone, {
     
-    ddGroup : "TreeDD",
+    expandToFit: function(header) {
+        if (header) {
+            var maxWidth = this.getMaxContentWidth(header);
+            delete header.flex;
+            header.setWidth(maxWidth);
+        }
+    },
 
     
-    expandDelay : 1000,
+    getMaxContentWidth: function(header) {
+        var cellSelector = header.getCellInnerSelector(),
+            cells        = this.el.query(cellSelector),
+            i = 0,
+            ln = cells.length,
+            maxWidth = header.el.dom.scrollWidth,
+            scrollWidth;
 
-    
-    expandNode : function(node){
-        if(node.hasChildNodes() && !node.isExpanded()){
-            node.expand(false, null, this.triggerCacheRefresh.createDelegate(this));
+        for (; i < ln; i++) {
+            scrollWidth = cells[i].scrollWidth;
+            if (scrollWidth > maxWidth) {
+                maxWidth = scrollWidth;
+            }
         }
+        return maxWidth;
     },
 
-    
-    queueExpand : function(node){
-        this.expandProcId = this.expandNode.defer(this.expandDelay, this, [node]);
+    getPositionByEvent: function(e) {
+        var me       = this,
+            cellNode = e.getTarget(me.cellSelector),
+            rowNode  = e.getTarget(me.itemSelector),
+            record   = me.getRecord(rowNode),
+            header   = me.getHeaderByCell(cellNode);
+
+        return me.getPosition(record, header);
     },
 
-    
-    cancelExpand : function(){
-        if(this.expandProcId){
-            clearTimeout(this.expandProcId);
-            this.expandProcId = false;
+    getHeaderByCell: function(cell) {
+        if (cell) {
+            var m = cell.className.match(this.cellRe);
+            if (m && m[1]) {
+                return Ext.getCmp(m[1]);
+            }
         }
+        return false;
     },
 
     
-    isValidDropPoint : function(n, pt, dd, e, data){
-        if(!n || !data){ return false; }
-        var targetNode = n.node;
-        var dropNode = data.node;
+    walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
+        var me       = this,
+            row      = pos.row,
+            column   = pos.column,
+            rowCount = me.store.getCount(),
+            firstCol = me.getFirstVisibleColumnIndex(),
+            lastCol  = me.getLastVisibleColumnIndex(),
+            newPos   = {row: row, column: column},
+            activeHeader = me.headerCt.getHeaderAtIndex(column);
+
         
-        if(!(targetNode && targetNode.isTarget && pt)){
-            return false;
-        }
-        if(pt == "append" && targetNode.allowChildren === false){
+        if (!activeHeader || activeHeader.hidden) {
             return false;
         }
-        if((pt == "above" || pt == "below") && (targetNode.parentNode && targetNode.parentNode.allowChildren === false)){
-            return false;
+
+        e = e || {};
+        direction = direction.toLowerCase();
+        switch (direction) {
+            case 'right':
+                
+                if (column === lastCol) {
+                    
+                    if (preventWrap || row === rowCount - 1) {
+                        return false;
+                    }
+                    if (!e.ctrlKey) {
+                        
+                        newPos.row = row + 1;
+                        newPos.column = firstCol;
+                    }
+                
+                } else {
+                    if (!e.ctrlKey) {
+                        newPos.column = column + me.getRightGap(activeHeader);
+                    } else {
+                        newPos.column = lastCol;
+                    }
+                }
+                break;
+
+            case 'left':
+                
+                if (column === firstCol) {
+                    
+                    if (preventWrap || row === 0) {
+                        return false;
+                    }
+                    if (!e.ctrlKey) {
+                        
+                        newPos.row = row - 1;
+                        newPos.column = lastCol;
+                    }
+                
+                } else {
+                    if (!e.ctrlKey) {
+                        newPos.column = column + me.getLeftGap(activeHeader);
+                    } else {
+                        newPos.column = firstCol;
+                    }
+                }
+                break;
+
+            case 'up':
+                
+                if (row === 0) {
+                    return false;
+                
+                } else {
+                    if (!e.ctrlKey) {
+                        newPos.row = row - 1;
+                    } else {
+                        newPos.row = 0;
+                    }
+                }
+                break;
+
+            case 'down':
+                
+                if (row === rowCount - 1) {
+                    return false;
+                
+                } else {
+                    if (!e.ctrlKey) {
+                        newPos.row = row + 1;
+                    } else {
+                        newPos.row = rowCount - 1;
+                    }
+                }
+                break;
         }
-        if(dropNode && (targetNode == dropNode || dropNode.contains(targetNode))){
+
+        if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
             return false;
-        }
-        
-        var overEvent = this.dragOverData;
-        overEvent.tree = this.tree;
-        overEvent.target = targetNode;
-        overEvent.data = data;
-        overEvent.point = pt;
-        overEvent.source = dd;
-        overEvent.rawEvent = e;
-        overEvent.dropNode = dropNode;
-        overEvent.cancel = false;  
-        var result = this.tree.fireEvent("nodedragover", overEvent);
-        return overEvent.cancel === false && result !== false;
-    },
-
-    
-    getDropPoint : function(e, n, dd){
-        var tn = n.node;
-        if(tn.isRoot){
-            return tn.allowChildren !== false ? "append" : false; 
-        }
-        var dragEl = n.ddel;
-        var t = Ext.lib.Dom.getY(dragEl), b = t + dragEl.offsetHeight;
-        var y = Ext.lib.Event.getPageY(e);
-        var noAppend = tn.allowChildren === false || tn.isLeaf();
-        if(this.appendOnly || tn.parentNode.allowChildren === false){
-            return noAppend ? false : "append";
-        }
-        var noBelow = false;
-        if(!this.allowParentInsert){
-            noBelow = tn.hasChildNodes() && tn.isExpanded();
-        }
-        var q = (b - t) / (noAppend ? 2 : 3);
-        if(y >= t && y < (t + q)){
-            return "above";
-        }else if(!noBelow && (noAppend || y >= b-q && y <= b)){
-            return "below";
-        }else{
-            return "append";
+        } else {
+            return newPos;
         }
     },
+    getFirstVisibleColumnIndex: function() {
+        var headerCt   = this.getHeaderCt(),
+            allColumns = headerCt.getGridColumns(),
+            visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
+            firstHeader = visHeaders[0];
 
-    
-    onNodeEnter : function(n, dd, e, data){
-        this.cancelExpand();
-    },
-    
-    onContainerOver : function(dd, e, data) {
-        if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
-            return this.dropAllowed;
-        }
-        return this.dropNotAllowed;
+        return headerCt.getHeaderIndex(firstHeader);
     },
 
-    
-    onNodeOver : function(n, dd, e, data){
-        var pt = this.getDropPoint(e, n, dd);
-        var node = n.node;
-        
-        
-        if(!this.expandProcId && pt == "append" && node.hasChildNodes() && !n.node.isExpanded()){
-            this.queueExpand(node);
-        }else if(pt != "append"){
-            this.cancelExpand();
-        }
-        
-        
-        var returnCls = this.dropNotAllowed;
-        if(this.isValidDropPoint(n, pt, dd, e, data)){
-           if(pt){
-               var el = n.ddel;
-               var cls;
-               if(pt == "above"){
-                   returnCls = n.node.isFirst() ? "x-tree-drop-ok-above" : "x-tree-drop-ok-between";
-                   cls = "x-tree-drag-insert-above";
-               }else if(pt == "below"){
-                   returnCls = n.node.isLast() ? "x-tree-drop-ok-below" : "x-tree-drop-ok-between";
-                   cls = "x-tree-drag-insert-below";
-               }else{
-                   returnCls = "x-tree-drop-ok-append";
-                   cls = "x-tree-drag-append";
-               }
-               if(this.lastInsertClass != cls){
-                   Ext.fly(el).replaceClass(this.lastInsertClass, cls);
-                   this.lastInsertClass = cls;
-               }
-           }
-       }
-       return returnCls;
-    },
+    getLastVisibleColumnIndex: function() {
+        var headerCt   = this.getHeaderCt(),
+            allColumns = headerCt.getGridColumns(),
+            visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
+            lastHeader = visHeaders[visHeaders.length - 1];
 
-    
-    onNodeOut : function(n, dd, e, data){
-        this.cancelExpand();
-        this.removeDropIndicators(n);
+        return headerCt.getHeaderIndex(lastHeader);
     },
 
-    
-    onNodeDrop : function(n, dd, e, data){
-        var point = this.getDropPoint(e, n, dd);
-        var targetNode = n.node;
-        targetNode.ui.startDrop();
-        if(!this.isValidDropPoint(n, point, dd, e, data)){
-            targetNode.ui.endDrop();
-            return false;
-        }
-        
-        var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, point, e) : null);
-        return this.processDrop(targetNode, data, point, dd, e, dropNode);
-    },
-    
-    onContainerDrop : function(dd, e, data){
-        if (this.allowContainerDrop && this.isValidDropPoint({ ddel: this.tree.getRootNode().ui.elNode, node: this.tree.getRootNode() }, "append", dd, e, data)) {
-            var targetNode = this.tree.getRootNode();       
-            targetNode.ui.startDrop();
-            var dropNode = data.node || (dd.getTreeNode ? dd.getTreeNode(data, targetNode, 'append', e) : null);
-            return this.processDrop(targetNode, data, 'append', dd, e, dropNode);
-        }
-        return false;
+    getHeaderCt: function() {
+        return this.headerCt;
     },
-    
-    
-    processDrop: function(target, data, point, dd, e, dropNode){
-        var dropEvent = {
-            tree : this.tree,
-            target: target,
-            data: data,
-            point: point,
-            source: dd,
-            rawEvent: e,
-            dropNode: dropNode,
-            cancel: !dropNode,
-            dropStatus: false
+
+    getPosition: function(record, header) {
+        var me = this,
+            store = me.store,
+            gridCols = me.headerCt.getGridColumns();
+
+        return {
+            row: store.indexOf(record),
+            column: Ext.Array.indexOf(gridCols, header)
         };
-        var retval = this.tree.fireEvent("beforenodedrop", dropEvent);
-        if(retval === false || dropEvent.cancel === true || !dropEvent.dropNode){
-            target.ui.endDrop();
-            return dropEvent.dropStatus;
-        }
-    
-        target = dropEvent.target;
-        if(point == 'append' && !target.isExpanded()){
-            target.expand(false, null, function(){
-                this.completeDrop(dropEvent);
-            }.createDelegate(this));
-        }else{
-            this.completeDrop(dropEvent);
-        }
-        return true;
     },
 
     
-    completeDrop : function(de){
-        var ns = de.dropNode, p = de.point, t = de.target;
-        if(!Ext.isArray(ns)){
-            ns = [ns];
-        }
-        var n;
-        for(var i = 0, len = ns.length; i < len; i++){
-            n = ns[i];
-            if(p == "above"){
-                t.parentNode.insertBefore(n, t);
-            }else if(p == "below"){
-                t.parentNode.insertBefore(n, t.nextSibling);
-            }else{
-                t.appendChild(n);
-            }
-        }
-        n.ui.focus();
-        if(Ext.enableFx && this.tree.hlDrop){
-            n.ui.highlight();
-        }
-        t.ui.endDrop();
-        this.tree.fireEvent("nodedrop", de);
-    },
+    getRightGap: function(activeHeader) {
+        var headerCt        = this.getHeaderCt(),
+            headers         = headerCt.getGridColumns(),
+            activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
+            i               = activeHeaderIdx + 1,
+            nextIdx;
 
-    
-    afterNodeMoved : function(dd, data, e, targetNode, dropNode){
-        if(Ext.enableFx && this.tree.hlDrop){
-            dropNode.ui.focus();
-            dropNode.ui.highlight();
+        for (; i <= headers.length; i++) {
+            if (!headers[i].hidden) {
+                nextIdx = i;
+                break;
+            }
         }
-        this.tree.fireEvent("nodedrop", this.tree, targetNode, data, dd, e);
-    },
 
-    
-    getTree : function(){
-        return this.tree;
+        return nextIdx - activeHeaderIdx;
     },
 
-    
-    removeDropIndicators : function(n){
-        if(n && n.ddel){
-            var el = n.ddel;
-            Ext.fly(el).removeClass([
-                    "x-tree-drag-insert-above",
-                    "x-tree-drag-insert-below",
-                    "x-tree-drag-append"]);
-            this.lastInsertClass = "_noclass";
+    beforeDestroy: function() {
+        if (this.rendered) {
+            this.el.removeAllListeners();
         }
+        this.callParent(arguments);
     },
 
     
-    beforeDragDrop : function(target, e, id){
-        this.cancelExpand();
-        return true;
-    },
+    getLeftGap: function(activeHeader) {
+        var headerCt        = this.getHeaderCt(),
+            headers         = headerCt.getGridColumns(),
+            activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
+            i               = activeHeaderIdx - 1,
+            prevIdx;
 
-    
-    afterRepair : function(data){
-        if(data && Ext.enableFx){
-            data.node.ui.highlight();
+        for (; i >= 0; i--) {
+            if (!headers[i].hidden) {
+                prevIdx = i;
+                break;
+            }
         }
-        this.hideProxy();
-    }    
+
+        return prevIdx - activeHeaderIdx;
+    }
 });
 
-}
-if(Ext.dd.DragZone){
-Ext.tree.TreeDragZone = function(tree, config){
-    Ext.tree.TreeDragZone.superclass.constructor.call(this, tree.innerCt, config);
-    
-    this.tree = tree;
-};
+Ext.define('Ext.grid.View', {
+    extend: 'Ext.view.Table',
+    alias: 'widget.gridview',
 
-Ext.extend(Ext.tree.TreeDragZone, Ext.dd.DragZone, {
     
-    ddGroup : "TreeDD",
+    stripeRows: true,
 
-    
-    onBeforeDrag : function(data, e){
-        var n = data.node;
-        return n && n.draggable && !n.disabled;
-    },
+    invalidateScrollerOnRefresh: true,
 
     
-    onInitDrag : function(e){
-        var data = this.dragData;
-        this.tree.getSelectionModel().select(data.node);
-        this.tree.eventModel.disable();
-        this.proxy.update("");
-        data.node.ui.appendDDGhost(this.proxy.ghost.dom);
-        this.tree.fireEvent("startdrag", this.tree, data.node, e);
+    scrollToTop : function(){
+        if (this.rendered) {
+            var section = this.ownerCt,
+                verticalScroller = section.verticalScroller;
+
+            if (verticalScroller) {
+                verticalScroller.scrollToTop();
+            }
+        }
     },
 
     
-    getRepairXY : function(e, data){
-        return data.node.ui.getDDRepairXY();
+    onAdd: function(ds, records, index) {
+        this.callParent(arguments);
+        this.doStripeRows(index);
     },
 
     
-    onEndDrag : function(data, e){
-        this.tree.eventModel.enable.defer(100, this.tree.eventModel);
-        this.tree.fireEvent("enddrag", this.tree, data.node, e);
+    onRemove: function(ds, records, index) {
+        this.callParent(arguments);
+        this.doStripeRows(index);
     },
 
-    
-    onValidDrop : function(dd, e, id){
-        this.tree.fireEvent("dragdrop", this.tree, this.dragData.node, dd, e);
-        this.hideProxy();
+    onUpdate: function(ds, record, operation) {
+        var index = ds.indexOf(record);
+        this.callParent(arguments);
+        this.doStripeRows(index, index);
     },
 
     
-    beforeInvalidDrop : function(e, id){
+    doStripeRows: function(startRow, endRow) {
         
-        var sm = this.tree.getSelectionModel();
-        sm.clearSelections();
-        sm.select(this.dragData.node);
+        if (this.stripeRows) {
+            var rows   = this.getNodes(startRow, endRow),
+                rowsLn = rows.length,
+                i      = 0,
+                row;
+
+            for (; i < rowsLn; i++) {
+                row = rows[i];
+                
+                row.className = row.className.replace(this.rowClsRe, ' ');
+                startRow++;
+                
+                if (startRow % 2 === 0) {
+                    row.className += (' ' + this.altRowCls);
+                }
+            }
+        }
     },
-    
-    
-    afterRepair : function(){
-        if (Ext.enableFx && this.tree.hlDrop) {
-            Ext.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
+
+    refresh: function(firstPass) {
+        this.callParent(arguments);
+        this.doStripeRows(0);
+        
+        var g = this.up('gridpanel');
+        if (g && this.invalidateScrollerOnRefresh) {
+            g.invalidateScroller();
         }
-        this.dragging = false;
     }
 });
-}
-Ext.tree.TreeEditor = function(tree, fc, config){
-    fc = fc || {};
-    var field = fc.events ? fc : new Ext.form.TextField(fc);
-    
-    Ext.tree.TreeEditor.superclass.constructor.call(this, field, config);
 
-    this.tree = tree;
 
-    if(!tree.rendered){
-        tree.on('render', this.initEditor, this);
-    }else{
-        this.initEditor(tree);
-    }
-};
+Ext.define('Ext.grid.Panel', {
+    extend: 'Ext.panel.Table',
+    requires: ['Ext.grid.View'],
+    alias: ['widget.gridpanel', 'widget.grid'],
+    alternateClassName: ['Ext.list.ListView', 'Ext.ListView', 'Ext.grid.GridPanel'],
+    viewType: 'gridview',
+
+    lockable: false,
 
-Ext.extend(Ext.tree.TreeEditor, Ext.Editor, {
-    
-    alignment: "l-l",
-    
-    autoSize: false,
     
-    hideEl : false,
     
-    cls: "x-small-editor x-tree-editor",
+    normalCfgCopy: ['invalidateScrollerOnRefresh', 'verticalScroller', 'verticalScrollDock', 'verticalScrollerType', 'scroll'],
+    lockedCfgCopy: ['invalidateScrollerOnRefresh'],
+
     
-    shim:false,
+
+    initComponent: function() {
+        var me = this;
+
+        if (me.columnLines) {
+            me.setColumnLines(me.columnLines);
+        }
+
+        me.callParent();
+    },
+
+    setColumnLines: function(show) {
+        var me = this,
+            method = (show) ? 'addClsWithUI' : 'removeClsWithUI';
+
+        me[method]('with-col-lines');
+    }
+});
+
+
+
+
+
+
+
+
+
+
+Ext.define('Ext.grid.RowEditor', {
+    extend: 'Ext.form.Panel',
+    requires: [
+        'Ext.tip.ToolTip',
+        'Ext.util.HashMap',
+        'Ext.util.KeyNav'
+    ],
+
+    saveBtnText  : 'Update',
+    cancelBtnText: 'Cancel',
+    errorsText: 'Errors',
+    dirtyText: 'You need to commit or cancel your changes',
+
+    lastScrollLeft: 0,
+    lastScrollTop: 0,
+
+    border: false,
     
-    shadow:"frame",
     
-    maxWidth: 250,
     
-    editDelay : 350,
+    hideMode: 'offsets',
 
-    initEditor : function(tree){
-        tree.on({
-            scope      : this,
-            beforeclick: this.beforeNodeClick,
-            dblclick   : this.onNodeDblClick
-        });
+    initComponent: function() {
+        var me = this,
+            form;
+
+        me.cls = Ext.baseCSSPrefix + 'grid-row-editor';
+
+        me.layout = {
+            type: 'hbox',
+            align: 'middle'
+        };
+
+        
         
-        this.on({
-            scope          : this,
-            complete       : this.updateNode,
-            beforestartedit: this.fitToTree,
-            specialkey     : this.onSpecialKey
+        me.columns = Ext.create('Ext.util.HashMap');
+        me.columns.getKey = function(columnHeader) {
+            var f;
+            if (columnHeader.getEditor) {
+                f = columnHeader.getEditor();
+                if (f) {
+                    return f.id;
+                }
+            }
+            return columnHeader.id;
+        };
+        me.mon(me.columns, {
+            add: me.onFieldAdd,
+            remove: me.onFieldRemove,
+            replace: me.onFieldReplace,
+            scope: me
         });
+
+        me.callParent(arguments);
+
+        if (me.fields) {
+            me.setField(me.fields);
+            delete me.fields;
+        }
+
+        form = me.getForm();
+        form.trackResetOnLoad = true;
+    },
+
+    onFieldChange: function() {
+        var me = this,
+            form = me.getForm(),
+            valid = form.isValid();
+        if (me.errorSummary && me.isVisible()) {
+            me[valid ? 'hideToolTip' : 'showToolTip']();
+        }
+        if (me.floatingButtons) {
+            me.floatingButtons.child('#update').setDisabled(!valid);
+        }
+        me.isValid = valid;
+    },
+
+    afterRender: function() {
+        var me = this,
+            plugin = me.editingPlugin;
+
+        me.callParent(arguments);
+        me.mon(me.renderTo, 'scroll', me.onCtScroll, me, { buffer: 100 });
+
         
-        this.on('startedit', this.bindScroll, this, {delay:10});
+        me.mon(me.el, {
+            click: Ext.emptyFn,
+            stopPropagation: true
+        });
+
+        me.el.swallowEvent([
+            'keypress',
+            'keydown'
+        ]);
+
+        me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
+            enter: plugin.completeEdit,
+            esc: plugin.onEscKey,
+            scope: plugin
+        });
+
+        me.mon(plugin.view, {
+            beforerefresh: me.onBeforeViewRefresh,
+            refresh: me.onViewRefresh,
+            scope: me
+        });
     },
 
-    
-    fitToTree : function(ed, el){
-        var td = this.tree.getTreeEl().dom, nd = el.dom;
-        if(td.scrollLeft >  nd.offsetLeft){ 
-            td.scrollLeft = nd.offsetLeft;
+    onBeforeViewRefresh: function(view) {
+        var me = this,
+            viewDom = view.el.dom;
+
+        if (me.el.dom.parentNode === viewDom) {
+            viewDom.removeChild(me.el.dom);
         }
-        var w = Math.min(
-                this.maxWidth,
-                (td.clientWidth > 20 ? td.clientWidth : td.offsetWidth) - Math.max(0, nd.offsetLeft-td.scrollLeft) - 5);
-        this.setSize(w, '');
     },
 
-    
-    triggerEdit : function(node, defer){
-        this.completeEdit();
-               if(node.attributes.editable !== false){
-           
-                       this.editNode = node;
-            if(this.tree.autoScroll){
-                Ext.fly(node.ui.getEl()).scrollIntoView(this.tree.body);
-            }
-            var value = node.text || '';
-            if (!Ext.isGecko && Ext.isEmpty(node.text)){
-                node.setText('&#160;');
+    onViewRefresh: function(view) {
+        var me = this,
+            viewDom = view.el.dom,
+            context = me.context,
+            idx;
+
+        viewDom.appendChild(me.el.dom);
+
+        
+        if (context && (idx = context.store.indexOf(context.record)) >= 0) {
+            context.row = view.getNode(idx);
+            me.reposition();
+            if (me.tooltip && me.tooltip.isVisible()) {
+                me.tooltip.setTarget(context.row);
             }
-            this.autoEditTimer = this.startEdit.defer(this.editDelay, this, [node.ui.textNode, value]);
-            return false;
+        } else {
+            me.editingPlugin.cancelEdit();
         }
     },
 
-    
-    bindScroll : function(){
-        this.tree.getTreeEl().on('scroll', this.cancelEdit, this);
-    },
+    onCtScroll: function(e, target) {
+        var me = this,
+            scrollTop  = target.scrollTop,
+            scrollLeft = target.scrollLeft;
 
-    
-    beforeNodeClick : function(node, e){
-        clearTimeout(this.autoEditTimer);
-        if(this.tree.getSelectionModel().isSelected(node)){
-            e.stopEvent();
-            return this.triggerEdit(node);
+        if (scrollTop !== me.lastScrollTop) {
+            me.lastScrollTop = scrollTop;
+            if ((me.tooltip && me.tooltip.isVisible()) || me.hiddenTip) {
+                me.repositionTip();
+            }
+        }
+        if (scrollLeft !== me.lastScrollLeft) {
+            me.lastScrollLeft = scrollLeft;
+            me.reposition();
         }
     },
 
-    onNodeDblClick : function(node, e){
-        clearTimeout(this.autoEditTimer);
+    onColumnAdd: function(column) {
+        this.setField(column);
     },
 
-    
-    updateNode : function(ed, value){
-        this.tree.getTreeEl().un('scroll', this.cancelEdit, this);
-        this.editNode.setText(value);
+    onColumnRemove: function(column) {
+        this.columns.remove(column);
     },
 
-    
-    onHide : function(){
-        Ext.tree.TreeEditor.superclass.onHide.call(this);
-        if(this.editNode){
-            this.editNode.ui.focus.defer(50, this.editNode.ui);
+    onColumnResize: function(column, width) {
+        column.getEditor().setWidth(width - 2);
+        if (this.isVisible()) {
+            this.reposition();
         }
     },
 
-    
-    onSpecialKey : function(field, e){
-        var k = e.getKey();
-        if(k == e.ESC){
-            e.stopEvent();
-            this.cancelEdit();
-        }else if(k == e.ENTER && !e.hasModifier()){
-            e.stopEvent();
-            this.completeEdit();
+    onColumnHide: function(column) {
+        column.getEditor().hide();
+        if (this.isVisible()) {
+            this.reposition();
         }
     },
-    
-    onDestroy : function(){
-        clearTimeout(this.autoEditTimer);
-        Ext.tree.TreeEditor.superclass.onDestroy.call(this);
-        var tree = this.tree;
-        tree.un('beforeclick', this.beforeNodeClick, this);
-        tree.un('dblclick', this.onNodeDblClick, this);
-    }
-});
-
-var swfobject = function() {
-    
-    var UNDEF = "undefined",
-        OBJECT = "object",
-        SHOCKWAVE_FLASH = "Shockwave Flash",
-        SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
-        FLASH_MIME_TYPE = "application/x-shockwave-flash",
-        EXPRESS_INSTALL_ID = "SWFObjectExprInst",
-        ON_READY_STATE_CHANGE = "onreadystatechange",
-        
-        win = window,
-        doc = document,
-        nav = navigator,
-        
-        plugin = false,
-        domLoadFnArr = [main],
-        regObjArr = [],
-        objIdArr = [],
-        listenersArr = [],
-        storedAltContent,
-        storedAltContentId,
-        storedCallbackFn,
-        storedCallbackObj,
-        isDomLoaded = false,
-        isExpressInstallActive = false,
-        dynamicStylesheet,
-        dynamicStylesheetMedia,
-        autoHideShow = true,
-    
-      
-    ua = function() {
-        var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
-            u = nav.userAgent.toLowerCase(),
-            p = nav.platform.toLowerCase(),
-            windows = p ? /win/.test(p) : /win/.test(u),
-            mac = p ? /mac/.test(p) : /mac/.test(u),
-            webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, 
-            ie = !+"\v1", 
-            playerVersion = [0,0,0],
-            d = null;
-        if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
-            d = nav.plugins[SHOCKWAVE_FLASH].description;
-            if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { 
-                plugin = true;
-                ie = false; 
-                d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
-                playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
-                playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
-                playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
-            }
-        }
-        else if (typeof win.ActiveXObject != UNDEF) {
-            try {
-                var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
-                if (a) { 
-                    d = a.GetVariable("$version");
-                    if (d) {
-                        ie = true; 
-                        d = d.split(" ")[1].split(",");
-                        playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
-                    }
-                }
-            }
-            catch(e) {}
-        }
-        return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
-    }(),
-    
-     
-    onDomLoad = function() {
-        if (!ua.w3) { return; }
-        if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { 
-            callDomLoadFunctions();
-        }
-        if (!isDomLoaded) {
-            if (typeof doc.addEventListener != UNDEF) {
-                doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
-            }       
-            if (ua.ie && ua.win) {
-                doc.attachEvent(ON_READY_STATE_CHANGE, function() {
-                    if (doc.readyState == "complete") {
-                        doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
-                        callDomLoadFunctions();
-                    }
-                });
-                if (win == top) { 
-                    (function(){
-                        if (isDomLoaded) { return; }
-                        try {
-                            doc.documentElement.doScroll("left");
-                        }
-                        catch(e) {
-                            setTimeout(arguments.callee, 0);
-                            return;
-                        }
-                        callDomLoadFunctions();
-                    })();
-                }
-            }
-            if (ua.wk) {
-                (function(){
-                    if (isDomLoaded) { return; }
-                    if (!/loaded|complete/.test(doc.readyState)) {
-                        setTimeout(arguments.callee, 0);
-                        return;
-                    }
-                    callDomLoadFunctions();
-                })();
-            }
-            addLoadEvent(callDomLoadFunctions);
-        }
-    }();
-    
-    function callDomLoadFunctions() {
-        if (isDomLoaded) { return; }
-        try { 
-            var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
-            t.parentNode.removeChild(t);
-        }
-        catch (e) { return; }
-        isDomLoaded = true;
-        var dl = domLoadFnArr.length;
-        for (var i = 0; i < dl; i++) {
-            domLoadFnArr[i]();
-        }
-    }
-    
-    function addDomLoadEvent(fn) {
-        if (isDomLoaded) {
-            fn();
-        }
-        else { 
-            domLoadFnArr[domLoadFnArr.length] = fn; 
-        }
-    }
-    
-    
-    function addLoadEvent(fn) {
-        if (typeof win.addEventListener != UNDEF) {
-            win.addEventListener("load", fn, false);
-        }
-        else if (typeof doc.addEventListener != UNDEF) {
-            doc.addEventListener("load", fn, false);
-        }
-        else if (typeof win.attachEvent != UNDEF) {
-            addListener(win, "onload", fn);
-        }
-        else if (typeof win.onload == "function") {
-            var fnOld = win.onload;
-            win.onload = function() {
-                fnOld();
-                fn();
-            };
-        }
-        else {
-            win.onload = fn;
-        }
-    }
-    
-    
-    function main() { 
-        if (plugin) {
-            testPlayerVersion();
-        }
-        else {
-            matchVersions();
-        }
-    }
-    
-    
-    function testPlayerVersion() {
-        var b = doc.getElementsByTagName("body")[0];
-        var o = createElement(OBJECT);
-        o.setAttribute("type", FLASH_MIME_TYPE);
-        var t = b.appendChild(o);
-        if (t) {
-            var counter = 0;
-            (function(){
-                if (typeof t.GetVariable != UNDEF) {
-                    var d = t.GetVariable("$version");
-                    if (d) {
-                        d = d.split(" ")[1].split(",");
-                        ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
-                    }
-                }
-                else if (counter < 10) {
-                    counter++;
-                    setTimeout(arguments.callee, 10);
-                    return;
-                }
-                b.removeChild(o);
-                t = null;
-                matchVersions();
-            })();
-        }
-        else {
-            matchVersions();
-        }
-    }
-    
-    
-    function matchVersions() {
-        var rl = regObjArr.length;
-        if (rl > 0) {
-            for (var i = 0; i < rl; i++) { 
-                var id = regObjArr[i].id;
-                var cb = regObjArr[i].callbackFn;
-                var cbObj = {success:false, id:id};
-                if (ua.pv[0] > 0) {
-                    var obj = getElementById(id);
-                    if (obj) {
-                        if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { 
-                            setVisibility(id, true);
-                            if (cb) {
-                                cbObj.success = true;
-                                cbObj.ref = getObjectById(id);
-                                cb(cbObj);
-                            }
-                        }
-                        else if (regObjArr[i].expressInstall && canExpressInstall()) { 
-                            var att = {};
-                            att.data = regObjArr[i].expressInstall;
-                            att.width = obj.getAttribute("width") || "0";
-                            att.height = obj.getAttribute("height") || "0";
-                            if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
-                            if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
-                            
-                            var par = {};
-                            var p = obj.getElementsByTagName("param");
-                            var pl = p.length;
-                            for (var j = 0; j < pl; j++) {
-                                if (p[j].getAttribute("name").toLowerCase() != "movie") {
-                                    par[p[j].getAttribute("name")] = p[j].getAttribute("value");
-                                }
-                            }
-                            showExpressInstall(att, par, id, cb);
-                        }
-                        else { 
-                            displayAltContent(obj);
-                            if (cb) { cb(cbObj); }
-                        }
-                    }
-                }
-                else {  
-                    setVisibility(id, true);
-                    if (cb) {
-                        var o = getObjectById(id); 
-                        if (o && typeof o.SetVariable != UNDEF) { 
-                            cbObj.success = true;
-                            cbObj.ref = o;
-                        }
-                        cb(cbObj);
-                    }
-                }
-            }
-        }
-    }
-    
-    function getObjectById(objectIdStr) {
-        var r = null;
-        var o = getElementById(objectIdStr);
-        if (o && o.nodeName == "OBJECT") {
-            if (typeof o.SetVariable != UNDEF) {
-                r = o;
-            }
-            else {
-                var n = o.getElementsByTagName(OBJECT)[0];
-                if (n) {
-                    r = n;
-                }
-            }
-        }
-        return r;
-    }
-    
-    
-    function canExpressInstall() {
-        return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
-    }
-    
-    
-    function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
-        isExpressInstallActive = true;
-        storedCallbackFn = callbackFn || null;
-        storedCallbackObj = {success:false, id:replaceElemIdStr};
-        var obj = getElementById(replaceElemIdStr);
-        if (obj) {
-            if (obj.nodeName == "OBJECT") { 
-                storedAltContent = abstractAltContent(obj);
-                storedAltContentId = null;
-            }
-            else { 
-                storedAltContent = obj;
-                storedAltContentId = replaceElemIdStr;
-            }
-            att.id = EXPRESS_INSTALL_ID;
-            if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
-            if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
-            doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
-            var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
-                fv = "MMredirectURL=" + win.location.toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
-            if (typeof par.flashvars != UNDEF) {
-                par.flashvars += "&" + fv;
-            }
-            else {
-                par.flashvars = fv;
-            }
-            
-            
-            if (ua.ie && ua.win && obj.readyState != 4) {
-                var newObj = createElement("div");
-                replaceElemIdStr += "SWFObjectNew";
-                newObj.setAttribute("id", replaceElemIdStr);
-                obj.parentNode.insertBefore(newObj, obj); 
-                obj.style.display = "none";
-                (function(){
-                    if (obj.readyState == 4) {
-                        obj.parentNode.removeChild(obj);
-                    }
-                    else {
-                        setTimeout(arguments.callee, 10);
-                    }
-                })();
-            }
-            createSWF(att, par, replaceElemIdStr);
-        }
-    }
-    
-    
-    function displayAltContent(obj) {
-        if (ua.ie && ua.win && obj.readyState != 4) {
-            
-            
-            var el = createElement("div");
-            obj.parentNode.insertBefore(el, obj); 
-            el.parentNode.replaceChild(abstractAltContent(obj), el);
-            obj.style.display = "none";
-            (function(){
-                if (obj.readyState == 4) {
-                    obj.parentNode.removeChild(obj);
-                }
-                else {
-                    setTimeout(arguments.callee, 10);
-                }
-            })();
-        }
-        else {
-            obj.parentNode.replaceChild(abstractAltContent(obj), obj);
-        }
-    } 
 
-    function abstractAltContent(obj) {
-        var ac = createElement("div");
-        if (ua.win && ua.ie) {
-            ac.innerHTML = obj.innerHTML;
-        }
-        else {
-            var nestedObj = obj.getElementsByTagName(OBJECT)[0];
-            if (nestedObj) {
-                var c = nestedObj.childNodes;
-                if (c) {
-                    var cl = c.length;
-                    for (var i = 0; i < cl; i++) {
-                        if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
-                            ac.appendChild(c[i].cloneNode(true));
-                        }
-                    }
-                }
-            }
-        }
-        return ac;
-    }
-    
-    
-    function createSWF(attObj, parObj, id) {
-        var r, el = getElementById(id);
-        if (ua.wk && ua.wk < 312) { return r; }
-        if (el) {
-            if (typeof attObj.id == UNDEF) { 
-                attObj.id = id;
-            }
-            if (ua.ie && ua.win) { 
-                var att = "";
-                for (var i in attObj) {
-                    if (attObj[i] != Object.prototype[i]) { 
-                        if (i.toLowerCase() == "data") {
-                            parObj.movie = attObj[i];
-                        }
-                        else if (i.toLowerCase() == "styleclass") { 
-                            att += ' class="' + attObj[i] + '"';
-                        }
-                        else if (i.toLowerCase() != "classid") {
-                            att += ' ' + i + '="' + attObj[i] + '"';
-                        }
-                    }
-                }
-                var par = "";
-                for (var j in parObj) {
-                    if (parObj[j] != Object.prototype[j]) { 
-                        par += '<param name="' + j + '" value="' + parObj[j] + '" />';
-                    }
-                }
-                el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
-                objIdArr[objIdArr.length] = attObj.id; 
-                r = getElementById(attObj.id);  
-            }
-            else { 
-                var o = createElement(OBJECT);
-                o.setAttribute("type", FLASH_MIME_TYPE);
-                for (var m in attObj) {
-                    if (attObj[m] != Object.prototype[m]) { 
-                        if (m.toLowerCase() == "styleclass") { 
-                            o.setAttribute("class", attObj[m]);
-                        }
-                        else if (m.toLowerCase() != "classid") { 
-                            o.setAttribute(m, attObj[m]);
-                        }
-                    }
-                }
-                for (var n in parObj) {
-                    if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { 
-                        createObjParam(o, n, parObj[n]);
-                    }
-                }
-                el.parentNode.replaceChild(o, el);
-                r = o;
-            }
-        }
-        return r;
-    }
-    
-    function createObjParam(el, pName, pValue) {
-        var p = createElement("param");
-        p.setAttribute("name", pName);  
-        p.setAttribute("value", pValue);
-        el.appendChild(p);
-    }
-    
-    
-    function removeSWF(id) {
-        var obj = getElementById(id);
-        if (obj && obj.nodeName == "OBJECT") {
-            if (ua.ie && ua.win) {
-                obj.style.display = "none";
-                (function(){
-                    if (obj.readyState == 4) {
-                        removeObjectInIE(id);
-                    }
-                    else {
-                        setTimeout(arguments.callee, 10);
-                    }
-                })();
-            }
-            else {
-                obj.parentNode.removeChild(obj);
-            }
+    onColumnShow: function(column) {
+        var field = column.getEditor();
+        field.setWidth(column.getWidth() - 2).show();
+        if (this.isVisible()) {
+            this.reposition();
         }
-    }
-    
-    function removeObjectInIE(id) {
-        var obj = getElementById(id);
-        if (obj) {
-            for (var i in obj) {
-                if (typeof obj[i] == "function") {
-                    obj[i] = null;
-                }
-            }
-            obj.parentNode.removeChild(obj);
+    },
+
+    onColumnMove: function(column, fromIdx, toIdx) {
+        var field = column.getEditor();
+        if (this.items.indexOf(field) != toIdx) {
+            this.move(fromIdx, toIdx);
         }
-    }
-    
-    
-    function getElementById(id) {
-        var el = null;
-        try {
-            el = doc.getElementById(id);
+    },
+
+    onFieldAdd: function(map, fieldId, column) {
+        var me = this,
+            colIdx = me.editingPlugin.grid.headerCt.getHeaderIndex(column),
+            field = column.getEditor({ xtype: 'displayfield' });
+
+        me.insert(colIdx, field);
+    },
+
+    onFieldRemove: function(map, fieldId, column) {
+        var me = this,
+            field = column.getEditor(),
+            fieldEl = field.el;
+        me.remove(field, false);
+        if (fieldEl) {
+            fieldEl.remove();
         }
-        catch (e) {}
-        return el;
-    }
-    
-    function createElement(el) {
-        return doc.createElement(el);
-    }
-    
-      
-    function addListener(target, eventType, fn) {
-        target.attachEvent(eventType, fn);
-        listenersArr[listenersArr.length] = [target, eventType, fn];
-    }
-    
-    
-    function hasPlayerVersion(rv) {
-        var pv = ua.pv, v = rv.split(".");
-        v[0] = parseInt(v[0], 10);
-        v[1] = parseInt(v[1], 10) || 0; 
-        v[2] = parseInt(v[2], 10) || 0;
-        return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
-    }
-    
-      
-    function createCSS(sel, decl, media, newStyle) {
-        if (ua.ie && ua.mac) { return; }
-        var h = doc.getElementsByTagName("head")[0];
-        if (!h) { return; } 
-        var m = (media && typeof media == "string") ? media : "screen";
-        if (newStyle) {
-            dynamicStylesheet = null;
-            dynamicStylesheetMedia = null;
+    },
+
+    onFieldReplace: function(map, fieldId, column, oldColumn) {
+        var me = this;
+        me.onFieldRemove(map, fieldId, oldColumn);
+    },
+
+    clearFields: function() {
+        var me = this,
+            map = me.columns;
+        map.each(function(fieldId) {
+            map.removeAtKey(fieldId);
+        });
+    },
+
+    getFloatingButtons: function() {
+        var me = this,
+            cssPrefix = Ext.baseCSSPrefix,
+            btnsCss = cssPrefix + 'grid-row-editor-buttons',
+            plugin = me.editingPlugin,
+            btns;
+
+        if (!me.floatingButtons) {
+            btns = me.floatingButtons = Ext.create('Ext.Container', {
+                renderTpl: [
+                    '<div class="{baseCls}-ml"></div>',
+                    '<div class="{baseCls}-mr"></div>',
+                    '<div class="{baseCls}-bl"></div>',
+                    '<div class="{baseCls}-br"></div>',
+                    '<div class="{baseCls}-bc"></div>'
+                ],
+
+                renderTo: me.el,
+                baseCls: btnsCss,
+                layout: {
+                    type: 'hbox',
+                    align: 'middle'
+                },
+                defaults: {
+                    margins: '0 1 0 1'
+                },
+                items: [{
+                    itemId: 'update',
+                    flex: 1,
+                    xtype: 'button',
+                    handler: plugin.completeEdit,
+                    scope: plugin,
+                    text: me.saveBtnText,
+                    disabled: !me.isValid
+                }, {
+                    flex: 1,
+                    xtype: 'button',
+                    handler: plugin.cancelEdit,
+                    scope: plugin,
+                    text: me.cancelBtnText
+                }]
+            });
+
+            
+            me.mon(btns.el, {
+                
+                
+                mousedown: Ext.emptyFn,
+                click: Ext.emptyFn,
+                stopEvent: true
+            });
         }
-        if (!dynamicStylesheet || dynamicStylesheetMedia != m) { 
+        return me.floatingButtons;
+    },
+
+    reposition: function(animateConfig) {
+        var me = this,
+            context = me.context,
+            row = context && Ext.get(context.row),
+            btns = me.getFloatingButtons(),
+            btnEl = btns.el,
+            grid = me.editingPlugin.grid,
+            viewEl = grid.view.el,
+            scroller = grid.verticalScroller,
+
             
-            var s = createElement("style");
-            s.setAttribute("type", "text/css");
-            s.setAttribute("media", m);
-            dynamicStylesheet = h.appendChild(s);
-            if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
-                dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
-            }
-            dynamicStylesheetMedia = m;
-        }
+            
+            mainBodyWidth = grid.headerCt.getFullWidth(),
+            scrollerWidth = grid.getWidth(),
+
+            
+            
+            width = Math.min(mainBodyWidth, scrollerWidth),
+            scrollLeft = grid.view.el.dom.scrollLeft,
+            btnWidth = btns.getWidth(),
+            left = (width - btnWidth) / 2 + scrollLeft,
+            y, rowH, newHeight,
+
+            invalidateScroller = function() {
+                if (scroller) {
+                    scroller.invalidate();
+                    btnEl.scrollIntoView(viewEl, false);
+                }
+                if (animateConfig && animateConfig.callback) {
+                    animateConfig.callback.call(animateConfig.scope || me);
+                }
+            };
+
         
-        if (ua.ie && ua.win) {
-            if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
-                dynamicStylesheet.addRule(sel, decl);
+        if (row && Ext.isElement(row.dom)) {
+            
+            
+            row.scrollIntoView(viewEl, false);
+
+            
+            
+            
+            y = row.getXY()[1] - 5;
+            rowH = row.getHeight();
+            newHeight = rowH + 10;
+
+            
+            
+            
+            
+            if (Ext.isIE) {
+                newHeight += 2;
             }
-        }
-        else {
-            if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
-                dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
+
+            
+            if (me.getHeight() != newHeight) {
+                me.setHeight(newHeight);
+                me.el.setLeft(0);
             }
-        }
-    }
-    
-    function setVisibility(id, isVisible) {
-        if (!autoHideShow) { return; }
-        var v = isVisible ? "visible" : "hidden";
-        if (isDomLoaded && getElementById(id)) {
-            getElementById(id).style.visibility = v;
-        }
-        else {
-            createCSS("#" + id, "visibility:" + v);
-        }
-    }
 
-    
-    function urlEncodeIfNecessary(s) {
-        var regex = /[\\\"<>\.;]/;
-        var hasBadChars = regex.exec(s) != null;
-        return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
-    }
-    
-    
-    var cleanup = function() {
-        if (ua.ie && ua.win) {
-            window.attachEvent("onunload", function() {
-                
-                var ll = listenersArr.length;
-                for (var i = 0; i < ll; i++) {
-                    listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
-                }
-                
-                var il = objIdArr.length;
-                for (var j = 0; j < il; j++) {
-                    removeSWF(objIdArr[j]);
-                }
-                
-                for (var k in ua) {
-                    ua[k] = null;
-                }
-                ua = null;
-                for (var l in swfobject) {
-                    swfobject[l] = null;
-                }
-                swfobject = null;
-            });
-        }
-    }();
-    
-    return {
-         
-        registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
-            if (ua.w3 && objectIdStr && swfVersionStr) {
-                var regObj = {};
-                regObj.id = objectIdStr;
-                regObj.swfVersion = swfVersionStr;
-                regObj.expressInstall = xiSwfUrlStr;
-                regObj.callbackFn = callbackFn;
-                regObjArr[regObjArr.length] = regObj;
-                setVisibility(objectIdStr, false);
-            }
-            else if (callbackFn) {
-                callbackFn({success:false, id:objectIdStr});
-            }
-        },
-        
-        getObjectById: function(objectIdStr) {
-            if (ua.w3) {
-                return getObjectById(objectIdStr);
-            }
-        },
-        
-        embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
-            var callbackObj = {success:false, id:replaceElemIdStr};
-            if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
-                setVisibility(replaceElemIdStr, false);
-                addDomLoadEvent(function() {
-                    widthStr += ""; 
-                    heightStr += "";
-                    var att = {};
-                    if (attObj && typeof attObj === OBJECT) {
-                        for (var i in attObj) { 
-                            att[i] = attObj[i];
-                        }
-                    }
-                    att.data = swfUrlStr;
-                    att.width = widthStr;
-                    att.height = heightStr;
-                    var par = {}; 
-                    if (parObj && typeof parObj === OBJECT) {
-                        for (var j in parObj) { 
-                            par[j] = parObj[j];
-                        }
-                    }
-                    if (flashvarsObj && typeof flashvarsObj === OBJECT) {
-                        for (var k in flashvarsObj) { 
-                            if (typeof par.flashvars != UNDEF) {
-                                par.flashvars += "&" + k + "=" + flashvarsObj[k];
-                            }
-                            else {
-                                par.flashvars = k + "=" + flashvarsObj[k];
-                            }
-                        }
-                    }
-                    if (hasPlayerVersion(swfVersionStr)) { 
-                        var obj = createSWF(att, par, replaceElemIdStr);
-                        if (att.id == replaceElemIdStr) {
-                            setVisibility(replaceElemIdStr, true);
+            if (animateConfig) {
+                var animObj = {
+                    to: {
+                        y: y
+                    },
+                    duration: animateConfig.duration || 125,
+                    listeners: {
+                        afteranimate: function() {
+                            invalidateScroller();
+                            y = row.getXY()[1] - 5;
+                            me.el.setY(y);
                         }
-                        callbackObj.success = true;
-                        callbackObj.ref = obj;
-                    }
-                    else if (xiSwfUrlStr && canExpressInstall()) { 
-                        att.data = xiSwfUrlStr;
-                        showExpressInstall(att, par, replaceElemIdStr, callbackFn);
-                        return;
                     }
-                    else { 
-                        setVisibility(replaceElemIdStr, true);
-                    }
-                    if (callbackFn) { callbackFn(callbackObj); }
-                });
+                };
+                me.animate(animObj);
+            } else {
+                me.el.setY(y);
+                invalidateScroller();
             }
-            else if (callbackFn) { callbackFn(callbackObj); }
-        },
-        
-        switchOffAutoHideShow: function() {
-            autoHideShow = false;
-        },
-        
-        ua: ua,
-        
-        getFlashPlayerVersion: function() {
-            return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
-        },
-        
-        hasFlashPlayerVersion: hasPlayerVersion,
+        }
+        if (me.getWidth() != mainBodyWidth) {
+            me.setWidth(mainBodyWidth);
+        }
+        btnEl.setLeft(left);
+    },
+
+    getEditor: function(fieldInfo) {
+        var me = this;
+
+        if (Ext.isNumber(fieldInfo)) {
+            
+            
+            
+            return me.query('>[isFormField]')[fieldInfo];
+        } else if (fieldInfo instanceof Ext.grid.column.Column) {
+            return fieldInfo.getEditor();
+        }
+    },
+
+    removeField: function(field) {
+        var me = this;
+
         
-        createSWF: function(attObj, parObj, replaceElemIdStr) {
-            if (ua.w3) {
-                return createSWF(attObj, parObj, replaceElemIdStr);
-            }
-            else {
-                return undefined;
-            }
-        },
+        field = me.getEditor(field);
+        me.mun(field, 'validitychange', me.onValidityChange, me);
+
         
-        showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
-            if (ua.w3 && canExpressInstall()) {
-                showExpressInstall(att, par, replaceElemIdStr, callbackFn);
-            }
-        },
         
-        removeSWF: function(objElemIdStr) {
-            if (ua.w3) {
-                removeSWF(objElemIdStr);
-            }
-        },
+        me.columns.removeKey(field.id);
+    },
+
+    setField: function(column) {
+        var me = this,
+            field;
+
+        if (Ext.isArray(column)) {
+            Ext.Array.forEach(column, me.setField, me);
+            return;
+        }
+
         
-        createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
-            if (ua.w3) {
-                createCSS(selStr, declStr, mediaStr, newStyleBoolean);
+        field = column.getEditor(null, {
+            xtype: 'displayfield',
+            
+            
+            getModelData: function() {
+                return null;
             }
-        },
-        
-        addDomLoadEvent: addDomLoadEvent,
-        
-        addLoadEvent: addLoadEvent,
+        });
+        field.margins = '0 0 0 2';
+        field.setWidth(column.getDesiredWidth() - 2);
+        me.mon(field, 'change', me.onFieldChange, me);
+
         
-        getQueryParamValue: function(param) {
-            var q = doc.location.search || doc.location.hash;
-            if (q) {
-                if (/\?/.test(q)) { q = q.split("?")[1]; } 
-                if (param == null) {
-                    return urlEncodeIfNecessary(q);
-                }
-                var pairs = q.split("&");
-                for (var i = 0; i < pairs.length; i++) {
-                    if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
-                        return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
-                    }
-                }
-            }
-            return "";
-        },
         
+        me.columns.add(field.id, column);
+        if (column.hidden) {
+            me.onColumnHide(column);
+        }
+        if (me.isVisible() && me.context) {
+            me.renderColumnData(field, me.context.record);
+        }
+    },
+
+    loadRecord: function(record) {
+        var me = this,
+            form = me.getForm();
+        form.loadRecord(record);
+        if (form.isValid()) {
+            me.hideToolTip();
+        } else {
+            me.showToolTip();
+        }
+
         
-        expressInstallCallback: function() {
-            if (isExpressInstallActive) {
-                var obj = getElementById(EXPRESS_INSTALL_ID);
-                if (obj && storedAltContent) {
-                    obj.parentNode.replaceChild(storedAltContent, obj);
-                    if (storedAltContentId) {
-                        setVisibility(storedAltContentId, true);
-                        if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
-                    }
-                    if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
-                }
-                isExpressInstallActive = false;
-            } 
+        Ext.Array.forEach(me.query('>displayfield'), function(field) {
+            me.renderColumnData(field, record);
+        }, me);
+    },
+
+    renderColumnData: function(field, record) {
+        var me = this,
+            grid = me.editingPlugin.grid,
+            headerCt = grid.headerCt,
+            view = grid.view,
+            store = view.store,
+            column = me.columns.get(field.id),
+            value = record.get(column.dataIndex);
+
+        
+        if (column.renderer) {
+            var metaData = { tdCls: '', style: '' },
+                rowIdx = store.indexOf(record),
+                colIdx = headerCt.getHeaderIndex(column);
+
+            value = column.renderer.call(
+                column.scope || headerCt.ownerCt,
+                value,
+                metaData,
+                record,
+                rowIdx,
+                colIdx,
+                store,
+                view
+            );
         }
-    };
-}();
 
-Ext.FlashComponent = Ext.extend(Ext.BoxComponent, {
-    
-    flashVersion : '9.0.115',
+        field.setRawValue(value);
+        field.resetOriginalValue();
+    },
 
-    
-    backgroundColor: '#ffffff',
+    beforeEdit: function() {
+        var me = this;
 
-    
-    wmode: 'opaque',
+        if (me.isVisible() && !me.autoCancel && me.isDirty()) {
+            me.showToolTip();
+            return false;
+        }
+    },
 
     
-    flashVars: undefined,
+    startEdit: function(record, columnHeader) {
+        var me = this,
+            grid = me.editingPlugin.grid,
+            view = grid.getView(),
+            store = grid.store,
+            context = me.context = Ext.apply(me.editingPlugin.context, {
+                view: grid.getView(),
+                store: store
+            });
 
-    
-    flashParams: undefined,
+        
+        context.grid.getSelectionModel().select(record);
 
-    
-    url: undefined,
-    swfId : undefined,
-    swfWidth: '100%',
-    swfHeight: '100%',
+        
+        me.loadRecord(record);
+
+        if (!me.isVisible()) {
+            me.show();
+            me.focusContextCell();
+        } else {
+            me.reposition({
+                callback: this.focusContextCell
+            });
+        }
+    },
 
     
-    expressInstall: false,
+    focusContextCell: function() {
+        var field = this.getEditor(this.context.colIdx);
+        if (field && field.focus) {
+            field.focus();
+        }
+    },
 
-    initComponent : function(){
-        Ext.FlashComponent.superclass.initComponent.call(this);
+    cancelEdit: function() {
+        var me = this,
+            form = me.getForm();
 
-        this.addEvents(
-            
-            'initialize'
-        );
+        me.hide();
+        form.clearInvalid();
+        form.reset();
     },
 
-    onRender : function(){
-        Ext.FlashComponent.superclass.onRender.apply(this, arguments);
+    completeEdit: function() {
+        var me = this,
+            form = me.getForm();
 
-        var params = Ext.apply({
-            allowScriptAccess: 'always',
-            bgcolor: this.backgroundColor,
-            wmode: this.wmode
-        }, this.flashParams), vars = Ext.apply({
-            allowedDomain: document.location.hostname,
-            YUISwfId: this.getId(),
-            YUIBridgeCallback: 'Ext.FlashEventProxy.onEvent'
-        }, this.flashVars);
+        if (!form.isValid()) {
+            return;
+        }
 
-        new swfobject.embedSWF(this.url, this.id, this.swfWidth, this.swfHeight, this.flashVersion,
-            this.expressInstall ? Ext.FlashComponent.EXPRESS_INSTALL_URL : undefined, vars, params);
+        form.updateRecord(me.context.record);
+        me.hide();
+        return true;
+    },
 
-        this.swf = Ext.getDom(this.id);
-        this.el = Ext.get(this.swf);
+    onShow: function() {
+        var me = this;
+        me.callParent(arguments);
+        me.reposition();
     },
 
-    getSwfId : function(){
-        return this.swfId || (this.swfId = "extswf" + (++Ext.Component.AUTO_ID));
+    onHide: function() {
+        var me = this;
+        me.callParent(arguments);
+        me.hideToolTip();
+        me.invalidateScroller();
+        if (me.context) {
+            me.context.view.focus();
+            me.context = null;
+        }
     },
 
-    getId : function(){
-        return this.id || (this.id = "extflashcmp" + (++Ext.Component.AUTO_ID));
+    isDirty: function() {
+        var me = this,
+            form = me.getForm();
+        return form.isDirty();
     },
 
-    onFlashEvent : function(e){
-        switch(e.type){
-            case "swfReady":
-                this.initSwf();
-                return;
-            case "log":
-                return;
+    getToolTip: function() {
+        var me = this,
+            tip;
+
+        if (!me.tooltip) {
+            tip = me.tooltip = Ext.createWidget('tooltip', {
+                cls: Ext.baseCSSPrefix + 'grid-row-editor-errors',
+                title: me.errorsText,
+                autoHide: false,
+                closable: true,
+                closeAction: 'disable',
+                anchor: 'left'
+            });
         }
-        e.component = this;
-        this.fireEvent(e.type.toLowerCase().replace(/event$/, ''), e);
+        return me.tooltip;
     },
 
-    initSwf : function(){
-        this.onSwfReady(!!this.isInitialized);
-        this.isInitialized = true;
-        this.fireEvent('initialize', this);
+    hideToolTip: function() {
+        var me = this,
+            tip = me.getToolTip();
+        if (tip.rendered) {
+            tip.disable();
+        }
+        me.hiddenTip = false;
     },
 
-    beforeDestroy: function(){
-        if(this.rendered){
-            swfobject.removeSWF(this.swf.id);
+    showToolTip: function() {
+        var me = this,
+            tip = me.getToolTip(),
+            context = me.context,
+            row = Ext.get(context.row),
+            viewEl = context.grid.view.el;
+
+        tip.setTarget(row);
+        tip.showAt([-10000, -10000]);
+        tip.body.update(me.getErrors());
+        tip.mouseOffset = [viewEl.getWidth() - row.getWidth() + me.lastScrollLeft + 15, 0];
+        me.repositionTip();
+        tip.doLayout();
+        tip.enable();
+    },
+
+    repositionTip: function() {
+        var me = this,
+            tip = me.getToolTip(),
+            context = me.context,
+            row = Ext.get(context.row),
+            viewEl = context.grid.view.el,
+            viewHeight = viewEl.getHeight(),
+            viewTop = me.lastScrollTop,
+            viewBottom = viewTop + viewHeight,
+            rowHeight = row.getHeight(),
+            rowTop = row.dom.offsetTop,
+            rowBottom = rowTop + rowHeight;
+
+        if (rowBottom > viewTop && rowTop < viewBottom) {
+            tip.show();
+            me.hiddenTip = false;
+        } else {
+            tip.hide();
+            me.hiddenTip = true;
         }
-        Ext.FlashComponent.superclass.beforeDestroy.call(this);
     },
 
-    onSwfReady : Ext.emptyFn
-});
+    getErrors: function() {
+        var me = this,
+            dirtyText = !me.autoCancel && me.isDirty() ? me.dirtyText + '<br />' : '',
+            errors = [];
+
+        Ext.Array.forEach(me.query('>[isFormField]'), function(field) {
+            errors = errors.concat(
+                Ext.Array.map(field.getErrors(), function(e) {
+                    return '<li>' + e + '</li>';
+                })
+            );
+        }, me);
 
+        return dirtyText + '<ul>' + errors.join('') + '</ul>';
+    },
 
-Ext.FlashComponent.EXPRESS_INSTALL_URL = 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf';
+    invalidateScroller: function() {
+        var me = this,
+            context = me.context,
+            scroller = context.grid.verticalScroller;
 
-Ext.reg('flash', Ext.FlashComponent);
-Ext.FlashEventProxy = {
-    onEvent : function(id, e){
-        var fp = Ext.getCmp(id);
-        if(fp){
-            fp.onFlashEvent(e);
-        }else{
-            arguments.callee.defer(10, this, [id, e]);
+        if (scroller) {
+            scroller.invalidate();
         }
     }
-};
+});
 
- Ext.chart.Chart = Ext.extend(Ext.FlashComponent, {
-    refreshBuffer: 100,
+Ext.define('Ext.grid.header.Container', {
+    extend: 'Ext.container.Container',
+    uses: [
+        'Ext.grid.ColumnLayout',
+        'Ext.grid.column.Column',
+        'Ext.menu.Menu',
+        'Ext.menu.CheckItem',
+        'Ext.menu.Separator',
+        'Ext.grid.plugin.HeaderResizer',
+        'Ext.grid.plugin.HeaderReorderer'
+    ],
+    border: true,
 
-    
+    alias: 'widget.headercontainer',
 
-    
-    chartStyle: {
-        padding: 10,
-        animationEnabled: true,
-        font: {
-            name: 'Tahoma',
-            color: 0x444444,
-            size: 11
-        },
-        dataTip: {
-            padding: 5,
-            border: {
-                color: 0x99bbe8,
-                size:1
-            },
-            background: {
-                color: 0xDAE7F6,
-                alpha: .9
-            },
-            font: {
-                name: 'Tahoma',
-                color: 0x15428B,
-                size: 10,
-                bold: true
-            }
-        }
-    },
+    baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
+    dock: 'top',
 
     
+    weight: 100,
+    defaultType: 'gridcolumn',
+    
+    defaultWidth: 100,
+
+
+    sortAscText: 'Sort Ascending',
+    sortDescText: 'Sort Descending',
+    sortClearText: 'Clear Sort',
+    columnsText: 'Columns',
+
+    lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last',
+    firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first',
+    headerOpenCls: Ext.baseCSSPrefix + 'column-header-open',
 
     
-    extraStyle: null,
+    triStateSort: false,
+
+    ddLock: false,
+
+    dragging: false,
 
     
-    seriesStyles: null,
 
     
-    disableCaching: Ext.isIE || Ext.isOpera,
-    disableCacheParam: '_dc',
+    sortable: true,
 
-    initComponent : function(){
-        Ext.chart.Chart.superclass.initComponent.call(this);
-        if(!this.url){
-            this.url = Ext.chart.Chart.CHART_URL;
+    initComponent: function() {
+        var me = this;
+
+        me.headerCounter = 0;
+        me.plugins = me.plugins || [];
+
+        
+        
+
+        
+        
+        if (!me.isHeader) {
+            me.resizer   = Ext.create('Ext.grid.plugin.HeaderResizer');
+            me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer');
+            if (!me.enableColumnResize) {
+                me.resizer.disable();
+            }
+            if (!me.enableColumnMove) {
+                me.reorderer.disable();
+            }
+            me.plugins.push(me.reorderer, me.resizer);
         }
-        if(this.disableCaching){
-            this.url = Ext.urlAppend(this.url, String.format('{0}={1}', this.disableCacheParam, new Date().getTime()));
+
+        
+        if (me.isHeader && !me.items) {
+            me.layout = 'auto';
         }
-        this.addEvents(
-            'itemmouseover',
-            'itemmouseout',
-            'itemclick',
-            'itemdoubleclick',
-            'itemdragstart',
-            'itemdrag',
-            'itemdragend',
+        
+        else {
+            me.layout = {
+                type: 'gridcolumn',
+                availableSpaceOffset: me.availableSpaceOffset,
+                align: 'stretchmax',
+                resetStretch: true
+            };
+        }
+        me.defaults = me.defaults || {};
+        Ext.applyIf(me.defaults, {
+            width: me.defaultWidth,
+            triStateSort: me.triStateSort,
+            sortable: me.sortable
+        });
+        me.callParent();
+        me.addEvents(
             
-            'beforerefresh',
+            'columnresize',
+
             
-            'refresh'
-        );
-        this.store = Ext.StoreMgr.lookup(this.store);
-    },
+            'headerclick',
 
-    
-     setStyle: function(name, value){
-         this.swf.setStyle(name, Ext.encode(value));
-     },
+            
+            'headertriggerclick',
 
-    
-    setStyles: function(styles){
-        this.swf.setStyles(Ext.encode(styles));
+            
+            'columnmove',
+            
+            'columnhide',
+            
+            'columnshow',
+            
+            'sortchange',
+            
+            'menucreate'
+        );
     },
 
+    onDestroy: function() {
+        Ext.destroy(this.resizer, this.reorderer);
+        this.callParent();
+    },
     
-    setSeriesStyles: function(styles){
-        this.seriesStyles = styles;
-        var s = [];
-        Ext.each(styles, function(style){
-            s.push(Ext.encode(style));
-        });
-        this.swf.setSeriesStyles(s);
+    applyDefaults: function(config){
+        
+        if (config && !config.isComponent && config.xtype == 'rownumberer') {
+            return config;
+        }
+        return this.callParent([config]);
     },
 
-    setCategoryNames : function(names){
-        this.swf.setCategoryNames(names);
-    },
+    applyColumnsState: function(columns) {
+        if (!columns || !columns.length) {
+            return;
+        }
+
+        var me = this,
+            i = 0,
+            index,
+            col;
+
+        Ext.each(columns, function (columnState) {
+            col = me.down('gridcolumn[headerId=' + columnState.id + ']');
+            if (col) {
+                index = me.items.indexOf(col);
+                if (i !== index) {
+                    me.moveHeader(index, i);
+                }
 
-    setLegendRenderer : function(fn, scope){
-        var chart = this;
-        scope = scope || chart;
-        chart.removeFnProxy(chart.legendFnName);
-        chart.legendFnName = chart.createFnProxy(function(name){
-            return fn.call(scope, name);
+                if (col.applyColumnState) {
+                    col.applyColumnState(columnState);
+                }
+                ++i;
+            }
         });
-        chart.swf.setLegendLabelFunction(chart.legendFnName);
     },
 
-    setTipRenderer : function(fn, scope){
-        var chart = this;
-        scope = scope || chart;
-        chart.removeFnProxy(chart.tipFnName);
-        chart.tipFnName = chart.createFnProxy(function(item, index, series){
-            var record = chart.store.getAt(index);
-            return fn.call(scope, chart, record, index, series);
+    getColumnsState: function () {
+        var me = this,
+            columns = [],
+            state;
+
+        me.items.each(function (col) {
+            state = col.getColumnState && col.getColumnState();
+            if (state) {
+                columns.push(state);
+            }
         });
-        chart.swf.setDataTipFunction(chart.tipFnName);
+
+        return columns;
     },
 
-    setSeries : function(series){
-        this.series = series;
-        this.refresh();
+    
+    
+    
+    onAdd: function(c) {
+        var me = this;
+        if (!c.headerId) {
+            c.headerId = c.initialConfig.id || ('h' + (++me.headerCounter));
+        }
+        me.callParent(arguments);
+        me.purgeCache();
     },
 
     
-    bindStore : function(store, initial){
-        if(!initial && this.store){
-            if(store !== this.store && this.store.autoDestroy){
-                this.store.destroy();
-            }else{
-                this.store.un("datachanged", this.refresh, this);
-                this.store.un("add", this.delayRefresh, this);
-                this.store.un("remove", this.delayRefresh, this);
-                this.store.un("update", this.delayRefresh, this);
-                this.store.un("clear", this.refresh, this);
+    
+    
+    onRemove: function(c) {
+        var me = this;
+        me.callParent(arguments);
+        me.purgeCache();
+    },
+
+    afterRender: function() {
+        this.callParent();
+        var store   = this.up('[store]').store,
+            sorters = store.sorters,
+            first   = sorters.first(),
+            hd;
+
+        if (first) {
+            hd = this.down('gridcolumn[dataIndex=' + first.property  +']');
+            if (hd) {
+                hd.setSortState(first.direction, false, true);
             }
         }
-        if(store){
-            store = Ext.StoreMgr.lookup(store);
-            store.on({
-                scope: this,
-                datachanged: this.refresh,
-                add: this.delayRefresh,
-                remove: this.delayRefresh,
-                update: this.delayRefresh,
-                clear: this.refresh
-            });
-        }
-        this.store = store;
-        if(store && !initial){
-            this.refresh();
-        }
     },
 
-    onSwfReady : function(isReset){
-        Ext.chart.Chart.superclass.onSwfReady.call(this, isReset);
-        var ref;
-        this.swf.setType(this.type);
+    afterLayout: function() {
+        if (!this.isHeader) {
+            var me = this,
+                topHeaders = me.query('>gridcolumn:not([hidden])'),
+                viewEl,
+                firstHeaderEl,
+                lastHeaderEl;
+
+            me.callParent(arguments);
+
+            if (topHeaders.length) {
+                firstHeaderEl = topHeaders[0].el;
+                if (firstHeaderEl !== me.pastFirstHeaderEl) {
+                    if (me.pastFirstHeaderEl) {
+                        me.pastFirstHeaderEl.removeCls(me.firstHeaderCls);
+                    }
+                    firstHeaderEl.addCls(me.firstHeaderCls);
+                    me.pastFirstHeaderEl = firstHeaderEl;
+                }
 
-        if(this.chartStyle){
-            this.setStyles(Ext.apply({}, this.extraStyle, this.chartStyle));
+                lastHeaderEl = topHeaders[topHeaders.length - 1].el;
+                if (lastHeaderEl !== me.pastLastHeaderEl) {
+                    if (me.pastLastHeaderEl) {
+                        me.pastLastHeaderEl.removeCls(me.lastHeaderCls);
+                    }
+                    lastHeaderEl.addCls(me.lastHeaderCls);
+                    me.pastLastHeaderEl = lastHeaderEl;
+                }
+            }
         }
 
-        if(this.categoryNames){
-            this.setCategoryNames(this.categoryNames);
-        }
+    },
+
+    onHeaderShow: function(header, preventLayout) {
+        
+        var me = this,
+            gridSection = me.ownerCt,
+            menu = me.getMenu(),
+            topItems, topItemsVisible,
+            colCheckItem,
+            itemToEnable,
+            len, i;
+
+        if (menu) {
+
+            colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
+            if (colCheckItem) {
+                colCheckItem.setChecked(true, true);
+            }
 
-        if(this.tipRenderer){
-            ref = this.getFunctionRef(this.tipRenderer);
-            this.setTipRenderer(ref.fn, ref.scope);
+            
+            topItems = menu.query('#columnItem>menucheckitem[checked]');
+            topItemsVisible = topItems.length;
+            if ((me.getVisibleGridColumns().length > 1) && me.disabledMenuItems && me.disabledMenuItems.length) {
+                if (topItemsVisible == 1) {
+                    Ext.Array.remove(me.disabledMenuItems, topItems[0]);
+                }
+                for (i = 0, len = me.disabledMenuItems.length; i < len; i++) {
+                    itemToEnable = me.disabledMenuItems[i];
+                    if (!itemToEnable.isDestroyed) {
+                        itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable']();
+                    }
+                }
+                if (topItemsVisible == 1) {
+                    me.disabledMenuItems = topItems;
+                } else {
+                    me.disabledMenuItems = [];
+                }
+            }
         }
-        if(this.legendRenderer){
-            ref = this.getFunctionRef(this.legendRenderer);
-            this.setLegendRenderer(ref.fn, ref.scope);
+
+        
+        
+        if (!header.isGroupHeader) {
+            if (me.view) {
+                me.view.onHeaderShow(me, header, true);
+            }
+            if (gridSection) {
+                gridSection.onHeaderShow(me, header);
+            }
         }
-        if(!isReset){
-            this.bindStore(this.store, true);
+        me.fireEvent('columnshow', me, header);
+
+        
+        if (preventLayout !== true) {
+            me.doLayout();
         }
-        this.refresh.defer(10, this);
     },
 
-    delayRefresh : function(){
-        if(!this.refreshTask){
-            this.refreshTask = new Ext.util.DelayedTask(this.refresh, this);
+    doComponentLayout: function(){
+        var me = this;
+        if (me.view && me.view.saveScrollState) {
+            me.view.saveScrollState();
+        }
+        me.callParent(arguments);
+        if (me.view && me.view.restoreScrollState) {
+            me.view.restoreScrollState();
         }
-        this.refreshTask.delay(this.refreshBuffer);
     },
 
-    refresh : function(){
-        if(this.fireEvent('beforerefresh', this) !== false){
-            var styleChanged = false;
+    onHeaderHide: function(header, suppressLayout) {
+        
+        var me = this,
+            gridSection = me.ownerCt,
+            menu = me.getMenu(),
+            colCheckItem;
+
+        if (menu) {
+
             
-            var data = [], rs = this.store.data.items;
-            for(var j = 0, len = rs.length; j < len; j++){
-                data[j] = rs[j].data;
+            colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
+            if (colCheckItem) {
+                colCheckItem.setChecked(false, true);
+            }
+            me.setDisabledItems();
+        }
+
+        
+        if (!header.isGroupHeader) {
+            if (me.view) {
+                me.view.onHeaderHide(me, header, true);
+            }
+            if (gridSection) {
+                gridSection.onHeaderHide(me, header);
             }
+
             
+            if (!suppressLayout) {
+                me.doLayout();
+            }
+        }
+        me.fireEvent('columnhide', me, header);
+    },
+
+    setDisabledItems: function(){
+        var me = this,
+            menu = me.getMenu(),
+            i = 0,
+            len,
+            itemsToDisable,
+            itemToDisable;
+
+        
+        itemsToDisable = menu.query('#columnItem>menucheckitem[checked]');
+        if ((itemsToDisable.length === 1)) {
+            if (!me.disabledMenuItems) {
+                me.disabledMenuItems = [];
+            }
+
             
-            var dataProvider = [];
-            var seriesCount = 0;
-            var currentSeries = null;
-            var i = 0;
-            if(this.series){
-                seriesCount = this.series.length;
-                for(i = 0; i < seriesCount; i++){
-                    currentSeries = this.series[i];
-                    var clonedSeries = {};
-                    for(var prop in currentSeries){
-                        if(prop == "style" && currentSeries.style !== null){
-                            clonedSeries.style = Ext.encode(currentSeries.style);
-                            styleChanged = true;
-                            
-                            
-                            
-                            
-                        } else{
-                            clonedSeries[prop] = currentSeries[prop];
-                        }
-                    }
-                    dataProvider.push(clonedSeries);
-                }
+            if ((me.getVisibleGridColumns().length === 1) && itemsToDisable[0].menu) {
+                itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]'));
             }
 
-            if(seriesCount > 0){
-                for(i = 0; i < seriesCount; i++){
-                    currentSeries = dataProvider[i];
-                    if(!currentSeries.type){
-                        currentSeries.type = this.type;
-                    }
-                    currentSeries.dataProvider = data;
+            len = itemsToDisable.length;
+            
+            for (i = 0; i < len; i++) {
+                itemToDisable = itemsToDisable[i];
+                if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) {
+
+                    
+                    
+                    itemToDisable.disabled = false;
+                    itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable']();
+                    me.disabledMenuItems.push(itemToDisable);
                 }
-            } else{
-                dataProvider.push({type: this.type, dataProvider: data});
-            }
-            this.swf.setDataProvider(dataProvider);
-            if(this.seriesStyles){
-                this.setSeriesStyles(this.seriesStyles);
             }
-            this.fireEvent('refresh', this);
         }
     },
 
     
-    createFnProxy : function(fn){
-        var fnName = 'extFnProxy' + (++Ext.chart.Chart.PROXY_FN_ID);
-        Ext.chart.Chart.proxyFunction[fnName] = fn;
-        return 'Ext.chart.Chart.proxyFunction.' + fnName;
+    tempLock: function() {
+        this.ddLock = true;
+        Ext.Function.defer(function() {
+            this.ddLock = false;
+        }, 200, this);
     },
 
-    
-    removeFnProxy : function(fn){
-        if(!Ext.isEmpty(fn)){
-            fn = fn.replace('Ext.chart.Chart.proxyFunction.', '');
-            delete Ext.chart.Chart.proxyFunction[fn];
+    onHeaderResize: function(header, w, suppressFocus) {
+        this.tempLock();
+        if (this.view && this.view.rendered) {
+            this.view.onHeaderResize(header, w, suppressFocus);
         }
     },
 
-    
-    getFunctionRef : function(val){
-        if(Ext.isFunction(val)){
-            return {
-                fn: val,
-                scope: this
-            };
-        }else{
-            return {
-                fn: val.fn,
-                scope: val.scope || this
-            }
-        }
+    onHeaderClick: function(header, e, t) {
+        this.fireEvent("headerclick", this, header, e, t);
     },
 
-    
-    onDestroy: function(){
-        if (this.refreshTask && this.refreshTask.cancel){
-            this.refreshTask.cancel();
+    onHeaderTriggerClick: function(header, e, t) {
+        
+        if (this.fireEvent("headertriggerclick", this, header, e, t) !== false) {
+            this.showMenuBy(t, header);
         }
-        Ext.chart.Chart.superclass.onDestroy.call(this);
-        this.bindStore(null);
-        this.removeFnProxy(this.tipFnName);
-        this.removeFnProxy(this.legendFnName);
-    }
-});
-Ext.reg('chart', Ext.chart.Chart);
-Ext.chart.Chart.PROXY_FN_ID = 0;
-Ext.chart.Chart.proxyFunction = {};
+    },
 
+    showMenuBy: function(t, header) {
+        var menu = this.getMenu(),
+            ascItem  = menu.down('#ascItem'),
+            descItem = menu.down('#descItem'),
+            sortableMth;
 
-Ext.chart.Chart.CHART_URL = 'http:/' + '/yui.yahooapis.com/2.8.0/build/charts/assets/charts.swf';
+        menu.activeHeader = menu.ownerCt = header;
+        menu.setFloatParent(header);
+        
+        header.titleContainer.addCls(this.headerOpenCls);
 
+        
+        sortableMth = header.sortable ? 'enable' : 'disable';
+        if (ascItem) {
+            ascItem[sortableMth]();
+        }
+        if (descItem) {
+            descItem[sortableMth]();
+        }
+        menu.showBy(t);
+    },
 
-Ext.chart.PieChart = Ext.extend(Ext.chart.Chart, {
-    type: 'pie',
+    
+    onMenuDeactivate: function() {
+        var menu = this.getMenu();
+        
+        menu.activeHeader.titleContainer.removeCls(this.headerOpenCls);
+    },
 
-    onSwfReady : function(isReset){
-        Ext.chart.PieChart.superclass.onSwfReady.call(this, isReset);
+    moveHeader: function(fromIdx, toIdx) {
 
-        this.setDataField(this.dataField);
-        this.setCategoryField(this.categoryField);
+        
+        this.tempLock();
+        this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx);
     },
 
-    setDataField : function(field){
-        this.dataField = field;
-        this.swf.setDataField(field);
-    },
+    purgeCache: function() {
+        var me = this;
+        
+        delete me.gridDataColumns;
+        delete me.hideableColumns;
 
-    setCategoryField : function(field){
-        this.categoryField = field;
-        this.swf.setCategoryField(field);
-    }
-});
-Ext.reg('piechart', Ext.chart.PieChart);
+        
+        if (me.menu) {
+            me.menu.destroy();
+            delete me.menu;
+        }
+    },
 
+    onHeaderMoved: function(header, fromIdx, toIdx) {
+        var me = this,
+            gridSection = me.ownerCt;
 
-Ext.chart.CartesianChart = Ext.extend(Ext.chart.Chart, {
-    onSwfReady : function(isReset){
-        Ext.chart.CartesianChart.superclass.onSwfReady.call(this, isReset);
-        this.labelFn = [];
-        if(this.xField){
-            this.setXField(this.xField);
-        }
-        if(this.yField){
-            this.setYField(this.yField);
-        }
-        if(this.xAxis){
-            this.setXAxis(this.xAxis);
+        if (gridSection && gridSection.onHeaderMove) {
+            gridSection.onHeaderMove(me, header, fromIdx, toIdx);
         }
-        if(this.xAxes){
-            this.setXAxes(this.xAxes);
-        }
-        if(this.yAxis){
-            this.setYAxis(this.yAxis);
-        }
-        if(this.yAxes){
-            this.setYAxes(this.yAxes);
+        me.fireEvent("columnmove", me, header, fromIdx, toIdx);
+    },
+
+    
+    getMenu: function() {
+        var me = this;
+
+        if (!me.menu) {
+            me.menu = Ext.create('Ext.menu.Menu', {
+                hideOnParentHide: false,  
+                items: me.getMenuItems(),
+                listeners: {
+                    deactivate: me.onMenuDeactivate,
+                    scope: me
+                }
+            });
+            me.setDisabledItems();
+            me.fireEvent('menucreate', me, me.menu);
         }
-        if(Ext.isDefined(this.constrainViewport)){
-            this.swf.setConstrainViewport(this.constrainViewport);
+        return me.menu;
+    },
+
+    
+    getMenuItems: function() {
+        var me = this,
+            menuItems = [],
+            hideableColumns = me.enableColumnHide ? me.getColumnMenu(me) : null;
+
+        if (me.sortable) {
+            menuItems = [{
+                itemId: 'ascItem',
+                text: me.sortAscText,
+                cls: Ext.baseCSSPrefix + 'hmenu-sort-asc',
+                handler: me.onSortAscClick,
+                scope: me
+            },{
+                itemId: 'descItem',
+                text: me.sortDescText,
+                cls: Ext.baseCSSPrefix + 'hmenu-sort-desc',
+                handler: me.onSortDescClick,
+                scope: me
+            }];
+        }
+        if (hideableColumns && hideableColumns.length) {
+            menuItems.push('-', {
+                itemId: 'columnItem',
+                text: me.columnsText,
+                cls: Ext.baseCSSPrefix + 'cols-icon',
+                menu: hideableColumns
+            });
         }
+        return menuItems;
     },
 
-    setXField : function(value){
-        this.xField = value;
-        this.swf.setHorizontalField(value);
+    
+    onSortAscClick: function() {
+        var menu = this.getMenu(),
+            activeHeader = menu.activeHeader;
+
+        activeHeader.setSortState('ASC');
+    },
+
+    
+    onSortDescClick: function() {
+        var menu = this.getMenu(),
+            activeHeader = menu.activeHeader;
+
+        activeHeader.setSortState('DESC');
     },
 
-    setYField : function(value){
-        this.yField = value;
-        this.swf.setVerticalField(value);
+    
+    getColumnMenu: function(headerContainer) {
+        var menuItems = [],
+            i = 0,
+            item,
+            items = headerContainer.query('>gridcolumn[hideable]'),
+            itemsLn = items.length,
+            menuItem;
+
+        for (; i < itemsLn; i++) {
+            item = items[i];
+            menuItem = Ext.create('Ext.menu.CheckItem', {
+                text: item.text,
+                checked: !item.hidden,
+                hideOnClick: false,
+                headerId: item.id,
+                menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined,
+                checkHandler: this.onColumnCheckChange,
+                scope: this
+            });
+            if (itemsLn === 1) {
+                menuItem.disabled = true;
+            }
+            menuItems.push(menuItem);
+
+            
+            
+            item.on({
+                destroy: Ext.Function.bind(menuItem.destroy, menuItem)
+            });
+        }
+        return menuItems;
     },
 
-    setXAxis : function(value){
-        this.xAxis = this.createAxis('xAxis', value);
-        this.swf.setHorizontalAxis(this.xAxis);
+    onColumnCheckChange: function(checkItem, checked) {
+        var header = Ext.getCmp(checkItem.headerId);
+        header[checked ? 'show' : 'hide']();
     },
 
-    setXAxes : function(value){
-        var axis;
-        for(var i = 0; i < value.length; i++) {
-            axis = this.createAxis('xAxis' + i, value[i]);
-            this.swf.setHorizontalAxis(axis);
+    
+    getColumnsForTpl: function(flushCache) {
+        var cols    = [],
+            headers   = this.getGridColumns(flushCache),
+            headersLn = headers.length,
+            i = 0,
+            header,
+            width;
+
+        for (; i < headersLn; i++) {
+            header = headers[i];
+
+            if (header.hidden || header.up('headercontainer[hidden=true]')) {
+                width = 0;
+            } else {
+                width = header.getDesiredWidth();
+                
+                
+                
+                if ((i === 0) && (Ext.isIE6 || Ext.isIE7)) {
+                    width += 1;
+                }
+            }
+            cols.push({
+                dataIndex: header.dataIndex,
+                align: header.align,
+                width: width,
+                id: header.id,
+                cls: header.tdCls,
+                columnId: header.getItemId()
+            });
         }
+        return cols;
     },
 
-    setYAxis : function(value){
-        this.yAxis = this.createAxis('yAxis', value);
-        this.swf.setVerticalAxis(this.yAxis);
+    
+    getColumnCount: function() {
+        return this.getGridColumns().length;
     },
 
-    setYAxes : function(value){
-        var axis;
-        for(var i = 0; i < value.length; i++) {
-            axis = this.createAxis('yAxis' + i, value[i]);
-            this.swf.setVerticalAxis(axis);
+    
+    getFullWidth: function(flushCache) {
+        var fullWidth = 0,
+            headers     = this.getVisibleGridColumns(flushCache),
+            headersLn   = headers.length,
+            i         = 0;
+
+        for (; i < headersLn; i++) {
+            if (!isNaN(headers[i].width)) {
+                
+                if (headers[i].getDesiredWidth) {
+                    fullWidth += headers[i].getDesiredWidth();
+                
+                } else {
+                    fullWidth += headers[i].getWidth();
+                }
+            }
         }
+        return fullWidth;
     },
 
-    createAxis : function(axis, value){
-        var o = Ext.apply({}, value),
-            ref,
-            old;
+    
+    clearOtherSortStates: function(activeHeader) {
+        var headers   = this.getGridColumns(),
+            headersLn = headers.length,
+            i         = 0,
+            oldSortState;
 
-        if(this[axis]){
-            old = this[axis].labelFunction;
-            this.removeFnProxy(old);
-            this.labelFn.remove(old);
+        for (; i < headersLn; i++) {
+            if (headers[i] !== activeHeader) {
+                oldSortState = headers[i].sortState;
+                
+                headers[i].setSortState(null, true);
+                
+                
+                
+            }
         }
-        if(o.labelRenderer){
-            ref = this.getFunctionRef(o.labelRenderer);
-            o.labelFunction = this.createFnProxy(function(v){
-                return ref.fn.call(ref.scope, v);
+    },
+
+    
+    getVisibleGridColumns: function(refreshCache) {
+        return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache));
+    },
+
+    
+    getGridColumns: function(refreshCache) {
+        var me = this,
+            result = refreshCache ? null : me.gridDataColumns;
+
+        
+        if (!result) {
+            me.gridDataColumns = result = [];
+            me.cascade(function(c) {
+                if ((c !== me) && !c.isGroupHeader) {
+                    result.push(c);
+                }
             });
-            delete o.labelRenderer;
-            this.labelFn.push(o.labelFunction);
         }
-        if(axis.indexOf('xAxis') > -1 && o.position == 'left'){
-            o.position = 'bottom';
+
+        return result;
+    },
+
+    
+    getHideableColumns: function(refreshCache) {
+        var me = this,
+            result = refreshCache ? null : me.hideableColumns;
+
+        if (!result) {
+            result = me.hideableColumns = me.query('[hideable]');
         }
-        return o;
+        return result;
     },
 
-    onDestroy : function(){
-        Ext.chart.CartesianChart.superclass.onDestroy.call(this);
-        Ext.each(this.labelFn, function(fn){
-            this.removeFnProxy(fn);
-        }, this);
-    }
-});
-Ext.reg('cartesianchart', Ext.chart.CartesianChart);
+    
+    getHeaderIndex: function(header) {
+        var columns = this.getGridColumns();
+        return Ext.Array.indexOf(columns, header);
+    },
+
+    
+    getHeaderAtIndex: function(index) {
+        var columns = this.getGridColumns();
+        return columns[index];
+    },
 
+    
+    prepareData: function(data, rowIdx, record, view, panel) {
+        var obj       = {},
+            headers   = this.gridDataColumns || this.getGridColumns(),
+            headersLn = headers.length,
+            colIdx    = 0,
+            header,
+            headerId,
+            renderer,
+            value,
+            metaData,
+            store = panel.store;
 
-Ext.chart.LineChart = Ext.extend(Ext.chart.CartesianChart, {
-    type: 'line'
-});
-Ext.reg('linechart', Ext.chart.LineChart);
+        for (; colIdx < headersLn; colIdx++) {
+            metaData = {
+                tdCls: '',
+                style: ''
+            };
+            header = headers[colIdx];
+            headerId = header.id;
+            renderer = header.renderer;
+            value = data[header.dataIndex];
+
+            
+            
+            if (typeof renderer === "string") {
+                header.renderer = renderer = Ext.util.Format[renderer];
+            }
 
+            if (typeof renderer === "function") {
+                value = renderer.call(
+                    header.scope || this.ownerCt,
+                    value,
+                    
+                    
+                    metaData,
+                    record,
+                    rowIdx,
+                    colIdx,
+                    store,
+                    view
+                );
+            }
 
-Ext.chart.ColumnChart = Ext.extend(Ext.chart.CartesianChart, {
-    type: 'column'
-});
-Ext.reg('columnchart', Ext.chart.ColumnChart);
 
+            obj[headerId+'-modified'] = record.isModified(header.dataIndex) ? Ext.baseCSSPrefix + 'grid-dirty-cell' : '';
+            obj[headerId+'-tdCls'] = metaData.tdCls;
+            obj[headerId+'-tdAttr'] = metaData.tdAttr;
+            obj[headerId+'-style'] = metaData.style;
+            if (value === undefined || value === null || value === '') {
+                value = '&#160;';
+            }
+            obj[headerId] = value;
+        }
+        return obj;
+    },
 
-Ext.chart.StackedColumnChart = Ext.extend(Ext.chart.CartesianChart, {
-    type: 'stackcolumn'
+    expandToFit: function(header) {
+        if (this.view) {
+            this.view.expandToFit(header);
+        }
+    }
 });
-Ext.reg('stackedcolumnchart', Ext.chart.StackedColumnChart);
 
 
-Ext.chart.BarChart = Ext.extend(Ext.chart.CartesianChart, {
-    type: 'bar'
-});
-Ext.reg('barchart', Ext.chart.BarChart);
+Ext.define('Ext.grid.column.Column', {
+    extend: 'Ext.grid.header.Container',
+    alias: 'widget.gridcolumn',
+    requires: ['Ext.util.KeyNav'],
+    alternateClassName: 'Ext.grid.Column',
 
+    baseCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable',
 
-Ext.chart.StackedBarChart = Ext.extend(Ext.chart.CartesianChart, {
-    type: 'stackbar'
-});
-Ext.reg('stackedbarchart', Ext.chart.StackedBarChart);
+    
+    hoverCls: Ext.baseCSSPrefix + 'column-header-over',
 
+    handleWidth: 5,
 
+    sortState: null,
 
+    possibleSortStates: ['ASC', 'DESC'],
 
-Ext.chart.Axis = function(config){
-    Ext.apply(this, config);
-};
+    renderTpl:
+        '<div id="{id}-titleContainer" class="' + Ext.baseCSSPrefix + 'column-header-inner">' +
+            '<span id="{id}-textEl" class="' + Ext.baseCSSPrefix + 'column-header-text">' +
+                '{text}' +
+            '</span>' +
+            '<tpl if="!values.menuDisabled">'+
+                '<div id="{id}-triggerEl" class="' + Ext.baseCSSPrefix + 'column-header-trigger"></div>'+
+            '</tpl>' +
+        '</div>',
 
-Ext.chart.Axis.prototype =
-{
     
-    type: null,
 
     
-    orientation: "horizontal",
+    dataIndex: null,
 
     
-    reverse: false,
+    text: '&#160;',
 
     
-    labelFunction: null,
+    sortable: true,
 
     
-    hideOverlappingLabels: true,
 
     
-    labelSpacing: 2
-};
-
-
-Ext.chart.NumericAxis = Ext.extend(Ext.chart.Axis, {
-    type: "numeric",
 
     
-    minimum: NaN,
 
     
-    maximum: NaN,
+    hideable: true,
 
     
-    majorUnit: NaN,
+    menuDisabled: false,
 
     
-    minorUnit: NaN,
+    renderer: false,
 
     
-    snapToUnits: true,
+    align: 'left',
 
     
-    alwaysShowZero: true,
+    draggable: true,
 
     
-    scale: "linear",
+    
+    initDraggable: Ext.emptyFn,
 
     
-    roundMajorUnit: true,
 
     
-    calculateByLabelSize: true,
 
     
-    position: 'left',
 
     
-    adjustMaximumByMajorUnit: true,
 
     
-    adjustMinimumByMajorUnit: true
 
-});
+    
+    isHeader: true,
 
+    initComponent: function() {
+        var me = this,
+            i,
+            len,
+            item;
 
-Ext.chart.TimeAxis = Ext.extend(Ext.chart.Axis, {
-    type: "time",
+        if (Ext.isDefined(me.header)) {
+            me.text = me.header;
+            delete me.header;
+        }
 
-    
-    minimum: null,
+        
+        
+        
+        if (me.flex) {
+            me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
+        }
+        
+        
+        else {
+            me.minWidth = me.width;
+        }
 
-    
-    maximum: null,
+        if (!me.triStateSort) {
+            me.possibleSortStates.length = 2;
+        }
 
-    
-    majorUnit: NaN,
+        
+        if (Ext.isDefined(me.columns)) {
+            me.isGroupHeader = true;
 
-    
-    majorTimeUnit: null,
 
-    
-    minorUnit: NaN,
+            
+            me.items = me.columns;
+            delete me.columns;
+            delete me.flex;
+            me.width = 0;
 
-    
-    minorTimeUnit: null,
+            
+            for (i = 0, len = me.items.length; i < len; i++) {
+                item = me.items[i];
+                if (!item.hidden) {
+                    me.width += item.width || Ext.grid.header.Container.prototype.defaultWidth;
+                }
+            }
+            me.minWidth = me.width;
 
-    
-    snapToUnits: true,
+            me.cls = (me.cls||'') + ' ' + Ext.baseCSSPrefix + 'group-header';
+            me.sortable = false;
+            me.resizable = false;
+            me.align = 'center';
+        }
 
-    
-    stackingEnabled: false,
+        me.addChildEls('titleContainer', 'triggerEl', 'textEl');
 
-    
-    calculateByLabelSize: true
+        
+        me.callParent(arguments);
+    },
 
-});
+    onAdd: function(childHeader) {
+        childHeader.isSubHeader = true;
+        childHeader.addCls(Ext.baseCSSPrefix + 'group-sub-header');
+        this.callParent(arguments);
+    },
 
+    onRemove: function(childHeader) {
+        childHeader.isSubHeader = false;
+        childHeader.removeCls(Ext.baseCSSPrefix + 'group-sub-header');
+        this.callParent(arguments);
+    },
 
-Ext.chart.CategoryAxis = Ext.extend(Ext.chart.Axis, {
-    type: "category",
+    initRenderData: function() {
+        var me = this;
 
-    
-    categoryNames: null,
+        Ext.applyIf(me.renderData, {
+            text: me.text,
+            menuDisabled: me.menuDisabled
+        });
+        return me.callParent(arguments);
+    },
 
-    
-    calculateCategoryCount: false
+    applyColumnState: function (state) {
+        var me = this,
+            defined = Ext.isDefined;
+            
+        
+        me.applyColumnsState(state.columns);
 
-});
+        
+        
+        if (defined(state.hidden)) {
+            me.hidden = state.hidden;
+        }
+        if (defined(state.locked)) {
+            me.locked = state.locked;
+        }
+        if (defined(state.sortable)) {
+            me.sortable = state.sortable;
+        }
+        if (defined(state.width)) {
+            delete me.flex;
+            me.width = state.width;
+        } else if (defined(state.flex)) {
+            delete me.width;
+            me.flex = state.flex;
+        }
+    },
 
+    getColumnState: function () {
+        var me = this,
+            columns = [],
+            state = {
+                id: me.headerId
+            };
 
-Ext.chart.Series = function(config) { Ext.apply(this, config); };
+        me.savePropsToState(['hidden', 'sortable', 'locked', 'flex', 'width'], state);
+        
+        if (me.isGroupHeader) {
+            me.items.each(function(column){
+                columns.push(column.getColumnState());
+            });
+            if (columns.length) {
+                state.columns = columns;
+            }
+        } else if (me.isSubHeader && me.ownerCt.hidden) {
+            
+            delete me.hidden;
+        }
 
-Ext.chart.Series.prototype =
-{
-    
-    type: null,
+        if ('width' in state) {
+            delete state.flex; 
+        }
+        return state;
+    },
 
     
-    displayName: null
-};
-
+    setText: function(text) {
+        this.text = text;
+        if (this.rendered) {
+            this.textEl.update(text);
+        }
+    },
 
-Ext.chart.CartesianSeries = Ext.extend(Ext.chart.Series, {
     
-    xField: null,
-
     
-    yField: null,
+    getOwnerHeaderCt: function() {
+        return this.up(':not([isHeader])');
+    },
 
     
-    showInLegend: true,
+    getIndex: function() {
+        return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this);
+    },
 
-    
-    axis: 'primary'
-});
+    onRender: function() {
+        var me = this,
+            grid = me.up('tablepanel');
 
+        
+        
+        if (grid && (!me.sortable || grid.sortableColumns === false) && !me.groupable && !me.lockable && (grid.enableColumnHide === false || !me.getOwnerHeaderCt().getHideableColumns().length)) {
+            me.menuDisabled = true;
+        }
+        me.callParent(arguments);
+    },
 
-Ext.chart.ColumnSeries = Ext.extend(Ext.chart.CartesianSeries, {
-    type: "column"
-});
+    afterRender: function() {
+        var me = this,
+            el = me.el;
 
+        me.callParent(arguments);
 
-Ext.chart.LineSeries = Ext.extend(Ext.chart.CartesianSeries, {
-    type: "line"
-});
+        el.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align).addClsOnOver(me.overCls);
 
+        me.mon(el, {
+            click:     me.onElClick,
+            dblclick:  me.onElDblClick,
+            scope:     me
+        });
 
-Ext.chart.BarSeries = Ext.extend(Ext.chart.CartesianSeries, {
-    type: "bar"
-});
+        
+        
+        if (!Ext.isIE8 || !Ext.isStrict) {
+            me.mon(me.getFocusEl(), {
+                focus: me.onTitleMouseOver,
+                blur: me.onTitleMouseOut,
+                scope: me
+            });
+        }
 
+        me.mon(me.titleContainer, {
+            mouseenter:  me.onTitleMouseOver,
+            mouseleave:  me.onTitleMouseOut,
+            scope:      me
+        });
 
+        me.keyNav = Ext.create('Ext.util.KeyNav', el, {
+            enter: me.onEnterKey,
+            down: me.onDownKey,
+            scope: me
+        });
+    },
 
-Ext.chart.PieSeries = Ext.extend(Ext.chart.Series, {
-    type: "pie",
-    dataField: null,
-    categoryField: null
-});
-Ext.menu.Menu = Ext.extend(Ext.Container, {
-    
-    
-    
-    minWidth : 120,
-    
-    shadow : 'sides',
-    
-    subMenuAlign : 'tl-tr?',
-    
-    defaultAlign : 'tl-bl?',
-    
-    allowOtherMenus : false,
-    
-    ignoreParentClicks : false,
-    
-    enableScrolling : true,
-    
-    maxHeight : null,
-    
-    scrollIncrement : 24,
-    
-    showSeparator : true,
     
-    defaultOffsets : [0, 0],
+    setWidth: function(width,  doLayout) {
+        var me = this,
+            headerCt = me.ownerCt,
+            siblings,
+            len, i,
+            oldWidth = me.getWidth(),
+            groupWidth = 0,
+            sibling;
 
-    
-    plain : false,
+        if (width !== oldWidth) {
+            me.oldWidth = oldWidth;
 
-    
-    floating : true,
+            
+            
+            me.minWidth = me.width = width;
 
+            
+            if (headerCt.isGroupHeader) {
+                siblings = headerCt.items.items;
+                len = siblings.length;
 
-    
-    zIndex: 15000,
+                for (i = 0; i < len; i++) {
+                    sibling = siblings[i];
+                    if (!sibling.hidden) {
+                        groupWidth += (sibling === me) ? width : sibling.getWidth();
+                    }
+                }
+                headerCt.setWidth(groupWidth, doLayout);
+            } else if (doLayout !== false) {
+                
+                headerCt.doLayout();
+            }
+        }
+    },
 
-    
-    hidden : true,
+    afterComponentLayout: function(width, height) {
+        var me = this,
+            ownerHeaderCt = this.getOwnerHeaderCt();
 
-    
-    layout : 'menu',
-    hideMode : 'offsets',    
-    scrollerHeight : 8,
-    autoLayout : true,       
-    defaultType : 'menuitem',
-    bufferResize : false,
+        me.callParent(arguments);
 
-    initComponent : function(){
-        if(Ext.isArray(this.initialConfig)){
-            Ext.apply(this, {items:this.initialConfig});
-        }
-        this.addEvents(
-            
-            'click',
-            
-            'mouseover',
-            
-            'mouseout',
-            
-            'itemclick'
-        );
-        Ext.menu.MenuMgr.register(this);
-        if(this.floating){
-            Ext.EventManager.onWindowResize(this.hide, this);
-        }else{
-            if(this.initialConfig.hidden !== false){
-                this.hidden = false;
-            }
-            this.internalDefaults = {hideOnClick: false};
+        
+        
+        
+        if (width && !me.isGroupHeader && ownerHeaderCt) {
+            ownerHeaderCt.onHeaderResize(me, width, true);
         }
-        Ext.menu.Menu.superclass.initComponent.call(this);
-        if(this.autoLayout){
-            var fn = this.doLayout.createDelegate(this, []);
-            this.on({
-                add: fn,
-                remove: fn
-            });
+        if (me.oldWidth && (width !== me.oldWidth)) {
+            ownerHeaderCt.fireEvent('columnresize', ownerHeaderCt, this, width);
         }
+        delete me.oldWidth;
     },
 
     
-    getLayoutTarget : function() {
-        return this.ul;
-    },
-
     
-    onRender : function(ct, position){
-        if(!ct){
-            ct = Ext.getBody();
+    
+    setPadding: function(headerHeight) {
+        var me = this,
+            lineHeight = Ext.util.TextMetrics.measure(me.textEl.dom, me.text).height;
+
+        
+        if (!me.isGroupHeader) {
+            if (me.titleContainer.getHeight() < headerHeight) {
+                me.titleContainer.dom.style.height = headerHeight + 'px';
+            }
         }
+        headerHeight = me.titleContainer.getViewSize().height;
 
-        var dh = {
-            id: this.getId(),
-            cls: 'x-menu ' + ((this.floating) ? 'x-menu-floating x-layer ' : '') + (this.cls || '') + (this.plain ? ' x-menu-plain' : '') + (this.showSeparator ? '' : ' x-menu-nosep'),
-            style: this.style,
-            cn: [
-                {tag: 'a', cls: 'x-menu-focus', href: '#', onclick: 'return false;', tabIndex: '-1'},
-                {tag: 'ul', cls: 'x-menu-list'}
-            ]
-        };
-        if(this.floating){
-            this.el = new Ext.Layer({
-                shadow: this.shadow,
-                dh: dh,
-                constrain: false,
-                parentEl: ct,
-                zindex: this.zIndex
+        
+        if (lineHeight) {
+            me.titleContainer.setStyle({
+                paddingTop: Math.max(((headerHeight - lineHeight) / 2), 0) + 'px'
             });
-        }else{
-            this.el = ct.createChild(dh);
         }
-        Ext.menu.Menu.superclass.onRender.call(this, ct, position);
 
-        if(!this.keyNav){
-            this.keyNav = new Ext.menu.MenuNav(this);
-        }
         
-        this.focusEl = this.el.child('a.x-menu-focus');
-        this.ul = this.el.child('ul.x-menu-list');
-        this.mon(this.ul, {
-            scope: this,
-            click: this.onClick,
-            mouseover: this.onMouseOver,
-            mouseout: this.onMouseOut
-        });
-        if(this.enableScrolling){
-            this.mon(this.el, {
-                scope: this,
-                delegate: '.x-menu-scroller',
-                click: this.onScroll,
-                mouseover: this.deactivateActive
-            });
+        if (Ext.isIE && me.triggerEl) {
+            me.triggerEl.setHeight(headerHeight);
         }
     },
 
-    
-    findTargetItem : function(e){
-        var t = e.getTarget('.x-menu-list-item', this.ul, true);
-        if(t && t.menuItemId){
-            return this.items.get(t.menuItemId);
-        }
+    onDestroy: function() {
+        var me = this;
+        
+        Ext.destroy(me.textEl, me.keyNav);
+        delete me.keyNav;
+        me.callParent(arguments);
     },
 
-    
-    onClick : function(e){
-        var t = this.findTargetItem(e);
-        if(t){
-            if(t.isFormField){
-                this.setActiveItem(t);
-            }else if(t instanceof Ext.menu.BaseItem){
-                if(t.menu && this.ignoreParentClicks){
-                    t.expandMenu();
-                    e.preventDefault();
-                }else if(t.onClick){
-                    t.onClick(e);
-                    this.fireEvent('click', this, t, e);
-                }
-            }
-        }
+    onTitleMouseOver: function() {
+        this.titleContainer.addCls(this.hoverCls);
     },
 
-    
-    setActiveItem : function(item, autoExpand){
-        if(item != this.activeItem){
-            this.deactivateActive();
-            if((this.activeItem = item).isFormField){
-                item.focus();
-            }else{
-                item.activate(autoExpand);
-            }
-        }else if(autoExpand){
-            item.expandMenu();
-        }
+    onTitleMouseOut: function() {
+        this.titleContainer.removeCls(this.hoverCls);
     },
 
-    deactivateActive : function(){
-        var a = this.activeItem;
-        if(a){
-            if(a.isFormField){
-                
-                if(a.collapse){
-                    a.collapse();
-                }
-            }else{
-                a.deactivate();
-            }
-            delete this.activeItem;
+    onDownKey: function(e) {
+        if (this.triggerEl) {
+            this.onElClick(e, this.triggerEl.dom || this.el.dom);
         }
     },
 
-    
-    tryActivate : function(start, step){
-        var items = this.items;
-        for(var i = start, len = items.length; i >= 0 && i < len; i+= step){
-            var item = items.get(i);
-            if(!item.disabled && (item.canActivate || item.isFormField)){
-                this.setActiveItem(item, false);
-                return item;
-            }
-        }
-        return false;
+    onEnterKey: function(e) {
+        this.onElClick(e, this.el.dom);
     },
 
     
-    onMouseOver : function(e){
-        var t = this.findTargetItem(e);
-        if(t){
-            if(t.canActivate && !t.disabled){
-                this.setActiveItem(t, true);
-            }
+    onElDblClick: function(e, t) {
+        var me = this,
+            ownerCt = me.ownerCt;
+        if (ownerCt && Ext.Array.indexOf(ownerCt.items, me) !== 0 && me.isOnLeftEdge(e) ) {
+            ownerCt.expandToFit(me.previousSibling('gridcolumn'));
         }
-        this.over = true;
-        this.fireEvent('mouseover', this, e, t);
     },
 
-    
-    onMouseOut : function(e){
-        var t = this.findTargetItem(e);
-        if(t){
-            if(t == this.activeItem && t.shouldDeactivate && t.shouldDeactivate(e)){
-                this.activeItem.deactivate();
-                delete this.activeItem;
+    onElClick: function(e, t) {
+
+        
+        var me = this,
+            ownerHeaderCt = me.getOwnerHeaderCt();
+
+        if (ownerHeaderCt && !ownerHeaderCt.ddLock) {
+            
+            
+            if (me.triggerEl && (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) {
+                ownerHeaderCt.onHeaderTriggerClick(me, e, t);
+            
+            } else if (e.getKey() || (!me.isOnLeftEdge(e) && !me.isOnRightEdge(e))) {
+                me.toggleSortState();
+                ownerHeaderCt.onHeaderClick(me, e, t);
             }
         }
-        this.over = false;
-        this.fireEvent('mouseout', this, e, t);
     },
 
     
-    onScroll : function(e, t){
-        if(e){
-            e.stopEvent();
-        }
-        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
-        ul.scrollTop += this.scrollIncrement * (top ? -1 : 1);
-        if(top ? ul.scrollTop <= 0 : ul.scrollTop + this.activeMax >= ul.scrollHeight){
-           this.onScrollerOut(null, t);
-        }
+    processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
+        return this.fireEvent.apply(this, arguments);
     },
 
-    
-    onScrollerIn : function(e, t){
-        var ul = this.ul.dom, top = Ext.fly(t).is('.x-menu-scroller-top');
-        if(top ? ul.scrollTop > 0 : ul.scrollTop + this.activeMax < ul.scrollHeight){
-            Ext.fly(t).addClass(['x-menu-item-active', 'x-menu-scroller-active']);
+    toggleSortState: function() {
+        var me = this,
+            idx,
+            nextIdx;
+
+        if (me.sortable) {
+            idx = Ext.Array.indexOf(me.possibleSortStates, me.sortState);
+
+            nextIdx = (idx + 1) % me.possibleSortStates.length;
+            me.setSortState(me.possibleSortStates[nextIdx]);
         }
     },
 
-    
-    onScrollerOut : function(e, t){
-        Ext.fly(t).removeClass(['x-menu-item-active', 'x-menu-scroller-active']);
+    doSort: function(state) {
+        var ds = this.up('tablepanel').store;
+        ds.sort({
+            property: this.getSortParam(),
+            direction: state
+        });
     },
 
     
-    show : function(el, pos, parentMenu){
-        if(this.floating){
-            this.parentMenu = parentMenu;
-            if(!this.el){
-                this.render();
-                this.doLayout(false, true);
-            }
-            this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign, this.defaultOffsets), parentMenu);
-        }else{
-            Ext.menu.Menu.superclass.show.call(this);
-        }
+    getSortParam: function() {
+        return this.dataIndex;
     },
 
     
-    showAt : function(xy, parentMenu){
-        if(this.fireEvent('beforeshow', this) !== false){
-            this.parentMenu = parentMenu;
-            if(!this.el){
-                this.render();
-            }
-            if(this.enableScrolling){
-                
-                this.el.setXY(xy);
-                
-                xy[1] = this.constrainScroll(xy[1]);
-                xy = [this.el.adjustForConstraints(xy)[0], xy[1]];
-            }else{
-                
-                xy = this.el.adjustForConstraints(xy);
+    
+    setSortState: function(state, skipClear, initial) {
+        var me = this,
+            colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-',
+            ascCls = colSortClsPrefix + 'ASC',
+            descCls = colSortClsPrefix + 'DESC',
+            nullCls = colSortClsPrefix + 'null',
+            ownerHeaderCt = me.getOwnerHeaderCt(),
+            oldSortState = me.sortState;
+
+        if (oldSortState !== state && me.getSortParam()) {
+            me.addCls(colSortClsPrefix + state);
+            
+            if (state && !initial) {
+                me.doSort(state);
+            }
+            switch (state) {
+                case 'DESC':
+                    me.removeCls([ascCls, nullCls]);
+                    break;
+                case 'ASC':
+                    me.removeCls([descCls, nullCls]);
+                    break;
+                case null:
+                    me.removeCls([ascCls, descCls]);
+                    break;
             }
-            this.el.setXY(xy);
-            this.el.show();
-            Ext.menu.Menu.superclass.onShow.call(this);
-            if(Ext.isIE){
-                
-                this.fireEvent('autosize', this);
-                if(!Ext.isIE8){
-                    this.el.repaint();
-                }
+            if (ownerHeaderCt && !me.triStateSort && !skipClear) {
+                ownerHeaderCt.clearOtherSortStates(me);
             }
-            this.hidden = false;
-            this.focus();
-            this.fireEvent('show', this);
+            me.sortState = state;
+            ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state);
         }
     },
 
-    constrainScroll : function(y){
-        var max, full = this.ul.setHeight('auto').getHeight(),
-            returnY = y, normalY, parentEl, scrollTop, viewHeight;
-        if(this.floating){
-            parentEl = Ext.fly(this.el.dom.parentNode);
-            scrollTop = parentEl.getScroll().top;
-            viewHeight = parentEl.getViewSize().height;
-            
-            
-            normalY = y - scrollTop;
-            max = this.maxHeight ? this.maxHeight : viewHeight - normalY;
-            if(full > viewHeight) {
-                max = viewHeight;
-                
-                returnY = y - normalY;
-            } else if(max < full) {
-                returnY = y - (full - max);
-                max = full;
+    hide: function() {
+        var me = this,
+            items,
+            len, i,
+            lb,
+            newWidth = 0,
+            ownerHeaderCt = me.getOwnerHeaderCt();
+
+        
+        me.oldWidth = me.getWidth();
+
+        
+        if (me.isGroupHeader) {
+            items = me.items.items;
+            me.callParent(arguments);
+            ownerHeaderCt.onHeaderHide(me);
+            for (i = 0, len = items.length; i < len; i++) {
+                items[i].hidden = true;
+                ownerHeaderCt.onHeaderHide(items[i], true);
             }
-        }else{
-            max = this.getHeight();
+            return;
         }
+
         
-        if (this.maxHeight){
-            max = Math.min(this.maxHeight, max);
-        }
-        if(full > max && max > 0){
-            this.activeMax = max - this.scrollerHeight * 2 - this.el.getFrameWidth('tb') - Ext.num(this.el.shadowOffset, 0);
-            this.ul.setHeight(this.activeMax);
-            this.createScrollers();
-            this.el.select('.x-menu-scroller').setDisplayed('');
-        }else{
-            this.ul.setHeight(full);
-            this.el.select('.x-menu-scroller').setDisplayed('none');
-        }
-        this.ul.dom.scrollTop = 0;
-        return returnY;
-    },
+        lb = me.ownerCt.componentLayout.layoutBusy;
+        me.ownerCt.componentLayout.layoutBusy = true;
+        me.callParent(arguments);
+        me.ownerCt.componentLayout.layoutBusy = lb;
 
-    createScrollers : function(){
-        if(!this.scroller){
-            this.scroller = {
-                pos: 0,
-                top: this.el.insertFirst({
-                    tag: 'div',
-                    cls: 'x-menu-scroller x-menu-scroller-top',
-                    html: '&#160;'
-                }),
-                bottom: this.el.createChild({
-                    tag: 'div',
-                    cls: 'x-menu-scroller x-menu-scroller-bottom',
-                    html: '&#160;'
-                })
-            };
-            this.scroller.top.hover(this.onScrollerIn, this.onScrollerOut, this);
-            this.scroller.topRepeater = new Ext.util.ClickRepeater(this.scroller.top, {
-                listeners: {
-                    click: this.onScroll.createDelegate(this, [null, this.scroller.top], false)
-                }
-            });
-            this.scroller.bottom.hover(this.onScrollerIn, this.onScrollerOut, this);
-            this.scroller.bottomRepeater = new Ext.util.ClickRepeater(this.scroller.bottom, {
-                listeners: {
-                    click: this.onScroll.createDelegate(this, [null, this.scroller.bottom], false)
+        
+        ownerHeaderCt.onHeaderHide(me);
+
+        if (me.ownerCt.isGroupHeader) {
+            
+            items = me.ownerCt.query('>:not([hidden])');
+            if (!items.length) {
+                me.ownerCt.hide();
+            }
+            
+            else {
+                for (i = 0, len = items.length; i < len; i++) {
+                    newWidth += items[i].getWidth();
                 }
-            });
+                me.ownerCt.minWidth = newWidth;
+                me.ownerCt.setWidth(newWidth);
+            }
         }
     },
 
-    onLayout : function(){
-        if(this.isVisible()){
-            if(this.enableScrolling){
-                this.constrainScroll(this.el.getTop());
-            }
-            if(this.floating){
-                this.el.sync();
+    show: function() {
+        var me = this,
+            ownerCt = me.ownerCt,
+            ownerCtCompLayout = ownerCt.componentLayout,
+            ownerCtCompLayoutBusy = ownerCtCompLayout.layoutBusy,
+            ownerCtLayout = ownerCt.layout,
+            ownerCtLayoutBusy = ownerCtLayout.layoutBusy,
+            items,
+            len, i,
+            item,
+            newWidth = 0;
+
+        
+
+        
+        ownerCtCompLayout.layoutBusy = ownerCtLayout.layoutBusy = true;
+
+        me.callParent(arguments);
+
+        ownerCtCompLayout.layoutBusy = ownerCtCompLayoutBusy;
+        ownerCtLayout.layoutBusy = ownerCtLayoutBusy;
+
+        
+        if (me.isSubHeader) {
+            if (!ownerCt.isVisible()) {
+                ownerCt.show();
             }
         }
-    },
 
-    focus : function(){
-        if(!this.hidden){
-            this.doFocus.defer(50, this);
+        
+        if (me.isGroupHeader && !me.query(':not([hidden])').length) {
+            items = me.query('>*');
+            for (i = 0, len = items.length; i < len; i++) {
+                item = items[i];
+                item.preventLayout = true;
+                item.show();
+                newWidth += item.getWidth();
+                delete item.preventLayout;
+            }
+            me.setWidth(newWidth);
         }
-    },
 
-    doFocus : function(){
-        if(!this.hidden){
-            this.focusEl.focus();
+        
+        if (ownerCt.isGroupHeader && me.preventLayout !== true) {
+            items = ownerCt.query('>:not([hidden])');
+            for (i = 0, len = items.length; i < len; i++) {
+                newWidth += items[i].getWidth();
+            }
+            ownerCt.minWidth = newWidth;
+            ownerCt.setWidth(newWidth);
         }
-    },
 
-    
-    hide : function(deep){
-        if (!this.isDestroyed) {
-            this.deepHide = deep;
-            Ext.menu.Menu.superclass.hide.call(this);
-            delete this.deepHide;
+        
+        ownerCt = me.getOwnerHeaderCt();
+        if (ownerCt) {
+            ownerCt.onHeaderShow(me, me.preventLayout);
         }
     },
 
-    
-    onHide : function(){
-        Ext.menu.Menu.superclass.onHide.call(this);
-        this.deactivateActive();
-        if(this.el && this.floating){
-            this.el.hide();
+    getDesiredWidth: function() {
+        var me = this;
+        if (me.rendered && me.componentLayout && me.componentLayout.lastComponentSize) {
+            
+            
+            
+            
+            
+            
+            return me.componentLayout.lastComponentSize.width;
+        
+        
+        
         }
-        var pm = this.parentMenu;
-        if(this.deepHide === true && pm){
-            if(pm.floating){
-                pm.hide(true);
-            }else{
-                pm.deactivateActive();
-            }
+        else if (me.flex) {
+            
+            return me.width;
+        }
+        else {
+            return me.width;
         }
     },
 
-    
-    lookupComponent : function(c){
-         if(Ext.isString(c)){
-            c = (c == 'separator' || c == '-') ? new Ext.menu.Separator() : new Ext.menu.TextItem(c);
-             this.applyDefaults(c);
-         }else{
-            if(Ext.isObject(c)){
-                c = this.getMenuItem(c);
-            }else if(c.tagName || c.el){ 
-                c = new Ext.BoxComponent({
-                    el: c
-                });
-            }
-         }
-         return c;
+    getCellSelector: function() {
+        return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.getItemId();
     },
 
-    applyDefaults : function(c){
-        if(!Ext.isString(c)){
-            c = Ext.menu.Menu.superclass.applyDefaults.call(this, c);
-            var d = this.internalDefaults;
-            if(d){
-                if(c.events){
-                    Ext.applyIf(c.initialConfig, d);
-                    Ext.apply(c, d);
-                }else{
-                    Ext.applyIf(c, d);
-                }
-            }
-        }
-        return c;
+    getCellInnerSelector: function() {
+        return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner';
     },
 
-    
-    getMenuItem : function(config){
-       if(!config.isXType){
-            if(!config.xtype && Ext.isBoolean(config.checked)){
-                return new Ext.menu.CheckItem(config)
-            }
-            return Ext.create(config, this.defaultType);
-        }
-        return config;
+    isOnLeftEdge: function(e) {
+        return (e.getXY()[0] - this.el.getLeft() <= this.handleWidth);
     },
 
-    
-    addSeparator : function(){
-        return this.add(new Ext.menu.Separator());
-    },
+    isOnRightEdge: function(e) {
+        return (this.el.getRight() - e.getXY()[0] <= this.handleWidth);
+    }
 
     
-    addElement : function(el){
-        return this.add(new Ext.menu.BaseItem({
-            el: el
-        }));
-    },
-
     
-    addItem : function(item){
-        return this.add(item);
-    },
 
     
-    addMenuItem : function(config){
-        return this.add(this.getMenuItem(config));
-    },
+    
+});
+
+
+Ext.define('Ext.grid.RowNumberer', {
+    extend: 'Ext.grid.column.Column',
+    alias: 'widget.rownumberer',
 
     
-    addText : function(text){
-        return this.add(new Ext.menu.TextItem(text));
-    },
+    text: "&#160",
 
     
-    onDestroy : function(){
-        Ext.EventManager.removeResizeListener(this.hide, this);
-        var pm = this.parentMenu;
-        if(pm && pm.activeChild == this){
-            delete pm.activeChild;
-        }
-        delete this.parentMenu;
-        Ext.menu.Menu.superclass.onDestroy.call(this);
-        Ext.menu.MenuMgr.unregister(this);
-        if(this.keyNav) {
-            this.keyNav.disable();
-        }
-        var s = this.scroller;
-        if(s){
-            Ext.destroy(s.topRepeater, s.bottomRepeater, s.top, s.bottom);
-        }
-        Ext.destroy(
-            this.el,
-            this.focusEl,
-            this.ul
-        );
-    }
-});
+    width: 23,
 
-Ext.reg('menu', Ext.menu.Menu);
+    
+    sortable: false,
 
+    align: 'right',
 
-Ext.menu.MenuNav = Ext.extend(Ext.KeyNav, function(){
-    function up(e, m){
-        if(!m.tryActivate(m.items.indexOf(m.activeItem)-1, -1)){
-            m.tryActivate(m.items.length-1, -1);
-        }
-    }
-    function down(e, m){
-        if(!m.tryActivate(m.items.indexOf(m.activeItem)+1, 1)){
-            m.tryActivate(0, 1);
+    constructor : function(config){
+        this.callParent(arguments);
+        if (this.rowspan) {
+            this.renderer = Ext.Function.bind(this.renderer, this);
         }
-    }
-    return {
-        constructor : function(menu){
-            Ext.menu.MenuNav.superclass.constructor.call(this, menu.el);
-            this.scope = this.menu = menu;
-        },
+    },
 
-        doRelay : function(e, h){
-            var k = e.getKey();
+    
+    resizable: false,
+    hideable: false,
+    menuDisabled: true,
+    dataIndex: '',
+    cls: Ext.baseCSSPrefix + 'row-numberer',
+    rowspan: undefined,
 
-            if (this.menu.activeItem && this.menu.activeItem.isFormField && k != e.TAB) {
-                return false;
-            }
-            if(!this.menu.activeItem && e.isNavKeyPress() && k != e.SPACE && k != e.RETURN){
-                this.menu.tryActivate(0, 1);
-                return false;
-            }
-            return h.call(this.scope || this, e, this.menu);
-        },
+    
+    renderer: function(value, metaData, record, rowIdx, colIdx, store) {
+        if (this.rowspan){
+            metaData.cellAttr = 'rowspan="'+this.rowspan+'"';
+        }
 
-        tab: function(e, m) {
-            e.stopEvent();
-            if (e.shiftKey) {
-                up(e, m);
-            } else {
-                down(e, m);
-            }
-        },
+        metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
+        return store.indexOfTotal(record) + 1;
+    }
+});
 
-        up : up,
 
-        down : down,
+Ext.define('Ext.view.DropZone', {
+    extend: 'Ext.dd.DropZone',
 
-        right : function(e, m){
-            if(m.activeItem){
-                m.activeItem.expandMenu(true);
-            }
-        },
+    indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
+    indicatorCls: 'x-grid-drop-indicator',
 
-        left : function(e, m){
-            m.hide();
-            if(m.parentMenu && m.parentMenu.activeItem){
-                m.parentMenu.activeItem.activate();
-            }
-        },
+    constructor: function(config) {
+        var me = this;
+        Ext.apply(me, config);
 
-        enter : function(e, m){
-            if(m.activeItem){
-                e.stopPropagation();
-                m.activeItem.onClick(e);
-                m.fireEvent('click', this, m.activeItem);
-                return true;
-            }
+        
+        
+        
+        
+        
+        if (!me.ddGroup) {
+            me.ddGroup = 'view-dd-zone-' + me.view.id;
         }
-    };
-}());
-
-Ext.menu.MenuMgr = function(){
-   var menus, active, groups = {}, attached = false, lastShow = new Date();
-
-   
-   function init(){
-       menus = {};
-       active = new Ext.util.MixedCollection();
-       Ext.getDoc().addKeyListener(27, function(){
-           if(active.length > 0){
-               hideAll();
-           }
-       });
-   }
 
-   
-   function hideAll(){
-       if(active && active.length > 0){
-           var c = active.clone();
-           c.each(function(m){
-               m.hide();
-           });
-           return true;
-       }
-       return false;
-   }
+        
+        
+        
+        me.callParent([me.view.el]);
+    },
 
-   
-   function onHide(m){
-       active.remove(m);
-       if(active.length < 1){
-           Ext.getDoc().un("mousedown", onMouseDown);
-           attached = false;
-       }
-   }
 
-   
-   function onShow(m){
-       var last = active.last();
-       lastShow = new Date();
-       active.add(m);
-       if(!attached){
-           Ext.getDoc().on("mousedown", onMouseDown);
-           attached = true;
-       }
-       if(m.parentMenu){
-          m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
-          m.parentMenu.activeChild = m;
-       }else if(last && !last.isDestroyed && last.isVisible()){
-          m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
-       }
-   }
 
-   
-   function onBeforeHide(m){
-       if(m.activeChild){
-           m.activeChild.hide();
-       }
-       if(m.autoHideTimer){
-           clearTimeout(m.autoHideTimer);
-           delete m.autoHideTimer;
-       }
-   }
+    fireViewEvent: function() {
+        var me = this,
+            result;
 
-   
-   function onBeforeShow(m){
-       var pm = m.parentMenu;
-       if(!pm && !m.allowOtherMenus){
-           hideAll();
-       }else if(pm && pm.activeChild){
-           pm.activeChild.hide();
-       }
-   }
+        me.lock();
+        result = me.view.fireEvent.apply(me.view, arguments);
+        me.unlock();
+        return result;
+    },
 
-   
-   function onMouseDown(e){
-       if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
-           hideAll();
-       }
-   }
+    getTargetFromEvent : function(e) {
+        var node = e.getTarget(this.view.getItemSelector()),
+            mouseY, nodeList, testNode, i, len, box;
 
-   
-   function onBeforeCheck(mi, state){
-       if(state){
-           var g = groups[mi.group];
-           for(var i = 0, l = g.length; i < l; i++){
-               if(g[i] != mi){
-                   g[i].setChecked(false);
-               }
-           }
-       }
-   }
 
-   return {
 
-       
-       hideAll : function(){
-            return hideAll();
-       },
+        if (!node) {
+            mouseY = e.getPageY();
+            for (i = 0, nodeList = this.view.getNodes(), len = nodeList.length; i < len; i++) {
+                testNode = nodeList[i];
+                box = Ext.fly(testNode).getBox();
+                if (mouseY <= box.bottom) {
+                    return testNode;
+                }
+            }
+        }
+        return node;
+    },
 
-       
-       register : function(menu){
-           if(!menus){
-               init();
-           }
-           menus[menu.id] = menu;
-           menu.on({
-               beforehide: onBeforeHide,
-               hide: onHide,
-               beforeshow: onBeforeShow,
-               show: onShow
-           });
-       },
-
-        
-       get : function(menu){
-           if(typeof menu == "string"){ 
-               if(!menus){  
-                   return null;
-               }
-               return menus[menu];
-           }else if(menu.events){  
-               return menu;
-           }else if(typeof menu.length == 'number'){ 
-               return new Ext.menu.Menu({items:menu});
-           }else{ 
-               return Ext.create(menu, 'menu');
-           }
-       },
+    getIndicator: function() {
+        var me = this;
 
-       
-       unregister : function(menu){
-           delete menus[menu.id];
-           menu.un("beforehide", onBeforeHide);
-           menu.un("hide", onHide);
-           menu.un("beforeshow", onBeforeShow);
-           menu.un("show", onShow);
-       },
+        if (!me.indicator) {
+            me.indicator = Ext.createWidget('component', {
+                html: me.indicatorHtml,
+                cls: me.indicatorCls,
+                ownerCt: me.view,
+                floating: true,
+                shadow: false
+            });
+        }
+        return me.indicator;
+    },
 
-       
-       registerCheckable : function(menuItem){
-           var g = menuItem.group;
-           if(g){
-               if(!groups[g]){
-                   groups[g] = [];
-               }
-               groups[g].push(menuItem);
-               menuItem.on("beforecheckchange", onBeforeCheck);
-           }
-       },
+    getPosition: function(e, node) {
+        var y      = e.getXY()[1],
+            region = Ext.fly(node).getRegion(),
+            pos;
 
-       
-       unregisterCheckable : function(menuItem){
-           var g = menuItem.group;
-           if(g){
-               groups[g].remove(menuItem);
-               menuItem.un("beforecheckchange", onBeforeCheck);
-           }
-       },
-
-       getCheckedItem : function(groupId){
-           var g = groups[groupId];
-           if(g){
-               for(var i = 0, l = g.length; i < l; i++){
-                   if(g[i].checked){
-                       return g[i];
-                   }
-               }
-           }
-           return null;
-       },
-
-       setCheckedItem : function(groupId, itemId){
-           var g = groups[groupId];
-           if(g){
-               for(var i = 0, l = g.length; i < l; i++){
-                   if(g[i].id == itemId){
-                       g[i].setChecked(true);
-                   }
-               }
-           }
-           return null;
-       }
-   };
-}();
+        if ((region.bottom - y) >= (region.bottom - region.top) / 2) {
+            pos = "before";
+        } else {
+            pos = "after";
+        }
+        return pos;
+    },
 
-Ext.menu.BaseItem = Ext.extend(Ext.Component, {
-    
-    
-    
-    
-    canActivate : false,
-    
-    activeClass : "x-menu-item-active",
-    
-    hideOnClick : true,
     
-    clickHideDelay : 1,
+    containsRecordAtOffset: function(records, record, offset) {
+        if (!record) {
+            return false;
+        }
+        var view = this.view,
+            recordIndex = view.indexOf(record),
+            nodeBefore = view.getNode(recordIndex + offset),
+            recordBefore = nodeBefore ? view.getRecord(nodeBefore) : null;
 
-    
-    ctype : "Ext.menu.BaseItem",
+        return recordBefore && Ext.Array.contains(records, recordBefore);
+    },
 
-    
-    actionMode : "container",
+    positionIndicator: function(node, data, e) {
+        var me = this,
+            view = me.view,
+            pos = me.getPosition(e, node),
+            overRecord = view.getRecord(node),
+            draggingRecords = data.records,
+            indicator, indicatorY;
+
+        if (!Ext.Array.contains(draggingRecords, overRecord) && (
+            pos == 'before' && !me.containsRecordAtOffset(draggingRecords, overRecord, -1) ||
+            pos == 'after' && !me.containsRecordAtOffset(draggingRecords, overRecord, 1)
+        )) {
+            me.valid = true;
+
+            if (me.overRecord != overRecord || me.currentPosition != pos) {
+
+                indicatorY = Ext.fly(node).getY() - view.el.getY() - 1;
+                if (pos == 'after') {
+                    indicatorY += Ext.fly(node).getHeight();
+                }
+                me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, indicatorY);
 
-    initComponent : function(){
-        Ext.menu.BaseItem.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'click',
-            
-            'activate',
-            
-            'deactivate'
-        );
-        if(this.handler){
-            this.on("click", this.handler, this.scope);
+                
+                me.overRecord = overRecord;
+                me.currentPosition = pos;
+            }
+        } else {
+            me.invalidateDrop();
         }
     },
 
-    
-    onRender : function(container, position){
-        Ext.menu.BaseItem.superclass.onRender.apply(this, arguments);
-        if(this.ownerCt && this.ownerCt instanceof Ext.menu.Menu){
-            this.parentMenu = this.ownerCt;
-        }else{
-            this.container.addClass('x-menu-list-item');
-            this.mon(this.el, {
-                scope: this,
-                click: this.onClick,
-                mouseenter: this.activate,
-                mouseleave: this.deactivate
-            });
+    invalidateDrop: function() {
+        if (this.valid) {
+            this.valid = false;
+            this.getIndicator().hide();
         }
     },
 
     
-    setHandler : function(handler, scope){
-        if(this.handler){
-            this.un("click", this.handler, this.scope);
+    onNodeOver: function(node, dragZone, e, data) {
+        var me = this;
+
+        if (!Ext.Array.contains(data.records, me.view.getRecord(node))) {
+            me.positionIndicator(node, data, e);
         }
-        this.on("click", this.handler = handler, this.scope = scope);
+        return me.valid ? me.dropAllowed : me.dropNotAllowed;
     },
 
     
-    onClick : function(e){
-        if(!this.disabled && this.fireEvent("click", this, e) !== false
-                && (this.parentMenu && this.parentMenu.fireEvent("itemclick", this, e) !== false)){
-            this.handleClick(e);
-        }else{
-            e.stopEvent();
+    
+    notifyOut: function(node, dragZone, e, data) {
+        var me = this;
+
+        me.callParent(arguments);
+        delete me.overRecord;
+        delete me.currentPosition;
+        if (me.indicator) {
+            me.indicator.hide();
         }
     },
 
     
-    activate : function(){
-        if(this.disabled){
-            return false;
+    onContainerOver : function(dd, e, data) {
+        var me = this,
+            view = me.view,
+            count = view.store.getCount();
+
+        
+        if (count) {
+            me.positionIndicator(view.getNode(count - 1), data, e);
         }
-        var li = this.container;
-        li.addClass(this.activeClass);
-        this.region = li.getRegion().adjust(2, 2, -2, -2);
-        this.fireEvent("activate", this);
-        return true;
+
+        
+        else {
+            delete me.overRecord;
+            delete me.currentPosition;
+            me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, 0);
+            me.valid = true;
+        }
+        return me.dropAllowed;
     },
 
-    
-    deactivate : function(){
-        this.container.removeClass(this.activeClass);
-        this.fireEvent("deactivate", this);
+    onContainerDrop : function(dd, e, data) {
+        return this.onNodeDrop(dd, null, e, data);
     },
 
-    
-    shouldDeactivate : function(e){
-        return !this.region || !this.region.contains(e.getPoint());
+    onNodeDrop: function(node, dragZone, e, data) {
+        var me = this,
+            dropped = false,
+
+            
+            
+            
+            
+            processDrop = function () {
+                me.invalidateDrop();
+                me.handleNodeDrop(data, me.overRecord, me.currentPosition);
+                dropped = true;
+                me.fireViewEvent('drop', node, data, me.overRecord, me.currentPosition);
+            },
+            performOperation = false;
+
+        if (me.valid) {
+            performOperation = me.fireViewEvent('beforedrop', node, data, me.overRecord, me.currentPosition, processDrop);
+            if (performOperation !== false) {
+                
+                if (!dropped) {
+                    processDrop();
+                }
+            }
+        }
+        return performOperation;
     },
+    
+    destroy: function(){
+        Ext.destroy(this.indicator);
+        delete this.indicator;
+        this.callParent();
+    }
+});
+
+Ext.define('Ext.grid.ViewDropZone', {
+    extend: 'Ext.view.DropZone',
+
+    indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
+    indicatorCls: 'x-grid-drop-indicator',
 
-    
-    handleClick : function(e){
-        var pm = this.parentMenu;
-        if(this.hideOnClick){
-            if(pm.floating){
-                pm.hide.defer(this.clickHideDelay, pm, [true]);
-            }else{
-                pm.deactivateActive();
+    handleNodeDrop : function(data, record, position) {
+        var view = this.view,
+            store = view.getStore(),
+            index, records, i, len;
+
+        
+        if (data.copy) {
+            records = data.records;
+            data.records = [];
+            for (i = 0, len = records.length; i < len; i++) {
+                data.records.push(records[i].copy(records[i].getId()));
             }
+        } else {
+            
+            data.view.store.remove(data.records, data.view === view);
         }
-    },
 
-    
-    expandMenu : Ext.emptyFn,
+        index = store.indexOf(record);
 
-    
-    hideMenu : Ext.emptyFn
-});
-Ext.reg('menubaseitem', Ext.menu.BaseItem);
-Ext.menu.TextItem = Ext.extend(Ext.menu.BaseItem, {
-    
-    
-    hideOnClick : false,
-    
-    itemCls : "x-menu-text",
-    
-    constructor : function(config){
-        if(typeof config == 'string'){
-            config = {text: config}
+        
+        if (position !== 'before') {
+            index++;
         }
-        Ext.menu.TextItem.superclass.constructor.call(this, config);
-    },
-
-    
-    onRender : function(){
-        var s = document.createElement("span");
-        s.className = this.itemCls;
-        s.innerHTML = this.text;
-        this.el = s;
-        Ext.menu.TextItem.superclass.onRender.apply(this, arguments);
+        store.insert(index, data.records);
+        view.getSelectionModel().select(data.records);
     }
 });
-Ext.reg('menutextitem', Ext.menu.TextItem);
-Ext.menu.Separator = Ext.extend(Ext.menu.BaseItem, {
-    
-    itemCls : "x-menu-sep",
-    
-    hideOnClick : false,
-    
-    
-    activeClass: '',
 
-    
-    onRender : function(li){
-        var s = document.createElement("span");
-        s.className = this.itemCls;
-        s.innerHTML = "&#160;";
-        this.el = s;
-        li.addClass("x-menu-sep-li");
-        Ext.menu.Separator.superclass.onRender.apply(this, arguments);
-    }
-});
-Ext.reg('menuseparator', Ext.menu.Separator);
-Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
-    
+Ext.define('Ext.grid.column.Action', {
+    extend: 'Ext.grid.column.Column',
+    alias: ['widget.actioncolumn'],
+    alternateClassName: 'Ext.grid.ActionColumn',
+
     
     
     
@@ -36794,11011 +81303,11791 @@ Ext.menu.Item = Ext.extend(Ext.menu.BaseItem, {
     
     
     
-    itemCls : 'x-menu-item',
     
-    canActivate : true,
     
-    showDelay: 200,
     
-    hideDelay: 200,
+    header: '&#160;',
+
+    actionIdRe: new RegExp(Ext.baseCSSPrefix + 'action-col-(\\d+)'),
 
     
-    ctype: 'Ext.menu.Item',
+    altText: '',
 
-    initComponent : function(){
-        Ext.menu.Item.superclass.initComponent.call(this);
-        if(this.menu){
-            this.menu = Ext.menu.MenuMgr.get(this.menu);
-            this.menu.ownerCt = this;
-        }
-    },
+    sortable: false,
 
-    
-    onRender : function(container, position){
-        if (!this.itemTpl) {
-            this.itemTpl = Ext.menu.Item.prototype.itemTpl = new Ext.XTemplate(
-                '<a id="{id}" class="{cls}" hidefocus="true" unselectable="on" href="{href}"',
-                    '<tpl if="hrefTarget">',
-                        ' target="{hrefTarget}"',
-                    '</tpl>',
-                 '>',
-                     '<img src="{icon}" class="x-menu-item-icon {iconCls}"/>',
-                     '<span class="x-menu-item-text">{text}</span>',
-                 '</a>'
-             );
-        }
-        var a = this.getTemplateArgs();
-        this.el = position ? this.itemTpl.insertBefore(position, a, true) : this.itemTpl.append(container, a, true);
-        this.iconEl = this.el.child('img.x-menu-item-icon');
-        this.textEl = this.el.child('.x-menu-item-text');
-        if(!this.href) { 
-            this.mon(this.el, 'click', Ext.emptyFn, null, { preventDefault: true });
-        }
-        Ext.menu.Item.superclass.onRender.call(this, container, position);
-    },
+    constructor: function(config) {
+        var me = this,
+            cfg = Ext.apply({}, config),
+            items = cfg.items || [me],
+            l = items.length,
+            i,
+            item;
 
-    getTemplateArgs: function() {
-        return {
-            id: this.id,
-            cls: this.itemCls + (this.menu ?  ' x-menu-item-arrow' : '') + (this.cls ?  ' ' + this.cls : ''),
-            href: this.href || '#',
-            hrefTarget: this.hrefTarget,
-            icon: this.icon || Ext.BLANK_IMAGE_URL,
-            iconCls: this.iconCls || '',
-            text: this.itemText||this.text||'&#160;'
+        
+        delete cfg.items;
+        me.callParent([cfg]);
+
+        
+        me.items = items;
+
+
+
+        me.renderer = function(v, meta) {
+
+            v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
+
+            meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
+            for (i = 0; i < l; i++) {
+                item = items[i];
+                item.disable = Ext.Function.bind(me.disableAction, me, [i]);
+                item.enable = Ext.Function.bind(me.enableAction, me, [i]);
+                v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
+                    '" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' + (item.disabled ? Ext.baseCSSPrefix + 'item-disabled' : ' ') + (item.iconCls || '') +
+                    ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || '')) + '"' +
+                    ((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
+            }
+            return v;
         };
     },
 
     
-    setText : function(text){
-        this.text = text||'&#160;';
-        if(this.rendered){
-            this.textEl.update(this.text);
-            this.parentMenu.layout.doAutoSize();
-        }
-    },
+    enableAction: function(index) {
+        var me = this;
 
-    
-    setIconClass : function(cls){
-        var oldCls = this.iconCls;
-        this.iconCls = cls;
-        if(this.rendered){
-            this.iconEl.replaceClass(oldCls, this.iconCls);
+        if (!index) {
+            index = 0;
+        } else if (!Ext.isNumber(index)) {
+            index = Ext.Array.indexOf(me.items, index);
         }
+        me.items[index].disabled = false;
+        me.up('tablepanel').el.select('.' + Ext.baseCSSPrefix + 'action-col-' + index).removeCls(me.disabledCls);
     },
 
     
-    beforeDestroy: function(){
-        if (this.menu){
-            delete this.menu.ownerCt;
-            this.menu.destroy();
-        }
-        Ext.menu.Item.superclass.beforeDestroy.call(this);
-    },
+    disableAction: function(index) {
+        var me = this;
 
-    
-    handleClick : function(e){
-        if(!this.href){ 
-            e.stopEvent();
+        if (!index) {
+            index = 0;
+        } else if (!Ext.isNumber(index)) {
+            index = Ext.Array.indexOf(me.items, index);
         }
-        Ext.menu.Item.superclass.handleClick.apply(this, arguments);
+        me.items[index].disabled = true;
+        me.up('tablepanel').el.select('.' + Ext.baseCSSPrefix + 'action-col-' + index).addCls(me.disabledCls);
     },
 
-    
-    activate : function(autoExpand){
-        if(Ext.menu.Item.superclass.activate.apply(this, arguments)){
-            this.focus();
-            if(autoExpand){
-                this.expandMenu();
-            }
-        }
-        return true;
+    destroy: function() {
+        delete this.items;
+        delete this.renderer;
+        return this.callParent(arguments);
     },
 
     
-    shouldDeactivate : function(e){
-        if(Ext.menu.Item.superclass.shouldDeactivate.call(this, e)){
-            if(this.menu && this.menu.isVisible()){
-                return !this.menu.getEl().getRegion().contains(e.getPoint());
+    processEvent : function(type, view, cell, recordIndex, cellIndex, e){
+        var me = this,
+            match = e.getTarget().className.match(me.actionIdRe),
+            item, fn;
+            
+        if (match) {
+            item = me.items[parseInt(match[1], 10)];
+            if (item) {
+                if (type == 'click') {
+                    fn = item.handler || me.handler;
+                    if (fn && !item.disabled) {
+                        fn.call(item.scope || me.scope || me, view, recordIndex, cellIndex, item, e);
+                    }
+                } else if (type == 'mousedown' && item.stopSelection !== false) {
+                    return false;
+                }
             }
-            return true;
         }
-        return false;
+        return me.callParent(arguments);
     },
 
-    
-    deactivate : function(){
-        Ext.menu.Item.superclass.deactivate.apply(this, arguments);
-        this.hideMenu();
+    cascade: function(fn, scope) {
+        fn.call(scope||this, this);
     },
 
     
-    expandMenu : function(autoActivate){
-        if(!this.disabled && this.menu){
-            clearTimeout(this.hideTimer);
-            delete this.hideTimer;
-            if(!this.menu.isVisible() && !this.showTimer){
-                this.showTimer = this.deferExpand.defer(this.showDelay, this, [autoActivate]);
-            }else if (this.menu.isVisible() && autoActivate){
-                this.menu.tryActivate(0, 1);
-            }
-        }
-    },
+    getRefItems: function() {
+        return [];
+    }
+});
+
+Ext.define('Ext.grid.column.Boolean', {
+    extend: 'Ext.grid.column.Column',
+    alias: ['widget.booleancolumn'],
+    alternateClassName: 'Ext.grid.BooleanColumn',
 
     
-    deferExpand : function(autoActivate){
-        delete this.showTimer;
-        this.menu.show(this.container, this.parentMenu.subMenuAlign || 'tl-tr?', this.parentMenu);
-        if(autoActivate){
-            this.menu.tryActivate(0, 1);
-        }
-    },
+    trueText: 'true',
 
     
-    hideMenu : function(){
-        clearTimeout(this.showTimer);
-        delete this.showTimer;
-        if(!this.hideTimer && this.menu && this.menu.isVisible()){
-            this.hideTimer = this.deferHide.defer(this.hideDelay, this);
-        }
-    },
+    falseText: 'false',
 
     
-    deferHide : function(){
-        delete this.hideTimer;
-        if(this.menu.over){
-            this.parentMenu.setActiveItem(this, false);
-        }else{
-            this.menu.hide();
-        }
+    undefinedText: '&#160;',
+
+    constructor: function(cfg){
+        this.callParent(arguments);
+        var trueText      = this.trueText,
+            falseText     = this.falseText,
+            undefinedText = this.undefinedText;
+
+        this.renderer = function(value){
+            if(value === undefined){
+                return undefinedText;
+            }
+            if(!value || value === 'false'){
+                return falseText;
+            }
+            return trueText;
+        };
     }
 });
-Ext.reg('menuitem', Ext.menu.Item);
-Ext.menu.CheckItem = Ext.extend(Ext.menu.Item, {
-    
-    
-    itemCls : "x-menu-item x-menu-check-item",
-    
-    groupClass : "x-menu-group-item",
 
-    
-    checked: false,
+Ext.define('Ext.grid.column.Date', {
+    extend: 'Ext.grid.column.Column',
+    alias: ['widget.datecolumn'],
+    requires: ['Ext.Date'],
+    alternateClassName: 'Ext.grid.DateColumn',
 
     
-    ctype: "Ext.menu.CheckItem",
-    
-    initComponent : function(){
-        Ext.menu.CheckItem.superclass.initComponent.call(this);
-           this.addEvents(
-               
-               "beforecheckchange" ,
-               
-               "checkchange"
-           );
-           
-           if(this.checkHandler){
-               this.on('checkchange', this.checkHandler, this.scope);
-           }
-           Ext.menu.MenuMgr.registerCheckable(this);
-    },
 
-    
-    onRender : function(c){
-        Ext.menu.CheckItem.superclass.onRender.apply(this, arguments);
-        if(this.group){
-            this.el.addClass(this.groupClass);
-        }
-        if(this.checked){
-            this.checked = false;
-            this.setChecked(true, true);
+    initComponent: function(){
+        var me = this;
+        
+        me.callParent(arguments);
+        if (!me.format) {
+            me.format = Ext.Date.defaultFormat;
         }
-    },
+        me.renderer = Ext.util.Format.dateRenderer(me.format);
+    }
+});
 
-    
-    destroy : function(){
-        Ext.menu.MenuMgr.unregisterCheckable(this);
-        Ext.menu.CheckItem.superclass.destroy.apply(this, arguments);
-    },
+Ext.define('Ext.grid.column.Number', {
+    extend: 'Ext.grid.column.Column',
+    alias: ['widget.numbercolumn'],
+    requires: ['Ext.util.Format'],
+    alternateClassName: 'Ext.grid.NumberColumn',
 
     
-    setChecked : function(state, suppressEvent){
-        var suppress = suppressEvent === true;
-        if(this.checked != state && (suppress || this.fireEvent("beforecheckchange", this, state) !== false)){
-            if(this.container){
-                this.container[state ? "addClass" : "removeClass"]("x-menu-item-checked");
-            }
-            this.checked = state;
-            if(!suppress){
-                this.fireEvent("checkchange", this, state);
-            }
-        }
-    },
+    format : '0,000.00',
+
+    constructor: function(cfg) {
+        this.callParent(arguments);
+        this.renderer = Ext.util.Format.numberRenderer(this.format);
+    }
+});
+
+Ext.define('Ext.grid.column.Template', {
+    extend: 'Ext.grid.column.Column',
+    alias: ['widget.templatecolumn'],
+    requires: ['Ext.XTemplate'],
+    alternateClassName: 'Ext.grid.TemplateColumn',
 
     
-    handleClick : function(e){
-       if(!this.disabled && !(this.checked && this.group)){
-           this.setChecked(!this.checked);
-       }
-       Ext.menu.CheckItem.superclass.handleClick.apply(this, arguments);
+
+    constructor: function(cfg){
+        var me = this,
+            tpl;
+            
+        me.callParent(arguments);
+        tpl = me.tpl = (!Ext.isPrimitive(me.tpl) && me.tpl.compile) ? me.tpl : Ext.create('Ext.XTemplate', me.tpl);
+
+        me.renderer = function(value, p, record) {
+            var data = Ext.apply({}, record.data, record.getAssociatedData());
+            return tpl.apply(data);
+        };
     }
 });
-Ext.reg('menucheckitem', Ext.menu.CheckItem);
- Ext.menu.DateMenu = Ext.extend(Ext.menu.Menu, {
+
+
+Ext.define('Ext.grid.feature.Feature', {
+    extend: 'Ext.util.Observable',
+    alias: 'feature.feature',
     
-    enableScrolling : false,
+    isFeature: true,
+    disabled: false,
     
-        
     
-    hideOnClick : true,
+    hasFeatureEvent: true,
     
     
-    pickerId : null,
+    eventPrefix: null,
     
     
+    eventSelector: null,
     
     
-    cls : 'x-date-menu',
+    view: null,
     
     
+    grid: null,
     
     
-
-    initComponent : function(){
-        this.on('beforeshow', this.onBeforeShow, this);
-        if(this.strict = (Ext.isIE7 && Ext.isStrict)){
-            this.on('show', this.onShow, this, {single: true, delay: 20});
-        }
-        Ext.apply(this, {
-            plain: true,
-            showSeparator: false,
-            items: this.picker = new Ext.DatePicker(Ext.applyIf({
-                internalRender: this.strict || !Ext.isIE,
-                ctCls: 'x-menu-date-item',
-                id: this.pickerId
-            }, this.initialConfig))
-        });
-        this.picker.purgeListeners();
-        Ext.menu.DateMenu.superclass.initComponent.call(this);
-        
-        this.relayEvents(this.picker, ['select']);
-        this.on('show', this.picker.focus, this.picker);
-        this.on('select', this.menuHide, this);
-        if(this.handler){
-            this.on('select', this.handler, this.scope || this);
-        }
+    collectData: false,
+        
+    getFeatureTpl: function() {
+        return '';
     },
-
-    menuHide : function() {
-        if(this.hideOnClick){
-            this.hide(true);
-        }
+    
+    
+    getFireEventArgs: function(eventName, view, featureTarget, e) {
+        return [eventName, view, featureTarget, e];
     },
-
-    onBeforeShow : function(){
-        if(this.picker){
-            this.picker.hideMonthPicker(true);
-        }
+    
+    
+    attachEvents: function() {
+        
+    },
+    
+    getFragmentTpl: function() {
+        return;
     },
-
-    onShow : function(){
-        var el = this.picker.getEl();
-        el.setWidth(el.getWidth()); 
-    }
- });
- Ext.reg('datemenu', Ext.menu.DateMenu);
- Ext.menu.ColorMenu = Ext.extend(Ext.menu.Menu, {
     
-    enableScrolling : false,
     
+    mutateMetaRowTpl: function(metaRowTplArray) {
         
+    },
     
     
-    hideOnClick : true,
+    getMetaRowTplFragments: function() {
+        return {};
+    },
+
+    getTableFragments: function() {
+        return {};
+    },
     
-    cls : 'x-color-menu',
     
+    getAdditionalData: function(data, idx, record, orig) {
+        return {};
+    },
     
-    paletteId : null,
     
+    enable: function() {
+        this.disabled = false;
+    },
     
     
+    disable: function() {
+        this.disabled = true;
+    }
     
+});
+
+Ext.define('Ext.grid.feature.AbstractSummary', {
     
     
+   
+    extend: 'Ext.grid.feature.Feature',
     
+    alias: 'feature.abstractsummary',
+   
     
+   
+   
+    showSummaryRow: true,
     
     
-    initComponent : function(){
-        Ext.apply(this, {
-            plain: true,
-            showSeparator: false,
-            items: this.palette = new Ext.ColorPalette(Ext.applyIf({
-                id: this.paletteId
-            }, this.initialConfig))
-        });
-        this.palette.purgeListeners();
-        Ext.menu.ColorMenu.superclass.initComponent.call(this);
-        
-        this.relayEvents(this.palette, ['select']);
-        this.on('select', this.menuHide, this);
-        if(this.handler){
-            this.on('select', this.handler, this.scope || this);
-        }
+    nestedIdRe: /\{\{id\}([\w\-]*)\}/g,
+    
+    
+    toggleSummaryRow: function(visible){
+        this.showSummaryRow = !!visible;
     },
-
-    menuHide : function(){
-        if(this.hideOnClick){
-            this.hide(true);
-        }
-    }
-});
-Ext.reg('colormenu', Ext.menu.ColorMenu);
-
-Ext.form.Field = Ext.extend(Ext.BoxComponent,  {
     
     
+    getSummaryFragments: function(){
+        var fragments = {};
+        if (this.showSummaryRow) {
+            Ext.apply(fragments, {
+                printSummaryRow: Ext.bind(this.printSummaryRow, this)
+            });
+        }
+        return fragments;
+    },
     
     
+    printSummaryRow: function(index){
+        var inner = this.view.getTableChunker().metaRowTpl.join(''),
+            prefix = Ext.baseCSSPrefix;
+        
+        inner = inner.replace(prefix + 'grid-row', prefix + 'grid-row-summary');
+        inner = inner.replace('{{id}}', '{gridSummaryValue}');
+        inner = inner.replace(this.nestedIdRe, '{id$1}');  
+        inner = inner.replace('{[this.embedRowCls()]}', '{rowCls}');
+        inner = inner.replace('{[this.embedRowAttr()]}', '{rowAttr}');
+        inner = Ext.create('Ext.XTemplate', inner, {
+            firstOrLastCls: Ext.view.TableChunker.firstOrLastCls
+        });
+        
+        return inner.applyTemplate({
+            columns: this.getPrintData(index)
+        });
+    },
     
     
+    getColumnValue: function(column, summaryData){
+        var comp     = Ext.getCmp(column.id),
+            value    = summaryData[column.id],
+            renderer = comp.summaryRenderer;
 
+        if (renderer) {
+            value = renderer.call(
+                comp.scope || this,
+                value,
+                summaryData,
+                column.dataIndex
+            );
+        }
+        return value;
+    },
     
-    invalidClass : 'x-form-invalid',
     
-    invalidText : 'The value in this field is invalid',
+    getSummary: function(store, type, field, group){
+        if (type) {
+            if (Ext.isFunction(type)) {
+                return store.aggregate(type, null, group);
+            }
+            
+            switch (type) {
+                case 'count':
+                    return store.count(group);
+                case 'min':
+                    return store.min(field, group);
+                case 'max':
+                    return store.max(field, group);
+                case 'sum':
+                    return store.sum(field, group);
+                case 'average':
+                    return store.average(field, group);
+                default:
+                    return group ? {} : '';
+                    
+            }
+        }
+    }
     
-    focusClass : 'x-form-focus',
+});
+
+
+Ext.define('Ext.grid.feature.Chunking', {
+    extend: 'Ext.grid.feature.Feature',
+    alias: 'feature.chunking',
     
+    chunkSize: 20,
+    rowHeight: Ext.isIE ? 27 : 26,
+    visibleChunk: 0,
+    hasFeatureEvent: false,
+    attachEvents: function() {
+        var grid = this.view.up('gridpanel'),
+            scroller = grid.down('gridscroller[dock=right]');
+        scroller.el.on('scroll', this.onBodyScroll, this, {buffer: 300});
+        
+    },
     
-    validationEvent : 'keyup',
+    onBodyScroll: function(e, t) {
+        var view = this.view,
+            top  = t.scrollTop,
+            nextChunk = Math.floor(top / this.rowHeight / this.chunkSize);
+        if (nextChunk !== this.visibleChunk) {
+        
+            this.visibleChunk = nextChunk;
+            view.refresh();
+            view.el.dom.scrollTop = top;
+            
+            view.el.dom.scrollTop = top;
+        }
+    },
     
-    validateOnBlur : true,
+    collectData: function(records, preppedRecords, startIndex, fullWidth, orig) {
+        var o = {
+            fullWidth: orig.fullWidth,
+            chunks: []
+        },
+        
+        
+        recordCount = orig.rows.length,
+        start = 0,
+        i = 0,
+        visibleChunk = this.visibleChunk,
+        chunk,
+        rows,
+        chunkLength;
+
+        for (; start < recordCount; start+=this.chunkSize, i++) {
+            if (start+this.chunkSize > recordCount) {
+                chunkLength = recordCount - start;
+            } else {
+                chunkLength = this.chunkSize;
+            }
+            
+            if (i >= visibleChunk - 1 && i <= visibleChunk + 1) {
+                rows = orig.rows.slice(start, start+this.chunkSize);
+            } else {
+                rows = [];
+            }
+            o.chunks.push({
+                rows: rows,
+                fullWidth: fullWidth,
+                chunkHeight: chunkLength * this.rowHeight
+            });
+        }
+        
+        
+        return o;
+    },
     
-    validationDelay : 250,
+    getTableFragments: function() {
+        return {
+            openTableWrap: function() {
+                return '<tpl for="chunks"><div class="' + Ext.baseCSSPrefix + 'grid-chunk" style="height: {chunkHeight}px;">';
+            },
+            closeTableWrap: function() {
+                return '</div></tpl>';
+            }
+        };
+    }
+});
+
+
+Ext.define('Ext.grid.feature.Grouping', {
+    extend: 'Ext.grid.feature.Feature',
+    alias: 'feature.grouping',
+
+    eventPrefix: 'group',
+    eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd',
+
+    constructor: function() {
+        var me = this;
+        
+        me.collapsedState = {};
+        me.callParent(arguments);
+    },
     
-    defaultAutoCreate : {tag: 'input', type: 'text', size: '20', autocomplete: 'off'},
     
-    fieldClass : 'x-form-field',
+
     
-    msgTarget : 'qtip',
+
     
-    msgFx : 'normal',
+
     
-    readOnly : false,
+
     
-    disabled : false,
+
     
-    submitValue: true,
+    groupHeaderTpl: 'Group: {name}',
 
     
-    isFormField : true,
+    depthToIndent: 17,
 
+    collapsedCls: Ext.baseCSSPrefix + 'grid-group-collapsed',
+    hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed',
+
+    
+    groupByText : 'Group By This Field',
     
-    msgDisplay: '',
+    showGroupsText : 'Show in Groups',
 
     
-    hasFocus : false,
+    hideGroupedHeader : false,
 
     
-    initComponent : function(){
-        Ext.form.Field.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'focus',
-            
-            'blur',
-            
-            'specialkey',
-            
-            'change',
-            
-            'invalid',
-            
-            'valid'
-        );
-    },
+    startCollapsed : false,
 
     
-    getName : function(){
-        return this.rendered && this.el.dom.name ? this.el.dom.name : this.name || this.id || '';
-    },
+    enableGroupingMenu : true,
 
     
-    onRender : function(ct, position){
-        if(!this.el){
-            var cfg = this.getAutoCreate();
+    enableNoGroups : true,
+    
+    enable: function() {
+        var me    = this,
+            view  = me.view,
+            store = view.store,
+            groupToggleMenuItem;
+            
+        me.lastGroupField = me.getGroupField();
 
-            if(!cfg.name){
-                cfg.name = this.name || this.id;
-            }
-            if(this.inputType){
-                cfg.type = this.inputType;
-            }
-            this.autoEl = cfg;
-        }
-        Ext.form.Field.superclass.onRender.call(this, ct, position);
-        if(this.submitValue === false){
-            this.el.dom.removeAttribute('name');
-        }
-        var type = this.el.dom.type;
-        if(type){
-            if(type == 'password'){
-                type = 'text';
-            }
-            this.el.addClass('x-form-'+type);
+        if (me.lastGroupIndex) {
+            store.group(me.lastGroupIndex);
         }
-        if(this.readOnly){
-            this.setReadOnly(true);
+        me.callParent();
+        groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
+        groupToggleMenuItem.setChecked(true, true);
+        me.refreshIf();
+    },
+
+    disable: function() {
+        var me    = this,
+            view  = me.view,
+            store = view.store,
+            remote = store.remoteGroup,
+            groupToggleMenuItem,
+            lastGroup;
+            
+        lastGroup = store.groupers.first();
+        if (lastGroup) {
+            me.lastGroupIndex = lastGroup.property;
+            me.block();
+            store.clearGrouping();
+            me.unblock();
         }
-        if(this.tabIndex !== undefined){
-            this.el.dom.setAttribute('tabIndex', this.tabIndex);
+        
+        me.callParent();
+        groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
+        groupToggleMenuItem.setChecked(true, true);
+        groupToggleMenuItem.setChecked(false, true);
+        if (!remote) {
+            view.refresh();
         }
-
-        this.el.addClass([this.fieldClass, this.cls]);
     },
-
     
-    getItemCt : function(){
-        return this.itemCt;
+    refreshIf: function() {
+        if (this.blockRefresh !== true) {
+            this.view.refresh();
+        }    
     },
 
-    
-    initValue : function(){
-        if(this.value !== undefined){
-            this.setValue(this.value);
-        }else if(!Ext.isEmpty(this.el.dom.value) && this.el.dom.value != this.emptyText){
-            this.setValue(this.el.dom.value);
-        }
+    getFeatureTpl: function(values, parent, x, xcount) {
+        var me = this;
         
-        this.originalValue = this.getValue();
+        return [
+            '<tpl if="typeof rows !== \'undefined\'">',
+                
+                '<tr class="' + Ext.baseCSSPrefix + 'grid-group-hd ' + (me.startCollapsed ? me.hdCollapsedCls : '') + ' {hdCollapsedCls}"><td class="' + Ext.baseCSSPrefix + 'grid-cell" colspan="' + parent.columns.length + '" {[this.indentByDepth(values)]}><div class="' + Ext.baseCSSPrefix + 'grid-cell-inner"><div class="' + Ext.baseCSSPrefix + 'grid-group-title">{collapsed}' + me.groupHeaderTpl + '</div></div></td></tr>',
+                
+                '<tr id="{viewId}-gp-{name}" class="' + Ext.baseCSSPrefix + 'grid-group-body ' + (me.startCollapsed ? me.collapsedCls : '') + ' {collapsedCls}"><td colspan="' + parent.columns.length + '">{[this.recurse(values)]}</td></tr>',
+            '</tpl>'
+        ].join('');
     },
 
-    
-    isDirty : function() {
-        if(this.disabled || !this.rendered) {
-            return false;
-        }
-        return String(this.getValue()) !== String(this.originalValue);
+    getFragmentTpl: function() {
+        return {
+            indentByDepth: this.indentByDepth,
+            depthToIndent: this.depthToIndent
+        };
     },
 
-    
-    setReadOnly : function(readOnly){
-        if(this.rendered){
-            this.el.dom.readOnly = readOnly;
-        }
-        this.readOnly = readOnly;
+    indentByDepth: function(values) {
+        var depth = values.depth || 0;
+        return 'style="padding-left:'+ depth * this.depthToIndent + 'px;"';
     },
 
     
-    afterRender : function(){
-        Ext.form.Field.superclass.afterRender.call(this);
-        this.initEvents();
-        this.initValue();
+    
+    destroy: function() {
+        var me = this;
+        
+        delete me.view;
+        delete me.prunedHeader;
     },
 
     
-    fireKey : function(e){
-        if(e.isSpecialKey()){
-            this.fireEvent('specialkey', this, e);
+    attachEvents: function() {
+        var me = this,
+            view = me.view;
+
+        view.on({
+            scope: me,
+            groupclick: me.onGroupClick,
+            rowfocus: me.onRowFocus
+        });
+        view.store.on('groupchange', me.onGroupChange, me);
+
+        me.pruneGroupedHeader();
+
+        if (me.enableGroupingMenu) {
+            me.injectGroupingMenu();
         }
+        me.lastGroupField = me.getGroupField();
+        me.block();
+        me.onGroupChange();
+        me.unblock();
     },
-
     
-    reset : function(){
-        this.setValue(this.originalValue);
-        this.clearInvalid();
+    injectGroupingMenu: function() {
+        var me       = this,
+            view     = me.view,
+            headerCt = view.headerCt;
+        headerCt.showMenuBy = me.showMenuBy;
+        headerCt.getMenuItems = me.getMenuItems();
     },
-
     
-    initEvents : function(){
-        this.mon(this.el, Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.fireKey,  this);
-        this.mon(this.el, 'focus', this.onFocus, this);
-
+    showMenuBy: function(t, header) {
+        var menu = this.getMenu(),
+            groupMenuItem  = menu.down('#groupMenuItem'),
+            groupableMth = header.groupable === false ?  'disable' : 'enable';
+            
+        groupMenuItem[groupableMth]();
+        Ext.grid.header.Container.prototype.showMenuBy.apply(this, arguments);
+    },
+    
+    getMenuItems: function() {
+        var me                 = this,
+            groupByText        = me.groupByText,
+            disabled           = me.disabled,
+            showGroupsText     = me.showGroupsText,
+            enableNoGroups     = me.enableNoGroups,
+            groupMenuItemClick = Ext.Function.bind(me.onGroupMenuItemClick, me),
+            groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me);
         
         
-        this.mon(this.el, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
+        return function() {
+            var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
+            o.push('-', {
+                iconCls: Ext.baseCSSPrefix + 'group-by-icon',
+                itemId: 'groupMenuItem',
+                text: groupByText,
+                handler: groupMenuItemClick
+            });
+            if (enableNoGroups) {
+                o.push({
+                    itemId: 'groupToggleMenuItem',
+                    text: showGroupsText,
+                    checked: !disabled,
+                    checkHandler: groupToggleMenuItemClick
+                });
+            }
+            return o;
+        };
     },
 
+
     
-    preFocus: Ext.emptyFn,
+    onGroupMenuItemClick: function(menuItem, e) {
+        var me = this,
+            menu = menuItem.parentMenu,
+            hdr  = menu.activeHeader,
+            view = me.view,
+            store = view.store,
+            remote = store.remoteGroup;
 
+        delete me.lastGroupIndex;
+        me.block();
+        me.enable();
+        store.group(hdr.dataIndex);
+        me.pruneGroupedHeader();
+        me.unblock();
+        if (!remote) {
+            view.refresh();
+        }  
+    },
     
-    onFocus : function(){
-        this.preFocus();
-        if(this.focusClass){
-            this.el.addClass(this.focusClass);
-        }
-        if(!this.hasFocus){
-            this.hasFocus = true;
-            
-            this.startValue = this.getValue();
-            this.fireEvent('focus', this);
-        }
+    block: function(){
+        this.blockRefresh = this.view.blockRefresh = true;
     },
-
     
-    beforeBlur : Ext.emptyFn,
+    unblock: function(){
+        this.blockRefresh = this.view.blockRefresh = false;
+    },
 
     
-    onBlur : function(){
-        this.beforeBlur();
-        if(this.focusClass){
-            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.fireEvent('change', this, v, this.startValue);
-        }
-        this.fireEvent('blur', this);
-        this.postBlur();
+    onGroupToggleMenuItemClick: function(menuItem, checked) {
+        this[checked ? 'enable' : 'disable']();
     },
 
     
-    postBlur : Ext.emptyFn,
+    pruneGroupedHeader: function() {
+        var me         = this,
+            view       = me.view,
+            store      = view.store,
+            groupField = me.getGroupField(),
+            headerCt   = view.headerCt,
+            header     = headerCt.down('header[dataIndex=' + groupField + ']');
 
-    
-    isValid : function(preventMark){
-        if(this.disabled){
-            return true;
+        if (header) {
+            if (me.prunedHeader) {
+                me.prunedHeader.show();
+            }
+            me.prunedHeader = header;
+            header.hide();
         }
-        var restore = this.preventMark;
-        this.preventMark = preventMark === true;
-        var v = this.validateValue(this.processValue(this.getRawValue()));
-        this.preventMark = restore;
-        return v;
     },
 
-    
-    validate : function(){
-        if(this.disabled || this.validateValue(this.processValue(this.getRawValue()))){
-            this.clearInvalid();
-            return true;
+    getGroupField: function(){
+        var group = this.view.store.groupers.first();
+        if (group) {
+            return group.property;    
         }
-        return false;
+        return ''; 
     },
 
     
-    processValue : function(value){
-        return value;
+    onRowFocus: function(rowIdx) {
+        var node    = this.view.getNode(rowIdx),
+            groupBd = Ext.fly(node).up('.' + this.collapsedCls);
+
+        if (groupBd) {
+            
+            
+            this.expand(groupBd);
+        }
     },
 
     
-     validateValue : function(value) {
-         
-         var error = this.getErrors(value)[0];
+    expand: function(groupBd) {
+        var me = this,
+            view = me.view,
+            grid = view.up('gridpanel'),
+            groupBdDom = Ext.getDom(groupBd);
+            
+        me.collapsedState[groupBdDom.id] = false;
 
-         if (error == undefined) {
-             return true;
-         } else {
-             this.markInvalid(error);
-             return false;
-         }
-     },
-    
-    
-    getErrors: function() {
-        return [];
-    },
+        groupBd.removeCls(me.collapsedCls);
+        groupBd.prev().removeCls(me.hdCollapsedCls);
 
-    
-    getActiveError : function(){
-        return this.activeError || '';
+        grid.determineScrollbars();
+        grid.invalidateScroller();
+        view.fireEvent('groupexpand');
     },
 
     
-    markInvalid : function(msg){
-        
-        if (this.rendered && !this.preventMark) {
-            msg = msg || this.invalidText;
+    collapse: function(groupBd) {
+        var me = this,
+            view = me.view,
+            grid = view.up('gridpanel'),
+            groupBdDom = Ext.getDom(groupBd);
+            
+        me.collapsedState[groupBdDom.id] = true;
+
+        groupBd.addCls(me.collapsedCls);
+        groupBd.prev().addCls(me.hdCollapsedCls);
 
-            var mt = this.getMessageHandler();
-            if(mt){
-                mt.mark(this, msg);
-            }else if(this.msgTarget){
-                this.el.addClass(this.invalidClass);
-                var t = Ext.getDom(this.msgTarget);
-                if(t){
-                    t.innerHTML = msg;
-                    t.style.display = this.msgDisplay;
+        grid.determineScrollbars();
+        grid.invalidateScroller();
+        view.fireEvent('groupcollapse');
+    },
+    
+    onGroupChange: function(){
+        var me = this,
+            field = me.getGroupField(),
+            menuItem;
+            
+        if (me.hideGroupedHeader) {
+            if (me.lastGroupField) {
+                menuItem = me.getMenuItem(me.lastGroupField);
+                if (menuItem) {
+                    menuItem.setChecked(true);
+                }
+            }
+            if (field) {
+                menuItem = me.getMenuItem(field);
+                if (menuItem) {
+                    menuItem.setChecked(false);
                 }
             }
         }
-        
-        this.setActiveError(msg);
+        if (me.blockRefresh !== true) {
+            me.view.refresh();
+        }
+        me.lastGroupField = field;
     },
     
     
-    clearInvalid : function(){
-        
-        if (this.rendered && !this.preventMark) {
-            this.el.removeClass(this.invalidClass);
-            var mt = this.getMessageHandler();
-            if(mt){
-                mt.clear(this);
-            }else if(this.msgTarget){
-                this.el.removeClass(this.invalidClass);
-                var t = Ext.getDom(this.msgTarget);
-                if(t){
-                    t.innerHTML = '';
-                    t.style.display = 'none';
-                }
-            }
-        }
-        
-        this.unsetActiveError();
+    getMenuItem: function(dataIndex){
+        var view = this.view,
+            header = view.headerCt.down('gridcolumn[dataIndex=' + dataIndex + ']'),
+            menu = view.headerCt.getMenu();
+            
+        return menu.down('menuitem[headerId='+ header.id +']');
     },
 
     
-    setActiveError: function(msg, suppressEvent) {
-        this.activeError = msg;
-        if (suppressEvent !== true) this.fireEvent('invalid', this, msg);
+    onGroupClick: function(view, group, idx, foo, e) {
+        var me = this,
+            toggleCls = me.toggleCls,
+            groupBd = Ext.fly(group.nextSibling, '_grouping');
+
+        if (groupBd.hasCls(me.collapsedCls)) {
+            me.expand(groupBd);
+        } else {
+            me.collapse(groupBd);
+        }
     },
+
     
-    
-    unsetActiveError: function(suppressEvent) {
-        delete this.activeError;
-        if (suppressEvent !== true) this.fireEvent('valid', this);
+    getMetaRowTplFragments: function() {
+        return {
+            isRow: this.isRow,
+            closeRow: this.closeRow
+        };
     },
 
     
-    getMessageHandler : function(){
-        return Ext.form.MessageTargets[this.msgTarget];
+    
+    isRow: function() {
+        return '<tpl if="typeof rows === \'undefined\'">';
     },
 
     
-    getErrorCt : function(){
-        return this.el.findParent('.x-form-element', 5, true) || 
-            this.el.findParent('.x-form-field-wrap', 5, true);   
+    
+    closeRow: function() {
+        return '</tpl>';
     },
 
     
-    alignErrorEl : function(){
-        this.errorEl.setWidth(this.getErrorCt().getWidth(true) - 20);
+    mutateMetaRowTpl: function(metaRowTpl) {
+        metaRowTpl.unshift('{[this.isRow()]}');
+        metaRowTpl.push('{[this.closeRow()]}');
     },
 
     
-    alignErrorIcon : function(){
-        this.errorIcon.alignTo(this.el, 'tl-tr', [2, 0]);
+    
+    getAdditionalData: function(data, idx, record, orig) {
+        var view = this.view,
+            hCt  = view.headerCt,
+            col  = hCt.items.getAt(0),
+            o = {},
+            tdAttrKey = col.id + '-tdAttr';
+
+        
+        o[tdAttrKey] = this.indentByDepth(data) + " " + (orig[tdAttrKey] ? orig[tdAttrKey] : '');
+        o.collapsed = 'true';
+        return o;
     },
 
     
-    getRawValue : function(){
-        var v = this.rendered ? this.el.getValue() : Ext.value(this.value, '');
-        if(v === this.emptyText){
-            v = '';
+    getGroupRows: function(group, records, preppedRecords, fullWidth) {
+        var me = this,
+            children = group.children,
+            rows = group.rows = [],
+            view = me.view;
+        group.viewId = view.id;
+
+        Ext.Array.each(records, function(record, idx) {
+            if (Ext.Array.indexOf(children, record) != -1) {
+                rows.push(Ext.apply(preppedRecords[idx], {
+                    depth: 1
+                }));
+            }
+        });
+        delete group.children;
+        group.fullWidth = fullWidth;
+        if (me.collapsedState[view.id + '-gp-' + group.name]) {
+            group.collapsedCls = me.collapsedCls;
+            group.hdCollapsedCls = me.hdCollapsedCls;
         }
-        return v;
+
+        return group;
     },
 
     
-    getValue : function(){
-        if(!this.rendered) {
-            return this.value;
-        }
-        var v = this.el.getValue();
-        if(v === this.emptyText || v === undefined){
-            v = '';
+    collectData: function(records, preppedRecords, startIndex, fullWidth, o) {
+        var me    = this,
+            store = me.view.store,
+            groups;
+            
+        if (!me.disabled && store.isGrouped()) {
+            groups = store.getGroups();
+            Ext.Array.each(groups, function(group, idx){
+                me.getGroupRows(group, records, preppedRecords, fullWidth);
+            }, me);
+            return {
+                rows: groups,
+                fullWidth: fullWidth
+            };
         }
-        return v;
+        return o;
     },
+    
+    
+    
+    
+    
+    getFireEventArgs: function(type, view, featureTarget, e) {
+        var returnArray = [type, view, featureTarget],
+            groupBd     = Ext.fly(featureTarget.nextSibling, '_grouping'),
+            groupBdId   = Ext.getDom(groupBd).id,
+            prefix      = view.id + '-gp-',
+            groupName   = groupBdId.substr(prefix.length);
+        
+        returnArray.push(groupName, e);
+        
+        return returnArray;
+    }
+});
+
+
+Ext.define('Ext.grid.feature.GroupingSummary', {
 
     
-    setRawValue : function(v){
-        return this.rendered ? (this.el.dom.value = (Ext.isEmpty(v) ? '' : v)) : '';
+
+    extend: 'Ext.grid.feature.Grouping',
+
+    alias: 'feature.groupingsummary',
+
+    mixins: {
+        summary: 'Ext.grid.feature.AbstractSummary'
     },
 
     
-    setValue : function(v){
-        this.value = v;
-        if(this.rendered){
-            this.el.dom.value = (Ext.isEmpty(v) ? '' : v);
-            this.validate();
+
+
+   
+   getFeatureTpl: function() {
+        var tpl = this.callParent(arguments);
+
+        if (this.showSummaryRow) {
+            
+            tpl = tpl.replace('</tpl>', '');
+            tpl += '{[this.printSummaryRow(xindex)]}</tpl>';
         }
-        return this;
+        return tpl;
     },
 
     
-    append : function(v){
-         this.setValue([this.getValue(), v].join(''));
-    }
+    getFragmentTpl: function() {
+        var me = this,
+            fragments = me.callParent();
 
-    
-    
+        Ext.apply(fragments, me.getSummaryFragments());
+        if (me.showSummaryRow) {
+            
+            me.summaryGroups = me.view.store.getGroups();
+            me.summaryData = me.generateSummaryData();
+        }
+        return fragments;
+    },
 
     
-});
-
+    getPrintData: function(index){
+        var me = this,
+            columns = me.view.headerCt.getColumnsForTpl(),
+            i = 0,
+            length = columns.length,
+            data = [],
+            name = me.summaryGroups[index - 1].name,
+            active = me.summaryData[name],
+            column;
 
-Ext.form.MessageTargets = {
-    'qtip' : {
-        mark: function(field, msg){
-            field.el.addClass(field.invalidClass);
-            field.el.dom.qtip = msg;
-            field.el.dom.qclass = 'x-form-invalid-tip';
-            if(Ext.QuickTips){ 
-                Ext.QuickTips.enable();
-            }
-        },
-        clear: function(field){
-            field.el.removeClass(field.invalidClass);
-            field.el.dom.qtip = '';
+        for (; i < length; ++i) {
+            column = columns[i];
+            column.gridSummaryValue = this.getColumnValue(column, active);
+            data.push(column);
         }
+        return data;
     },
-    'title' : {
-        mark: function(field, msg){
-            field.el.addClass(field.invalidClass);
-            field.el.dom.title = msg;
-        },
-        clear: function(field){
-            field.el.dom.title = '';
+
+    
+    generateSummaryData: function(){
+        var me = this,
+            data = {},
+            remoteData = {},
+            store = me.view.store,
+            groupField = this.getGroupField(),
+            reader = store.proxy.reader,
+            groups = me.summaryGroups,
+            columns = me.view.headerCt.getColumnsForTpl(),
+            remote,
+            i,
+            length,
+            fieldData,
+            root,
+            key,
+            comp;
+
+        for (i = 0, length = groups.length; i < length; ++i) {
+            data[groups[i].name] = {};
         }
-    },
-    'under' : {
-        mark: function(field, msg){
-            field.el.addClass(field.invalidClass);
-            if(!field.errorEl){
-                var elp = field.getErrorCt();
-                if(!elp){ 
-                    field.el.dom.title = msg;
-                    return;
+
+        
+        if (me.remoteRoot && reader.rawData) {
+            
+            root = reader.root;
+            reader.root = me.remoteRoot;
+            reader.buildExtractors(true);
+            Ext.Array.each(reader.getRoot(reader.rawData), function(value) {
+                 remoteData[value[groupField]] = value;
+            });
+            
+            reader.root = root;
+            reader.buildExtractors(true);
+        }
+
+        for (i = 0, length = columns.length; i < length; ++i) {
+            comp = Ext.getCmp(columns[i].id);
+            fieldData = me.getSummary(store, comp.summaryType, comp.dataIndex, true);
+
+            for (key in fieldData) {
+                if (fieldData.hasOwnProperty(key)) {
+                    data[key][comp.id] = fieldData[key];
                 }
-                field.errorEl = elp.createChild({cls:'x-form-invalid-msg'});
-                field.on('resize', field.alignErrorEl, field);
-                field.on('destroy', function(){
-                    Ext.destroy(this.errorEl);
-                }, field);
-            }
-            field.alignErrorEl();
-            field.errorEl.update(msg);
-            Ext.form.Field.msgFx[field.msgFx].show(field.errorEl, field);
-        },
-        clear: function(field){
-            field.el.removeClass(field.invalidClass);
-            if(field.errorEl){
-                Ext.form.Field.msgFx[field.msgFx].hide(field.errorEl, field);
-            }else{
-                field.el.dom.title = '';
             }
-        }
-    },
-    'side' : {
-        mark: function(field, msg){
-            field.el.addClass(field.invalidClass);
-            if(!field.errorIcon){
-                var elp = field.getErrorCt();
-                
-                if(!elp){
-                    field.el.dom.title = msg;
-                    return;
+
+            for (key in remoteData) {
+                if (remoteData.hasOwnProperty(key)) {
+                    remote = remoteData[key][comp.dataIndex];
+                    if (remote !== undefined && data[key] !== undefined) {
+                        data[key][comp.id] = remote;
+                    }
                 }
-                field.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
-                if (field.ownerCt) {
-                    field.ownerCt.on('afterlayout', field.alignErrorIcon, field);
-                    field.ownerCt.on('expand', field.alignErrorIcon, field);
-                }
-                field.on('resize', field.alignErrorIcon, field);
-                field.on('destroy', function(){
-                    Ext.destroy(this.errorIcon);
-                }, field);
-            }
-            field.alignErrorIcon();
-            field.errorIcon.dom.qtip = msg;
-            field.errorIcon.dom.qclass = 'x-form-invalid-tip';
-            field.errorIcon.show();
-        },
-        clear: function(field){
-            field.el.removeClass(field.invalidClass);
-            if(field.errorIcon){
-                field.errorIcon.dom.qtip = '';
-                field.errorIcon.hide();
-            }else{
-                field.el.dom.title = '';
             }
         }
+        return data;
     }
-};
+});
 
 
-Ext.form.Field.msgFx = {
-    normal : {
-        show: function(msgEl, f){
-            msgEl.setDisplayed('block');
-        },
+Ext.define('Ext.grid.feature.RowBody', {
+    extend: 'Ext.grid.feature.Feature',
+    alias: 'feature.rowbody',
+    rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden',
+    rowBodyTrCls: Ext.baseCSSPrefix + 'grid-rowbody-tr',
+    rowBodyTdCls: Ext.baseCSSPrefix + 'grid-cell-rowbody',
+    rowBodyDivCls: Ext.baseCSSPrefix + 'grid-rowbody',
 
-        hide : function(msgEl, f){
-            msgEl.setDisplayed(false).update('');
-        }
+    eventPrefix: 'rowbody',
+    eventSelector: '.' + Ext.baseCSSPrefix + 'grid-rowbody-tr',
+    
+    getRowBody: function(values) {
+        return [
+            '<tr class="' + this.rowBodyTrCls + ' {rowBodyCls}">',
+                '<td class="' + this.rowBodyTdCls + '" colspan="{rowBodyColspan}">',
+                    '<div class="' + this.rowBodyDivCls + '">{rowBody}</div>',
+                '</td>',
+            '</tr>'
+        ].join('');
+    },
+    
+    
+    getMetaRowTplFragments: function() {
+        return {
+            getRowBody: this.getRowBody,
+            rowBodyTrCls: this.rowBodyTrCls,
+            rowBodyTdCls: this.rowBodyTdCls,
+            rowBodyDivCls: this.rowBodyDivCls
+        };
     },
 
-    slide : {
-        show: function(msgEl, f){
-            msgEl.slideIn('t', {stopFx:true});
-        },
-
-        hide : function(msgEl, f){
-            msgEl.slideOut('t', {stopFx:true,useDisplay:true});
-        }
+    mutateMetaRowTpl: function(metaRowTpl) {
+        metaRowTpl.push('{[this.getRowBody(values)]}');
     },
 
-    slideRight : {
-        show: function(msgEl, f){
-            msgEl.fixDisplay();
-            msgEl.alignTo(f.el, 'tl-tr');
-            msgEl.slideIn('l', {stopFx:true});
-        },
+    
+    getAdditionalData: function(data, idx, record, orig) {
+        var headerCt = this.view.headerCt,
+            colspan  = headerCt.getColumnCount();
 
-        hide : function(msgEl, f){
-            msgEl.slideOut('l', {stopFx:true,useDisplay:true});
-        }
+        return {
+            rowBody: "",
+            rowBodyCls: this.rowBodyCls,
+            rowBodyColspan: colspan
+        };
     }
-};
-Ext.reg('field', Ext.form.Field);
+});
+
+Ext.define('Ext.grid.feature.RowWrap', {
+    extend: 'Ext.grid.feature.Feature',
+    alias: 'feature.rowwrap',
 
-Ext.form.TextField = Ext.extend(Ext.form.Field,  {
     
+    hasFeatureEvent: false,
     
+    mutateMetaRowTpl: function(metaRowTpl) {        
+        
+        
+        metaRowTpl[0] = metaRowTpl[0].replace(Ext.baseCSSPrefix + 'grid-row', '');
+        metaRowTpl[0] = metaRowTpl[0].replace("{[this.embedRowCls()]}", "");
+        
+        metaRowTpl.unshift('<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" style="width: {[this.embedFullWidth()]}px;">');
+        
+        metaRowTpl.unshift('<tr class="' + Ext.baseCSSPrefix + 'grid-row {[this.embedRowCls()]}"><td colspan="{[this.embedColSpan()]}"><div class="' + Ext.baseCSSPrefix + 'grid-rowwrap-div">');
+        
+        
+        metaRowTpl.push('</table>');
+        
+        metaRowTpl.push('</div></td></tr>');
+    },
     
-    grow : false,
+    embedColSpan: function() {
+        return '{colspan}';
+    },
     
-    growMin : 30,
+    embedFullWidth: function() {
+        return '{fullWidth}';
+    },
     
-    growMax : 800,
+    getAdditionalData: function(data, idx, record, orig) {
+        var headerCt = this.view.headerCt,
+            colspan  = headerCt.getColumnCount(),
+            fullWidth = headerCt.getFullWidth(),
+            items    = headerCt.query('gridcolumn'),
+            itemsLn  = items.length,
+            i = 0,
+            o = {
+                colspan: colspan,
+                fullWidth: fullWidth
+            },
+            id,
+            tdClsKey,
+            colResizerCls;
+
+        for (; i < itemsLn; i++) {
+            id = items[i].id;
+            tdClsKey = id + '-tdCls';
+            colResizerCls = Ext.baseCSSPrefix + 'grid-col-resizer-'+id;
+            
+            
+            
+            o[tdClsKey] = colResizerCls + " " + (orig[tdClsKey] ? orig[tdClsKey] : '');
+            
+            o[id+'-tdAttr'] = " style=\"width: " + (items[i].hidden ? 0 : items[i].getDesiredWidth()) + "px;\" ";
+            if (orig[id+'-tdAttr']) {
+                o[id+'-tdAttr'] += orig[id+'-tdAttr'];
+            }
+            
+        }
+
+        return o;
+    },
     
-    vtype : null,
+    getMetaRowTplFragments: function() {
+        return {
+            embedFullWidth: this.embedFullWidth,
+            embedColSpan: this.embedColSpan
+        };
+    }
     
-    maskRe : null,
+});
+
+Ext.define('Ext.grid.feature.Summary', {
     
-    disableKeyFilter : false,
     
-    allowBlank : true,
     
-    minLength : 0,
+    extend: 'Ext.grid.feature.AbstractSummary',
     
-    maxLength : Number.MAX_VALUE,
+    alias: 'feature.summary',
     
-    minLengthText : 'The minimum length for this field is {0}',
     
-    maxLengthText : 'The maximum length for this field is {0}',
     
-    selectOnFocus : false,
     
-    blankText : 'This field is required',
+    getFragmentTpl: function() {
+        
+        this.summaryData = this.generateSummaryData(); 
+        return this.getSummaryFragments();
+    },
     
-    validator : null,
     
-    regex : null,
+    getTableFragments: function(){
+        if (this.showSummaryRow) {
+            return {
+                closeRows: this.closeRows
+            };
+        }
+    },
     
-    regexText : '',
     
-    emptyText : null,
+    closeRows: function() {
+        return '</tpl>{[this.printSummaryRow()]}';
+    },
     
-    emptyClass : 'x-form-empty-field',
-
     
-
-    initComponent : function(){
-        Ext.form.TextField.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'autosize',
-
-            
-            'keydown',
-            
-            'keyup',
+    getPrintData: function(index){
+        var me = this,
+            columns = me.view.headerCt.getColumnsForTpl(),
+            i = 0,
+            length = columns.length,
+            data = [],
+            active = me.summaryData,
+            column;
             
-            'keypress'
-        );
+        for (; i < length; ++i) {
+            column = columns[i];
+            column.gridSummaryValue = this.getColumnValue(column, active);
+            data.push(column);
+        }
+        return data;
     },
-
     
-    initEvents : function(){
-        Ext.form.TextField.superclass.initEvents.call(this);
-        if(this.validationEvent == 'keyup'){
-            this.validationTask = new Ext.util.DelayedTask(this.validate, this);
-            this.mon(this.el, 'keyup', this.filterValidation, this);
-        }
-        else if(this.validationEvent !== false && this.validationEvent != 'blur'){
-               this.mon(this.el, this.validationEvent, this.validate, this, {buffer: this.validationDelay});
-        }
-        if(this.selectOnFocus || this.emptyText){            
-            this.mon(this.el, 'mousedown', this.onMouseDown, this);
+    
+    generateSummaryData: function(){
+        var me = this,
+            data = {},
+            store = me.view.store,
+            columns = me.view.headerCt.getColumnsForTpl(),
+            i = 0,
+            length = columns.length,
+            fieldData,
+            key,
+            comp;
             
-            if(this.emptyText){
-                this.applyEmptyText();
-            }
-        }
-        if(this.maskRe || (this.vtype && this.disableKeyFilter !== true && (this.maskRe = Ext.form.VTypes[this.vtype+'Mask']))){
-               this.mon(this.el, 'keypress', this.filterKeys, this);
-        }
-        if(this.grow){
-               this.mon(this.el, 'keyup', this.onKeyUpBuffered, this, {buffer: 50});
-                       this.mon(this.el, 'click', this.autoSize, this);
-        }
-        if(this.enableKeyEvents){
-            this.mon(this.el, {
-                scope: this,
-                keyup: this.onKeyUp,
-                keydown: this.onKeyDown,
-                keypress: this.onKeyPress
-            });
+        for (i = 0, length = columns.length; i < length; ++i) {
+            comp = Ext.getCmp(columns[i].id);
+            data[comp.id] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
         }
+        return data;
+    }
+});
+
+Ext.define('Ext.grid.header.DragZone', {
+    extend: 'Ext.dd.DragZone',
+    colHeaderCls: Ext.baseCSSPrefix + 'column-header',
+    maxProxyWidth: 120,
+
+    constructor: function(headerCt) {
+        this.headerCt = headerCt;
+        this.ddGroup =  this.getDDGroup();
+        this.callParent([headerCt.el]);
+        this.proxy.el.addCls(Ext.baseCSSPrefix + 'grid-col-dd');
     },
-    
-    onMouseDown: function(e){
-        if(!this.hasFocus){
-            this.mon(this.el, 'mouseup', Ext.emptyFn, this, { single: true, preventDefault: true });
-        }
+
+    getDDGroup: function() {
+        return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
     },
 
-    processValue : function(value){
-        if(this.stripCharsRe){
-            var newValue = value.replace(this.stripCharsRe, '');
-            if(newValue !== value){
-                this.setRawValue(newValue);
-                return newValue;
+    getDragData: function(e) {
+        var header = e.getTarget('.'+this.colHeaderCls),
+            headerCmp;
+
+        if (header) {
+            headerCmp = Ext.getCmp(header.id);
+            if (!this.headerCt.dragging && headerCmp.draggable && !(headerCmp.isOnLeftEdge(e) || headerCmp.isOnRightEdge(e))) {
+                var ddel = document.createElement('div');
+                ddel.innerHTML = Ext.getCmp(header.id).text;
+                return {
+                    ddel: ddel,
+                    header: headerCmp
+                };
             }
         }
-        return value;
+        return false;
     },
 
-    filterValidation : function(e){
-        if(!e.isNavKeyPress()){
-            this.validationTask.delay(this.validationDelay);
-        }
-    },
-    
-    
-    onDisable: function(){
-        Ext.form.TextField.superclass.onDisable.call(this);
-        if(Ext.isIE){
-            this.el.dom.unselectable = 'on';
-        }
+    onBeforeDrag: function() {
+        return !(this.headerCt.dragging || this.disabled);
     },
-    
-    
-    onEnable: function(){
-        Ext.form.TextField.superclass.onEnable.call(this);
-        if(Ext.isIE){
-            this.el.dom.unselectable = '';
-        }
+
+    onInitDrag: function() {
+        this.headerCt.dragging = true;
+        this.callParent(arguments);
     },
 
-    
-    onKeyUpBuffered : function(e){
-        if(this.doAutoSize(e)){
-            this.autoSize();
-        }
+    onDragDrop: function() {
+        this.headerCt.dragging = false;
+        this.callParent(arguments);
     },
-    
-    
-    doAutoSize : function(e){
-        return !e.isNavKeyPress();
+
+    afterRepair: function() {
+        this.callParent();
+        this.headerCt.dragging = false;
     },
 
+    getRepairXY: function() {
+        return this.dragData.header.el.getXY();
+    },
     
-    onKeyUp : function(e){
-        this.fireEvent('keyup', this, e);
+    disable: function() {
+        this.disabled = true;
     },
-
     
-    onKeyDown : function(e){
-        this.fireEvent('keydown', this, e);
+    enable: function() {
+        this.disabled = false;
+    }
+});
+
+
+Ext.define('Ext.grid.header.DropZone', {
+    extend: 'Ext.dd.DropZone',
+    colHeaderCls: Ext.baseCSSPrefix + 'column-header',
+    proxyOffsets: [-4, -9],
+
+    constructor: function(headerCt){
+        this.headerCt = headerCt;
+        this.ddGroup = this.getDDGroup();
+        this.callParent([headerCt.el]);
     },
 
-    
-    onKeyPress : function(e){
-        this.fireEvent('keypress', this, e);
+    getDDGroup: function() {
+        return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
     },
 
-    
-    reset : function(){
-        Ext.form.TextField.superclass.reset.call(this);
-        this.applyEmptyText();
+    getTargetFromEvent : function(e){
+        return e.getTarget('.' + this.colHeaderCls);
     },
 
-    applyEmptyText : function(){
-        if(this.rendered && this.emptyText && this.getRawValue().length < 1 && !this.hasFocus){
-            this.setRawValue(this.emptyText);
-            this.el.addClass(this.emptyClass);
+    getTopIndicator: function() {
+        if (!this.topIndicator) {
+            this.topIndicator = Ext.DomHelper.append(Ext.getBody(), {
+                cls: "col-move-top",
+                html: "&#160;"
+            }, true);
         }
+        return this.topIndicator;
     },
 
-    
-    preFocus : function(){
-        var el = this.el;
-        if(this.emptyText){
-            if(el.dom.value == this.emptyText){
-                this.setRawValue('');
-            }
-            el.removeClass(this.emptyClass);
-        }
-        if(this.selectOnFocus){
-            el.dom.select();
+    getBottomIndicator: function() {
+        if (!this.bottomIndicator) {
+            this.bottomIndicator = Ext.DomHelper.append(Ext.getBody(), {
+                cls: "col-move-bottom",
+                html: "&#160;"
+            }, true);
         }
+        return this.bottomIndicator;
     },
 
-    
-    postBlur : function(){
-        this.applyEmptyText();
-    },
+    getLocation: function(e, t) {
+        var x      = e.getXY()[0],
+            region = Ext.fly(t).getRegion(),
+            pos, header;
 
-    
-    filterKeys : function(e){
-        if(e.ctrlKey){
-            return;
-        }
-        var k = e.getKey();
-        if(Ext.isGecko && (e.isNavKeyPress() || k == e.BACKSPACE || (k == e.DELETE && e.button == -1))){
-            return;
-        }
-        var cc = String.fromCharCode(e.getCharCode());
-        if(!Ext.isGecko && e.isSpecialKey() && !cc){
-            return;
-        }
-        if(!this.maskRe.test(cc)){
-            e.stopEvent();
+        if ((region.right - x) <= (region.right - region.left) / 2) {
+            pos = "after";
+        } else {
+            pos = "before";
         }
+        return {
+            pos: pos,
+            header: Ext.getCmp(t.id),
+            node: t
+        };
     },
 
-    setValue : function(v){
-        if(this.emptyText && this.el && !Ext.isEmpty(v)){
-            this.el.removeClass(this.emptyClass);
-        }
-        Ext.form.TextField.superclass.setValue.apply(this, arguments);
-        this.applyEmptyText();
-        this.autoSize();
-        return this;
-    },
+    positionIndicator: function(draggedHeader, node, e){
+        var location = this.getLocation(e, node),
+            header = location.header,
+            pos    = location.pos,
+            nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
+            prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
+            region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
+            topXY, bottomXY, headerCtEl, minX, maxX;
 
-    
-    getErrors: function(value) {
-        var errors = Ext.form.TextField.superclass.getErrors.apply(this, arguments);
         
-        value = value || this.processValue(this.getRawValue());        
-        
-        if (Ext.isFunction(this.validator)) {
-            var msg = this.validator(value);
-            if (msg !== true) {
-                errors.push(msg);
-            }
+        if (!header.draggable && header.getIndex() == 0) {
+            return false;
         }
-        
-        if (value.length < 1 || value === this.emptyText) {
-            if (this.allowBlank) {
-                
-                return errors;
-            } else {
-                errors.push(this.blankText);
+
+        this.lastLocation = location;
+
+        if ((draggedHeader !== header) &&
+            ((pos === "before" && nextHd !== header) ||
+            (pos === "after" && prevHd !== header)) &&
+            !header.isDescendantOf(draggedHeader)) {
+
+            
+            
+            
+            var allDropZones = Ext.dd.DragDropManager.getRelated(this),
+                ln = allDropZones.length,
+                i  = 0,
+                dropZone;
+
+            for (; i < ln; i++) {
+                dropZone = allDropZones[i];
+                if (dropZone !== this && dropZone.invalidateDrop) {
+                    dropZone.invalidateDrop();
+                }
             }
-        }
-        
-        if (!this.allowBlank && (value.length < 1 || value === this.emptyText)) { 
-            errors.push(this.blankText);
-        }
-        
-        if (value.length < this.minLength) {
-            errors.push(String.format(this.minLengthText, this.minLength));
-        }
-        
-        if (value.length > this.maxLength) {
-            errors.push(String.format(this.maxLengthText, this.maxLength));
-        }
-        
-        if (this.vtype) {
-            var vt = Ext.form.VTypes;
-            if(!vt[this.vtype](value, this)){
-                errors.push(this.vtypeText || vt[this.vtype +'Text']);
+
+
+            this.valid = true;
+            topIndicator = this.getTopIndicator();
+            bottomIndicator = this.getBottomIndicator();
+            if (pos === 'before') {
+                topAnchor = 'tl';
+                bottomAnchor = 'bl';
+            } else {
+                topAnchor = 'tr';
+                bottomAnchor = 'br';
             }
-        }
+            topXY = header.el.getAnchorXY(topAnchor);
+            bottomXY = header.el.getAnchorXY(bottomAnchor);
+
+            
+            headerCtEl = this.headerCt.el;
+            minX = headerCtEl.getLeft();
+            maxX = headerCtEl.getRight();
+
+            topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
+            bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
+
+            
+            
+            topXY[0] -= 4;
+            topXY[1] -= 9;
+            bottomXY[0] -= 4;
+
+            
+            topIndicator.setXY(topXY);
+            bottomIndicator.setXY(bottomXY);
+            topIndicator.show();
+            bottomIndicator.show();
         
-        if (this.regex && !this.regex.test(value)) {
-            errors.push(this.regexText);
+        } else {
+            this.invalidateDrop();
         }
-        
-        return errors;
     },
 
-    
-    selectText : function(start, end){
-        var v = this.getRawValue();
-        var doFocus = false;
-        if(v.length > 0){
-            start = start === undefined ? 0 : start;
-            end = end === undefined ? v.length : end;
-            var d = this.el.dom;
-            if(d.setSelectionRange){
-                d.setSelectionRange(start, end);
-            }else if(d.createTextRange){
-                var range = d.createTextRange();
-                range.moveStart('character', start);
-                range.moveEnd('character', end-v.length);
-                range.select();
-            }
-            doFocus = Ext.isGecko || Ext.isOpera;
-        }else{
-            doFocus = true;
-        }
-        if(doFocus){
-            this.focus();
-        }
+    invalidateDrop: function() {
+        this.valid = false;
+        this.hideIndicators();
     },
 
-    
-    autoSize : function(){
-        if(!this.grow || !this.rendered){
-            return;
+    onNodeOver: function(node, dragZone, e, data) {
+        if (data.header.el.dom !== node) {
+            this.positionIndicator(data.header, node, e);
         }
-        if(!this.metrics){
-            this.metrics = Ext.util.TextMetrics.createInstance(this.el);
-        }
-        var el = this.el;
-        var v = el.dom.value;
-        var d = document.createElement('div');
-        d.appendChild(document.createTextNode(v));
-        v = d.innerHTML;
-        Ext.removeNode(d);
-        d = null;
-        v += '&#160;';
-        var w = Math.min(this.growMax, Math.max(this.metrics.getWidth(v) +  10, this.growMin));
-        this.el.setWidth(w);
-        this.fireEvent('autosize', this, w);
+        return this.valid ? this.dropAllowed : this.dropNotAllowed;
+    },
+
+    hideIndicators: function() {
+        this.getTopIndicator().hide();
+        this.getBottomIndicator().hide();
+    },
+
+    onNodeOut: function() {
+        this.hideIndicators();
     },
-       
-       onDestroy: function(){
-               if(this.validationTask){
-                       this.validationTask.cancel();
-                       this.validationTask = null;
-               }
-               Ext.form.TextField.superclass.onDestroy.call(this);
-       }
+
+    onNodeDrop: function(node, dragZone, e, data) {
+        if (this.valid) {
+            this.invalidateDrop();
+            var hd = data.header,
+                lastLocation = this.lastLocation,
+                fromCt  = hd.ownerCt,
+                fromIdx = fromCt.items.indexOf(hd), 
+                toCt    = lastLocation.header.ownerCt,
+                toIdx   = toCt.items.indexOf(lastLocation.header),
+                headerCt = this.headerCt,
+                groupCt,
+                scrollerOwner;
+
+            if (lastLocation.pos === 'after') {
+                toIdx++;
+            }
+
+            
+            
+            
+            if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && toCt.lockedCt) {
+                scrollerOwner = fromCt.up('[scrollerOwner]');
+                scrollerOwner.lock(hd, toIdx);
+            } else if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && fromCt.lockedCt) {
+                scrollerOwner = fromCt.up('[scrollerOwner]');
+                scrollerOwner.unlock(hd, toIdx);
+            } else {
+                
+                
+                if ((fromCt === toCt) && (toIdx > fromCt.items.indexOf(hd))) {
+                    toIdx--;
+                }
+
+                
+                if (fromCt !== toCt) {
+                    fromCt.suspendLayout = true;
+                    fromCt.remove(hd, false);
+                    fromCt.suspendLayout = false;
+                }
+
+                
+                if (fromCt.isGroupHeader) {
+                    if (!fromCt.items.getCount()) {
+                        groupCt = fromCt.ownerCt;
+                        groupCt.suspendLayout = true;
+                        groupCt.remove(fromCt, false);
+                        fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
+                        groupCt.suspendLayout = false;
+                    } else {
+                        fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
+                        fromCt.setWidth(fromCt.minWidth);
+                    }
+                }
+
+                
+                toCt.suspendLayout = true;
+                if (fromCt === toCt) {
+                    toCt.move(fromIdx, toIdx);
+                } else {
+                    toCt.insert(toIdx, hd);
+                }
+                toCt.suspendLayout = false;
+
+                
+                
+                
+                if (toCt.isGroupHeader) {
+                    hd.savedFlex = hd.flex;
+                    delete hd.flex;
+                    hd.width = hd.getWidth();
+                    
+                    
+                    toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
+                    toCt.setWidth(toCt.minWidth);
+                } else {
+                    if (hd.savedFlex) {
+                        hd.flex = hd.savedFlex;
+                        delete hd.width;
+                    }
+                }
+
+
+                
+                headerCt.purgeCache();
+                headerCt.doLayout();
+                headerCt.onHeaderMoved(hd, fromIdx, toIdx);
+                
+                if (!fromCt.items.getCount()) {
+                    fromCt.destroy();
+                }
+            }
+        }
+    }
 });
-Ext.reg('textfield', Ext.form.TextField);
 
-Ext.form.TriggerField = Ext.extend(Ext.form.TextField,  {
-    
-    
-    
-    defaultAutoCreate : {tag: "input", type: "text", size: "16", autocomplete: "off"},
-    
-    hideTrigger:false,
-    
-    editable: true,
-    
-    readOnly: false,
-    
-    wrapFocusClass: 'x-trigger-wrap-focus',
+
+Ext.define('Ext.grid.plugin.Editing', {
+    alias: 'editing.editing',
+
+    requires: [
+        'Ext.grid.column.Column',
+        'Ext.util.KeyNav'
+    ],
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
     
-    autoSize: Ext.emptyFn,
+    clicksToEdit: 2,
+
     
-    monitorTab : true,
+    defaultFieldXType: 'textfield',
+
     
-    deferHeight : true,
+    editStyle: '',
+
+    constructor: function(config) {
+        var me = this;
+        Ext.apply(me, config);
+
+        me.addEvents(
+            
+            'beforeedit',
+
+            
+            'edit',
+
+            
+            'validateedit'
+        );
+        me.mixins.observable.constructor.call(me);
+        
+        me.relayEvents(me, ['afteredit'], 'after');
+    },
+
     
-    mimicing : false,
+    init: function(grid) {
+        var me = this;
 
-    actionMode: 'wrap',
+        me.grid = grid;
+        me.view = grid.view;
+        me.initEvents();
+        me.mon(grid, 'reconfigure', me.onReconfigure, me);
+        me.onReconfigure();
 
-    defaultTriggerWidth: 17,
+        grid.relayEvents(me, ['beforeedit', 'edit', 'validateedit']);
+        
+        
+        grid.isEditable = true;
+        grid.editingPlugin = grid.view.editingPlugin = me;
+    },
 
     
-    onResize : function(w, h){
-        Ext.form.TriggerField.superclass.onResize.call(this, w, h);
-        var tw = this.getTriggerWidth();
-        if(Ext.isNumber(w)){
-            this.el.setWidth(w - tw);
-        }
-        this.wrap.setWidth(this.el.getWidth() + tw);
+    onReconfigure: function(){
+        this.initFieldAccessors(this.view.getGridColumns());
     },
 
-    getTriggerWidth: function(){
-        var tw = this.trigger.getWidth();
-        if(!this.hideTrigger && !this.readOnly && tw === 0){
-            tw = this.defaultTriggerWidth;
-        }
-        return tw;
+    
+    destroy: function() {
+        var me = this,
+            grid = me.grid,
+            headerCt = grid.headerCt,
+            events = grid.events;
+
+        Ext.destroy(me.keyNav);
+        me.removeFieldAccessors(grid.getView().getGridColumns());
+
+        
+        me.clearListeners();
+
+        delete me.grid.editingPlugin;
+        delete me.grid.view.editingPlugin;
+        delete me.grid;
+        delete me.view;
+        delete me.editor;
+        delete me.keyNav;
     },
 
     
-    alignErrorIcon : function(){
-        if(this.wrap){
-            this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
-        }
+    getEditStyle: function() {
+        return this.editStyle;
     },
 
     
-    onRender : function(ct, position){
-        this.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
-        Ext.form.TriggerField.superclass.onRender.call(this, ct, position);
+    initFieldAccessors: function(column) {
+        var me = this;
 
-        this.wrap = this.el.wrap({cls: 'x-form-field-wrap x-form-field-trigger-wrap'});
-        this.trigger = this.wrap.createChild(this.triggerConfig ||
-                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.triggerClass});
-        this.initTrigger();
-        if(!this.width){
-            this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth());
+        if (Ext.isArray(column)) {
+            Ext.Array.forEach(column, me.initFieldAccessors, me);
+            return;
         }
-        this.resizeEl = this.positionEl = this.wrap;
-    },
 
-    getWidth: function() {
-        return(this.el.getWidth() + this.trigger.getWidth());
-    },
+        
+        
+        Ext.applyIf(column, {
+            getEditor: function(record, defaultField) {
+                return me.getColumnField(this, defaultField);
+            },
 
-    updateEditState: function(){
-        if(this.rendered){
-            if (this.readOnly) {
-                this.el.dom.readOnly = true;
-                this.el.addClass('x-trigger-noedit');
-                this.mun(this.el, 'click', this.onTriggerClick, this);
-                this.trigger.setDisplayed(false);
-            } else {
-                if (!this.editable) {
-                    this.el.dom.readOnly = true;
-                    this.el.addClass('x-trigger-noedit');
-                    this.mon(this.el, 'click', this.onTriggerClick, this);
-                } else {
-                    this.el.dom.readOnly = false;
-                    this.el.removeClass('x-trigger-noedit');
-                    this.mun(this.el, 'click', this.onTriggerClick, this);
-                }
-                this.trigger.setDisplayed(!this.hideTrigger);
+            setEditor: function(field) {
+                me.setColumnField(this, field);
             }
-            this.onResize(this.width || this.wrap.getWidth());
-        }
+        });
     },
 
-    setHideTrigger: function(hideTrigger){
-        if(hideTrigger != this.hideTrigger){
-            this.hideTrigger = hideTrigger;
-            this.updateEditState();
+    
+    removeFieldAccessors: function(column) {
+        var me = this;
+
+        if (Ext.isArray(column)) {
+            Ext.Array.forEach(column, me.removeFieldAccessors, me);
+            return;
         }
+
+        delete column.getEditor;
+        delete column.setEditor;
     },
 
     
-    setEditable: function(editable){
-        if(editable != this.editable){
-            this.editable = editable;
-            this.updateEditState();
+    
+    getColumnField: function(columnHeader, defaultField) {
+        var field = columnHeader.field;
+
+        if (!field && columnHeader.editor) {
+            field = columnHeader.editor;
+            delete columnHeader.editor;
         }
-    },
 
-    
-    setReadOnly: function(readOnly){
-        if(readOnly != this.readOnly){
-            this.readOnly = readOnly;
-            this.updateEditState();
+        if (!field && defaultField) {
+            field = defaultField;
         }
-    },
 
-    afterRender : function(){
-        Ext.form.TriggerField.superclass.afterRender.call(this);
-        this.updateEditState();
-    },
+        if (field) {
+            if (Ext.isString(field)) {
+                field = { xtype: field };
+            }
+            if (Ext.isObject(field) && !field.isFormField) {
+                field = Ext.ComponentManager.create(field, this.defaultFieldXType);
+                columnHeader.field = field;
+            }
 
-    
-    initTrigger : function(){
-        this.mon(this.trigger, 'click', this.onTriggerClick, this, {preventDefault:true});
-        this.trigger.addClassOnOver('x-form-trigger-over');
-        this.trigger.addClassOnClick('x-form-trigger-click');
-    },
+            Ext.apply(field, {
+                name: columnHeader.dataIndex
+            });
 
-    
-    onDestroy : function(){
-        Ext.destroy(this.trigger, this.wrap);
-        if (this.mimicing){
-            this.doc.un('mousedown', this.mimicBlur, this);
+            return field;
         }
-        delete this.doc;
-        Ext.form.TriggerField.superclass.onDestroy.call(this);
     },
 
     
-    onFocus : function(){
-        Ext.form.TriggerField.superclass.onFocus.call(this);
-        if(!this.mimicing){
-            this.wrap.addClass(this.wrapFocusClass);
-            this.mimicing = true;
-            this.doc.on('mousedown', this.mimicBlur, this, {delay: 10});
-            if(this.monitorTab){
-                this.on('specialkey', this.checkTab, this);
-            }
+    
+    setColumnField: function(column, field) {
+        if (Ext.isObject(field) && !field.isFormField) {
+            field = Ext.ComponentManager.create(field, this.defaultFieldXType);
         }
+        column.field = field;
     },
 
     
-    checkTab : function(me, e){
-        if(e.getKey() == e.TAB){
-            this.triggerBlur();
-        }
+    initEvents: function() {
+        var me = this;
+        me.initEditTriggers();
+        me.initCancelTriggers();
     },
 
     
-    onBlur : Ext.emptyFn,
+    initCancelTriggers: Ext.emptyFn,
 
     
-    mimicBlur : function(e){
-        if(!this.isDestroyed && !this.wrap.contains(e.target) && this.validateBlur(e)){
-            this.triggerBlur();
-        }
+    initEditTriggers: function() {
+        var me = this,
+            view = me.view,
+            clickEvent = me.clicksToEdit === 1 ? 'click' : 'dblclick';
+
+        
+        me.mon(view, 'cell' + clickEvent, me.startEditByClick, me);
+        view.on('render', function() {
+            me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
+                enter: me.onEnterKey,
+                esc: me.onEscKey,
+                scope: me
+            });
+        }, me, { single: true });
     },
 
     
-    triggerBlur : function(){
-        this.mimicing = false;
-        this.doc.un('mousedown', this.mimicBlur, this);
-        if(this.monitorTab && this.el){
-            this.un('specialkey', this.checkTab, this);
+    onEnterKey: function(e) {
+        var me = this,
+            grid = me.grid,
+            selModel = grid.getSelectionModel(),
+            record,
+            columnHeader = grid.headerCt.getHeaderAtIndex(0);
+
+        
+        
+        if (selModel.getCurrentPosition) {
+            pos = selModel.getCurrentPosition();
+            record = grid.store.getAt(pos.row);
+            columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);
         }
-        Ext.form.TriggerField.superclass.onBlur.call(this);
-        if(this.wrap){
-            this.wrap.removeClass(this.wrapFocusClass);
+        
+        else {
+            record = selModel.getLastSelected();
         }
+        me.startEdit(record, columnHeader);
     },
 
-    beforeBlur : Ext.emptyFn,
-
     
-    
-    validateBlur : function(e){
-        return true;
+    onEscKey: function(e) {
+        this.cancelEdit();
     },
 
     
-    onTriggerClick : Ext.emptyFn
+    startEditByClick: function(view, cell, colIdx, record, row, rowIdx, e) {
+        this.startEdit(record, view.getHeaderAtIndex(colIdx));
+    },
 
     
-    
-    
-});
+    beforeEdit: Ext.emptyFn,
 
-
-Ext.form.TwinTriggerField = Ext.extend(Ext.form.TriggerField, {
-    
-    
     
+    startEdit: function(record, columnHeader) {
+        var me = this,
+            context = me.getEditingContext(record, columnHeader);
 
-    initComponent : function(){
-        Ext.form.TwinTriggerField.superclass.initComponent.call(this);
+        if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
+            return false;
+        }
 
-        this.triggerConfig = {
-            tag:'span', cls:'x-form-twin-triggers', cn:[
-            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger1Class},
-            {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger " + this.trigger2Class}
-        ]};
+        me.context = context;
+        me.editing = true;
     },
 
-    getTrigger : function(index){
-        return this.triggers[index];
-    },
     
-    afterRender: function(){
-        Ext.form.TwinTriggerField.superclass.afterRender.call(this);
-        var triggers = this.triggers,
-            i = 0,
-            len = triggers.length;
-            
-        for(; i < len; ++i){
-            if(this['hideTrigger' + (i + 1)]){
-                    triggers[i].hide();
-                }
+    getEditingContext: function(record, columnHeader) {
+        var me = this,
+            grid = me.grid,
+            store = grid.store,
+            rowIdx,
+            colIdx,
+            view = grid.getView(),
+            value;
 
-        }    
-    },
+        
+        if (Ext.isNumber(record)) {
+            rowIdx = record;
+            record = store.getAt(rowIdx);
+        } else {
+            rowIdx = store.indexOf(record);
+        }
+        if (Ext.isNumber(columnHeader)) {
+            colIdx = columnHeader;
+            columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
+        } else {
+            colIdx = columnHeader.getIndex();
+        }
 
-    initTrigger : function(){
-        var ts = this.trigger.select('.x-form-trigger', true),
-            triggerField = this;
-            
-        ts.each(function(t, all, index){
-            var triggerIndex = 'Trigger'+(index+1);
-            t.hide = function(){
-                var w = triggerField.wrap.getWidth();
-                this.dom.style.display = 'none';
-                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
-                this['hidden' + triggerIndex] = true;
-            };
-            t.show = function(){
-                var w = triggerField.wrap.getWidth();
-                this.dom.style.display = '';
-                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
-                this['hidden' + triggerIndex] = false;
-            };
-            this.mon(t, 'click', this['on'+triggerIndex+'Click'], this, {preventDefault:true});
-            t.addClassOnOver('x-form-trigger-over');
-            t.addClassOnClick('x-form-trigger-click');
-        }, this);
-        this.triggers = ts.elements;
+        value = record.get(columnHeader.dataIndex);
+        return {
+            grid: grid,
+            record: record,
+            field: columnHeader.dataIndex,
+            value: value,
+            row: view.getNode(rowIdx),
+            column: columnHeader,
+            rowIdx: rowIdx,
+            colIdx: colIdx
+        };
     },
 
-    getTriggerWidth: function(){
-        var tw = 0;
-        Ext.each(this.triggers, function(t, index){
-            var triggerIndex = 'Trigger' + (index + 1),
-                w = t.getWidth();
-            if(w === 0 && !this['hidden' + triggerIndex]){
-                tw += this.defaultTriggerWidth;
-            }else{
-                tw += w;
-            }
-        }, this);
-        return tw;
+    
+    cancelEdit: function() {
+        this.editing = false;
     },
 
     
-    onDestroy : function() {
-        Ext.destroy(this.triggers);
-        Ext.form.TwinTriggerField.superclass.onDestroy.call(this);
+    completeEdit: function() {
+        var me = this;
+
+        if (me.editing && me.validateEdit()) {
+            me.fireEvent('edit', me.context);
+        }
+
+        delete me.context;
+        me.editing = false;
     },
 
     
-    onTrigger1Click : Ext.emptyFn,
-    
-    onTrigger2Click : Ext.emptyFn
+    validateEdit: function() {
+        var me = this,
+            context = me.context;
+
+        return me.fireEvent('validateedit', me, context) !== false && !context.cancel;
+    }
 });
-Ext.reg('trigger', Ext.form.TriggerField);
 
-Ext.form.TextArea = Ext.extend(Ext.form.TextField,  {
-    
-    growMin : 60,
-    
-    growMax: 1000,
-    growAppend : '&#160;\n&#160;',
 
-    enterIsSpecial : false,
+Ext.define('Ext.grid.plugin.CellEditing', {
+    alias: 'plugin.cellediting',
+    extend: 'Ext.grid.plugin.Editing',
+    requires: ['Ext.grid.CellEditor', 'Ext.util.DelayedTask'],
 
+    constructor: function() {
+        
+        
+        
+        this.callParent(arguments);
+        this.editors = Ext.create('Ext.util.MixedCollection', false, function(editor) {
+            return editor.editorId;
+        });
+        this.editTask = Ext.create('Ext.util.DelayedTask');
+    },
     
-    preventScrollbars: false,
-    
+    onReconfigure: function(){
+        this.editors.clear();
+        this.callParent();    
+    },
 
     
-    onRender : function(ct, position){
-        if(!this.el){
-            this.defaultAutoCreate = {
-                tag: "textarea",
-                style:"width:100px;height:60px;",
-                autocomplete: "off"
-            };
-        }
-        Ext.form.TextArea.superclass.onRender.call(this, ct, position);
-        if(this.grow){
-            this.textSizeEl = Ext.DomHelper.append(document.body, {
-                tag: "pre", cls: "x-form-grow-sizer"
-            });
-            if(this.preventScrollbars){
-                this.el.setStyle("overflow", "hidden");
+    destroy: function() {
+        var me = this;
+        me.editTask.cancel();
+        me.editors.each(Ext.destroy, Ext);
+        me.editors.clear();
+        me.callParent(arguments);
+    },
+    
+    onBodyScroll: function() {
+        var ed = this.getActiveEditor();
+        if (ed && ed.field) {
+            if (ed.field.triggerBlur) {
+                ed.field.triggerBlur();
+            } else {
+                ed.field.blur();
             }
-            this.el.setHeight(this.growMin);
         }
     },
 
-    onDestroy : function(){
-        Ext.removeNode(this.textSizeEl);
-        Ext.form.TextArea.superclass.onDestroy.call(this);
-    },
-
-    fireKey : function(e){
-        if(e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() != e.ENTER || e.hasModifier()))){
-            this.fireEvent("specialkey", this, e);
-        }
-    },
     
     
-    doAutoSize : function(e){
-        return !e.isNavKeyPress() || e.getKey() == e.ENTER;
+    initCancelTriggers: function() {
+        var me   = this,
+            grid = me.grid,
+            view = grid.view;
+            
+        view.addElListener('mousewheel', me.cancelEdit, me);
+        me.mon(view, 'bodyscroll', me.onBodyScroll, me);
+        me.mon(grid, {
+            columnresize: me.cancelEdit,
+            columnmove: me.cancelEdit,
+            scope: me
+        });
     },
 
     
-    autoSize: function(){
-        if(!this.grow || !this.textSizeEl){
-            return;
-        }
-        var el = this.el,
-            v = Ext.util.Format.htmlEncode(el.dom.value),
-            ts = this.textSizeEl,
-            h;
-            
-        Ext.fly(ts).setWidth(this.el.getWidth());
-        if(v.length < 1){
-            v = "&#160;&#160;";
-        }else{
-            v += this.growAppend;
-            if(Ext.isIE){
-                v = v.replace(/\n/g, '&#160;<br />');
-            }
-        }
-        ts.innerHTML = v;
-        h = Math.min(this.growMax, Math.max(ts.offsetHeight, this.growMin));
-        if(h != this.lastHeight){
-            this.lastHeight = h;
-            this.el.setHeight(h);
-            this.fireEvent("autosize", this, h);
-        }
-    }
-});
-Ext.reg('textarea', Ext.form.TextArea);
-Ext.form.NumberField = Ext.extend(Ext.form.TextField,  {
-    
-    
-    
-    fieldClass: "x-form-field x-form-num-field",
-    
-    allowDecimals : true,
-    
-    decimalSeparator : ".",
-    
-    decimalPrecision : 2,
-    
-    allowNegative : true,
-    
-    minValue : Number.NEGATIVE_INFINITY,
-    
-    maxValue : Number.MAX_VALUE,
-    
-    minText : "The minimum value for this field is {0}",
-    
-    maxText : "The maximum value for this field is {0}",
-    
-    nanText : "{0} is not a valid number",
-    
-    baseChars : "0123456789",
+    startEdit: function(record, columnHeader) {
+        var me = this,
+            value = record.get(columnHeader.dataIndex),
+            context = me.getEditingContext(record, columnHeader),
+            ed;
+
+        record = context.record;
+        columnHeader = context.column;
 
-    
-    initEvents : function(){
-        var allowed = this.baseChars + '';
-        if (this.allowDecimals) {
-            allowed += this.decimalSeparator;
-        }
-        if (this.allowNegative) {
-            allowed += '-';
-        }
-        this.maskRe = new RegExp('[' + Ext.escapeRe(allowed) + ']');
-        Ext.form.NumberField.superclass.initEvents.call(this);
-    },
-    
-    
-    getErrors: function(value) {
-        var errors = Ext.form.NumberField.superclass.getErrors.apply(this, arguments);
         
-        value = value || this.processValue(this.getRawValue());
         
-        if (value.length < 1) { 
-             return errors;
+        me.completeEdit();
+
+        context.originalValue = context.value = value;
+        if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
+            return false;
         }
         
-        value = String(value).replace(this.decimalSeparator, ".");
         
-        if(isNaN(value)){
-            errors.push(String.format(this.nanText, value));
+        if (columnHeader && !columnHeader.getEditor(record)) {
+            return false;
         }
         
-        var num = this.parseValue(value);
-        
-        if(num < this.minValue){
-            errors.push(String.format(this.minText, this.minValue));
+        ed = me.getEditor(record, columnHeader);
+        if (ed) {
+            me.context = context;
+            me.setActiveEditor(ed);
+            me.setActiveRecord(record);
+            me.setActiveColumn(columnHeader);
+
+            
+            me.editTask.delay(15, ed.startEdit, ed, [me.getCell(record, columnHeader), value]);
+        } else {
+            
+            
+            
+            
+            me.grid.getView().getEl(columnHeader).focus((Ext.isWebKit || Ext.isIE) ? 10 : false);
         }
-        
-        if(num > this.maxValue){
-            errors.push(String.format(this.maxText, this.maxValue));
+    },
+
+    completeEdit: function() {
+        var activeEd = this.getActiveEditor();
+        if (activeEd) {
+            activeEd.completeEdit();
         }
-        
-        return errors;
     },
 
-    getValue : function(){
-        return this.fixPrecision(this.parseValue(Ext.form.NumberField.superclass.getValue.call(this)));
+    
+    setActiveEditor: function(ed) {
+        this.activeEditor = ed;
+    },
+
+    getActiveEditor: function() {
+        return this.activeEditor;
+    },
+
+    setActiveColumn: function(column) {
+        this.activeColumn = column;
+    },
+
+    getActiveColumn: function() {
+        return this.activeColumn;
+    },
+
+    setActiveRecord: function(record) {
+        this.activeRecord = record;
+    },
+
+    getActiveRecord: function() {
+        return this.activeRecord;
     },
 
-    setValue : function(v){
-        v = this.fixPrecision(v);
-       v = Ext.isNumber(v) ? v : parseFloat(String(v).replace(this.decimalSeparator, "."));
-        v = isNaN(v) ? '' : String(v).replace(".", this.decimalSeparator);
-        return Ext.form.NumberField.superclass.setValue.call(this, v);
+    getEditor: function(record, column) {
+        var me = this,
+            editors = me.editors,
+            editorId = column.getItemId(),
+            editor = editors.getByKey(editorId);
+
+        if (editor) {
+            return editor;
+        } else {
+            editor = column.getEditor(record);
+            if (!editor) {
+                return false;
+            }
+
+            
+            if (!(editor instanceof Ext.grid.CellEditor)) {
+                editor = Ext.create('Ext.grid.CellEditor', {
+                    editorId: editorId,
+                    field: editor
+                });
+            }
+            editor.parentEl = me.grid.getEditorParent();
+            
+            editor.on({
+                scope: me,
+                specialkey: me.onSpecialKey,
+                complete: me.onEditComplete,
+                canceledit: me.cancelEdit
+            });
+            editors.add(editor);
+            return editor;
+        }
     },
     
     
-    setMinValue : function(value){
-        this.minValue = Ext.num(value, Number.NEGATIVE_INFINITY);
+    setColumnField: function(column, field) {
+        var ed = this.editors.getByKey(column.getItemId());
+        Ext.destroy(ed, column.field);
+        this.editors.removeAtKey(column.getItemId());
+        this.callParent(arguments);
     },
+
     
-    
-    setMaxValue : function(value){
-        this.maxValue = Ext.num(value, Number.MAX_VALUE);    
+    getCell: function(record, column) {
+        return this.grid.getView().getCell(record, column);
+    },
+
+    onSpecialKey: function(ed, field, e) {
+        var grid = this.grid,
+            sm;
+        if (e.getKey() === e.TAB) {
+            e.stopEvent();
+            sm = grid.getSelectionModel();
+            if (sm.onEditorTab) {
+                sm.onEditorTab(this, e);
+            }
+        }
     },
 
+    onEditComplete : function(ed, value, startValue) {
+        var me = this,
+            grid = me.grid,
+            sm = grid.getSelectionModel(),
+            activeColumn = me.getActiveColumn(),
+            dataIndex;
+
+        if (activeColumn) {
+            dataIndex = activeColumn.dataIndex;
+
+            me.setActiveEditor(null);
+            me.setActiveColumn(null);
+            me.setActiveRecord(null);
+            delete sm.wasEditing;
     
-    parseValue : function(value){
-        value = parseFloat(String(value).replace(this.decimalSeparator, "."));
-        return isNaN(value) ? '' : value;
+            if (!me.validateEdit()) {
+                return;
+            }
+            
+            
+            if (value !== startValue) {
+                me.context.record.set(dataIndex, value);
+            
+            } else {
+                grid.getView().getEl(activeColumn).focus();
+            }
+            me.context.value = value;
+            me.fireEvent('edit', me, me.context);
+        }
     },
 
     
-    fixPrecision : function(value){
-        var nan = isNaN(value);
-        if(!this.allowDecimals || this.decimalPrecision == -1 || nan || !value){
-           return nan ? '' : value;
+    cancelEdit: function() {
+        var me = this,
+            activeEd = me.getActiveEditor(),
+            viewEl = me.grid.getView().getEl(me.getActiveColumn());
+
+        me.setActiveEditor(null);
+        me.setActiveColumn(null);
+        me.setActiveRecord(null);
+        if (activeEd) {
+            activeEd.cancelEdit();
+            viewEl.focus();
         }
-        return parseFloat(parseFloat(value).toFixed(this.decimalPrecision));
     },
 
-    beforeBlur : function(){
-        var v = this.parseValue(this.getRawValue());
-        if(!Ext.isEmpty(v)){
-            this.setValue(v);
+    
+    startEditByPosition: function(position) {
+        var me = this,
+            grid = me.grid,
+            sm = grid.getSelectionModel(),
+            editRecord = grid.store.getAt(position.row),
+            editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
+
+        if (sm.selectByPosition) {
+            sm.selectByPosition(position);
         }
+        me.startEdit(editRecord, editColumnHeader);
     }
 });
-Ext.reg('numberfield', Ext.form.NumberField);
-Ext.form.DateField = Ext.extend(Ext.form.TriggerField,  {
-    
-    format : "m/d/Y",
-    
-    altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d",
-    
-    disabledDaysText : "Disabled",
-    
-    disabledDatesText : "Disabled",
-    
-    minText : "The date in this field must be equal to or after {0}",
-    
-    maxText : "The date in this field must be equal to or before {0}",
-    
-    invalidText : "{0} is not a valid date - it must be in the format {1}",
-    
-    triggerClass : 'x-form-date-trigger',
-    
-    showToday : true,
-    
-    
-    
+
+Ext.define('Ext.grid.plugin.DragDrop', {
+    extend: 'Ext.AbstractPlugin',
+    alias: 'plugin.gridviewdragdrop',
+
+    uses: [
+        'Ext.view.DragZone',
+        'Ext.grid.ViewDropZone'
+    ],
+
     
+
     
 
+    dragText : '{0} selected row{1}',
+
     
-    defaultAutoCreate : {tag: "input", type: "text", size: "10", autocomplete: "off"},
+    ddGroup : "GridDD",
 
     
+
     
-    initTime: '12', 
 
-    initTimeFormat: 'H',
+    
+    enableDrop: true,
 
     
-    safeParse : function(value, format) {
-        if (/[gGhH]/.test(format.replace(/(\\.)/g, ''))) {
-            
-            return Date.parseDate(value, format);
-        } else {
-            
-            var parsedDate = Date.parseDate(value + ' ' + this.initTime, format + ' ' + this.initTimeFormat);
+    enableDrag: true,
 
-            if (parsedDate) return parsedDate.clearTime();
-        }
+    init : function(view) {
+        view.on('render', this.onViewRender, this, {single: true});
     },
 
-    initComponent : function(){
-        Ext.form.DateField.superclass.initComponent.call(this);
-
-        this.addEvents(
-            
-            'select'
-        );
+    
+    destroy: function() {
+        Ext.destroy(this.dragZone, this.dropZone);
+    },
 
-        if(Ext.isString(this.minValue)){
-            this.minValue = this.parseDate(this.minValue);
+    enable: function() {
+        var me = this;
+        if (me.dragZone) {
+            me.dragZone.unlock();
         }
-        if(Ext.isString(this.maxValue)){
-            this.maxValue = this.parseDate(this.maxValue);
+        if (me.dropZone) {
+            me.dropZone.unlock();
         }
-        this.disabledDatesRE = null;
-        this.initDisabledDays();
+        me.callParent();
     },
 
-    initEvents: function() {
-        Ext.form.DateField.superclass.initEvents.call(this);
-        this.keyNav = new Ext.KeyNav(this.el, {
-            "down": function(e) {
-                this.onTriggerClick();
-            },
-            scope: this,
-            forceKeyDown: true
-        });
+    disable: function() {
+        var me = this;
+        if (me.dragZone) {
+            me.dragZone.lock();
+        }
+        if (me.dropZone) {
+            me.dropZone.lock();
+        }
+        me.callParent();
     },
 
+    onViewRender : function(view) {
+        var me = this;
 
-    
-    initDisabledDays : function(){
-        if(this.disabledDates){
-            var dd = this.disabledDates,
-                len = dd.length - 1,
-                re = "(?:";
-
-            Ext.each(dd, function(d, i){
-                re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
-                if(i != len){
-                    re += '|';
-                }
-            }, this);
-            this.disabledDatesRE = new RegExp(re + ')');
+        if (me.enableDrag) {
+            me.dragZone = Ext.create('Ext.view.DragZone', {
+                view: view,
+                ddGroup: me.dragGroup || me.ddGroup,
+                dragText: me.dragText
+            });
         }
-    },
 
-    
-    setDisabledDates : function(dd){
-        this.disabledDates = dd;
-        this.initDisabledDays();
-        if(this.menu){
-            this.menu.picker.setDisabledDates(this.disabledDatesRE);
+        if (me.enableDrop) {
+            me.dropZone = Ext.create('Ext.grid.ViewDropZone', {
+                view: view,
+                ddGroup: me.dropGroup || me.ddGroup
+            });
         }
+    }
+});
+
+Ext.define('Ext.grid.plugin.HeaderReorderer', {
+    extend: 'Ext.util.Observable',
+    requires: ['Ext.grid.header.DragZone', 'Ext.grid.header.DropZone'],
+    alias: 'plugin.gridheaderreorderer',
+
+    init: function(headerCt) {
+        this.headerCt = headerCt;
+        headerCt.on('render', this.onHeaderCtRender, this);
     },
 
     
-    setDisabledDays : function(dd){
-        this.disabledDays = dd;
-        if(this.menu){
-            this.menu.picker.setDisabledDays(dd);
-        }
+    destroy: function() {
+        Ext.destroy(this.dragZone, this.dropZone);
     },
 
-    
-    setMinValue : function(dt){
-        this.minValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
-        if(this.menu){
-            this.menu.picker.setMinDate(this.minValue);
+    onHeaderCtRender: function() {
+        this.dragZone = Ext.create('Ext.grid.header.DragZone', this.headerCt);
+        this.dropZone = Ext.create('Ext.grid.header.DropZone', this.headerCt);
+        if (this.disabled) {
+            this.dragZone.disable();
         }
     },
-
     
-    setMaxValue : function(dt){
-        this.maxValue = (Ext.isString(dt) ? this.parseDate(dt) : dt);
-        if(this.menu){
-            this.menu.picker.setMaxDate(this.maxValue);
+    enable: function() {
+        this.disabled = false;
+        if (this.dragZone) {
+            this.dragZone.enable();
         }
     },
-
     
-    getErrors: function(value) {
-        var errors = Ext.form.DateField.superclass.getErrors.apply(this, arguments);
+    disable: function() {
+        this.disabled = true;
+        if (this.dragZone) {
+            this.dragZone.disable();
+        }
+    }
+});
 
-        value = this.formatDate(value || this.processValue(this.getRawValue()));
+Ext.define('Ext.grid.plugin.HeaderResizer', {
+    extend: 'Ext.util.Observable',
+    requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
+    alias: 'plugin.gridheaderresizer',
 
-        if (value.length < 1) { 
-             return errors;
-        }
+    disabled: false,
 
-        var svalue = value;
-        value = this.parseDate(value);
-        if (!value) {
-            errors.push(String.format(this.invalidText, svalue, this.format));
-            return errors;
-        }
+    
+    configs: {
+        dynamic: true
+    },
 
-        var time = value.getTime();
-        if (this.minValue && time < this.minValue.clearTime().getTime()) {
-            errors.push(String.format(this.minText, this.formatDate(this.minValue)));
-        }
+    colHeaderCls: Ext.baseCSSPrefix + 'column-header',
 
-        if (this.maxValue && time > this.maxValue.clearTime().getTime()) {
-            errors.push(String.format(this.maxText, this.formatDate(this.maxValue)));
-        }
+    minColWidth: 40,
+    maxColWidth: 1000,
+    wResizeCursor: 'col-resize',
+    eResizeCursor: 'col-resize',
+    
+    
+    
+    
 
-        if (this.disabledDays) {
-            var day = value.getDay();
+    init: function(headerCt) {
+        this.headerCt = headerCt;
+        headerCt.on('render', this.afterHeaderRender, this, {single: true});
+    },
 
-            for(var i = 0; i < this.disabledDays.length; i++) {
-                if (day === this.disabledDays[i]) {
-                    errors.push(this.disabledDaysText);
-                    break;
-                }
-            }
+    
+    destroy: function() {
+        if (this.tracker) {
+            this.tracker.destroy();
         }
+    },
 
-        var fvalue = this.formatDate(value);
-        if (this.disabledDatesRE && this.disabledDatesRE.test(fvalue)) {
-            errors.push(String.format(this.disabledDatesText, fvalue));
-        }
+    afterHeaderRender: function() {
+        var headerCt = this.headerCt,
+            el = headerCt.el;
 
-        return errors;
+        headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
+
+        this.tracker = Ext.create('Ext.dd.DragTracker', {
+            disabled: this.disabled,
+            onBeforeStart: Ext.Function.bind(this.onBeforeStart, this),
+            onStart: Ext.Function.bind(this.onStart, this),
+            onDrag: Ext.Function.bind(this.onDrag, this),
+            onEnd: Ext.Function.bind(this.onEnd, this),
+            tolerance: 3,
+            autoStart: 300,
+            el: el
+        });
     },
 
     
     
-    validateBlur : function(){
-        return !this.menu || !this.menu.isVisible();
-    },
-
     
-    getValue : function(){
-        return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || "";
-    },
+    onHeaderCtMouseMove: function(e, t) {
+        if (this.headerCt.dragging) {
+            if (this.activeHd) {
+                this.activeHd.el.dom.style.cursor = '';
+                delete this.activeHd;
+            }
+        } else {
+            var headerEl = e.getTarget('.' + this.colHeaderCls, 3, true),
+                overHeader, resizeHeader;
 
-    
-    setValue : function(date){
-        return Ext.form.DateField.superclass.setValue.call(this, this.formatDate(this.parseDate(date)));
-    },
+            if (headerEl){
+                overHeader = Ext.getCmp(headerEl.id);
 
-    
-    parseDate : function(value) {
-        if(!value || Ext.isDate(value)){
-            return value;
-        }
+                
+                if (overHeader.isOnLeftEdge(e)) {
+                    resizeHeader = overHeader.previousNode('gridcolumn:not([hidden])');
 
-        var v = this.safeParse(value, this.format),
-            af = this.altFormats,
-            afa = this.altFormatsArray;
+                }
+                
+                else if (overHeader.isOnRightEdge(e)) {
+                    resizeHeader = overHeader;
+                }
+                
+                else {
+                    resizeHeader = null;
+                }
 
-        if (!v && af) {
-            afa = afa || af.split("|");
+                
+                if (resizeHeader) {
+                    
+                    
+                    
+                    if (resizeHeader.isGroupHeader) {
+                        resizeHeader = resizeHeader.down(':not([isGroupHeader]):not([hidden]):last');
+                    }
 
-            for (var i = 0, len = afa.length; i < len && !v; i++) {
-                v = this.safeParse(value, afa[i]);
+                    
+                    
+                    if (resizeHeader && !(resizeHeader.fixed || (resizeHeader.resizable === false) || this.disabled)) {
+                        this.activeHd = resizeHeader;
+                        overHeader.el.dom.style.cursor = this.eResizeCursor;
+                    }
+                
+                } else {
+                    overHeader.el.dom.style.cursor = '';
+                    delete this.activeHd;
+                }
             }
         }
-        return v;
     },
 
     
-    onDestroy : function(){
-        Ext.destroy(this.menu, this.keyNav);
-        Ext.form.DateField.superclass.onDestroy.call(this);
+    onBeforeStart : function(e){
+        var t = e.getTarget();
+        
+        this.dragHd = this.activeHd;
+
+        if (!!this.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger') && !this.headerCt.dragging) {
+            
+            this.tracker.constrainTo = this.getConstrainRegion();
+            return true;
+        } else {
+            this.headerCt.dragging = false;
+            return false;
+        }
     },
 
     
-    formatDate : function(date){
-        return Ext.isDate(date) ? date.dateFormat(this.format) : date;
+    getConstrainRegion: function() {
+        var dragHdEl = this.dragHd.el,
+            region   = Ext.util.Region.getRegion(dragHdEl);
+
+        return region.adjust(
+            0,
+            this.maxColWidth - dragHdEl.getWidth(),
+            0,
+            this.minColWidth
+        );
     },
 
     
     
-    
-    onTriggerClick : function(){
-        if(this.disabled){
-            return;
-        }
-        if(this.menu == null){
-            this.menu = new Ext.menu.DateMenu({
-                hideOnClick: false,
-                focusOnSelect: false
-            });
+    onStart: function(e){
+        var me       = this,
+            dragHd   = me.dragHd,
+            dragHdEl = dragHd.el,
+            width    = dragHdEl.getWidth(),
+            headerCt = me.headerCt,
+            t        = e.getTarget();
+
+        if (me.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger')) {
+            headerCt.dragging = true;
         }
-        this.onFocus();
-        Ext.apply(this.menu.picker,  {
-            minDate : this.minValue,
-            maxDate : this.maxValue,
-            disabledDatesRE : this.disabledDatesRE,
-            disabledDatesText : this.disabledDatesText,
-            disabledDays : this.disabledDays,
-            disabledDaysText : this.disabledDaysText,
-            format : this.format,
-            showToday : this.showToday,
-            minText : String.format(this.minText, this.formatDate(this.minValue)),
-            maxText : String.format(this.maxText, this.formatDate(this.maxValue))
-        });
-        this.menu.picker.setValue(this.getValue() || new Date());
-        this.menu.show(this.el, "tl-bl?");
-        this.menuEvents('on');
-    },
 
-    
-    menuEvents: function(method){
-        this.menu[method]('select', this.onSelect, this);
-        this.menu[method]('hide', this.onMenuHide, this);
-        this.menu[method]('show', this.onFocus, this);
-    },
+        me.origWidth = width;
 
-    onSelect: function(m, d){
-        this.setValue(d);
-        this.fireEvent('select', this, d);
-        this.menu.hide();
-    },
+        
+        if (!me.dynamic) {
+            var xy           = dragHdEl.getXY(),
+                gridSection  = headerCt.up('[scrollerOwner]'),
+                dragHct      = me.dragHd.up(':not([isGroupHeader])'),
+                firstSection = dragHct.up(),
+                lhsMarker    = gridSection.getLhsMarker(),
+                rhsMarker    = gridSection.getRhsMarker(),
+                el           = rhsMarker.parent(),
+                offsetLeft   = el.getLeft(true),
+                offsetTop    = el.getTop(true),
+                topLeft      = el.translatePoints(xy),
+                markerHeight = firstSection.body.getHeight() + headerCt.getHeight(),
+                top = topLeft.top - offsetTop;
 
-    onMenuHide: function(){
-        this.focus(false, 60);
-        this.menuEvents('un');
+            lhsMarker.setTop(top);
+            rhsMarker.setTop(top);
+            lhsMarker.setHeight(markerHeight);
+            rhsMarker.setHeight(markerHeight);
+            lhsMarker.setLeft(topLeft.left - offsetLeft);
+            rhsMarker.setLeft(topLeft.left + width - offsetLeft);
+        }
     },
 
     
-    beforeBlur : function(){
-        var v = this.parseDate(this.getRawValue());
-        if(v){
-            this.setValue(v);
+    onDrag: function(e){
+        if (!this.dynamic) {
+            var xy          = this.tracker.getXY('point'),
+                gridSection = this.headerCt.up('[scrollerOwner]'),
+                rhsMarker   = gridSection.getRhsMarker(),
+                el          = rhsMarker.parent(),
+                topLeft     = el.translatePoints(xy),
+                offsetLeft  = el.getLeft(true);
+
+            rhsMarker.setLeft(topLeft.left - offsetLeft);
+        
+        } else {
+            this.doResize();
         }
-    }
+    },
 
-    
-    
-    
-    
-});
-Ext.reg('datefield', Ext.form.DateField);
+    onEnd: function(e){
+        this.headerCt.dragging = false;
+        if (this.dragHd) {
+            if (!this.dynamic) {
+                var dragHd      = this.dragHd,
+                    gridSection = this.headerCt.up('[scrollerOwner]'),
+                    lhsMarker   = gridSection.getLhsMarker(),
+                    rhsMarker   = gridSection.getRhsMarker(),
+                    currWidth   = dragHd.getWidth(),
+                    offset      = this.tracker.getOffset('point'),
+                    offscreen   = -9999;
 
-Ext.form.DisplayField = Ext.extend(Ext.form.Field,  {
-    validationEvent : false,
-    validateOnBlur : false,
-    defaultAutoCreate : {tag: "div"},
-    
-    fieldClass : "x-form-display-field",
-    
-    htmlEncode: false,
+                
+                lhsMarker.setLeft(offscreen);
+                rhsMarker.setLeft(offscreen);
+            }
+            this.doResize();
+        }
+    },
 
-    
-    initEvents : Ext.emptyFn,
+    doResize: function() {
+        if (this.dragHd) {
+            var dragHd = this.dragHd,
+                nextHd,
+                offset = this.tracker.getOffset('point');
 
-    isValid : function(){
-        return true;
-    },
+            
+            if (dragHd.flex) {
+                delete dragHd.flex;
+            }
 
-    validate : function(){
-        return true;
-    },
+            this.headerCt.suspendLayout = true;
+            dragHd.setWidth(this.origWidth + offset[0], false);
 
-    getRawValue : function(){
-        var v = this.rendered ? this.el.dom.innerHTML : Ext.value(this.value, '');
-        if(v === this.emptyText){
-            v = '';
-        }
-        if(this.htmlEncode){
-            v = Ext.util.Format.htmlDecode(v);
+            
+            
+            
+            
+            if (this.headerCt.forceFit) {
+                nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
+                if (nextHd) {
+                    delete nextHd.flex;
+                    nextHd.setWidth(nextHd.getWidth() - offset[0], false);
+                }
+            }
+            this.headerCt.suspendLayout = false;
+            this.headerCt.doComponentLayout(this.headerCt.getFullWidth());
         }
-        return v;
-    },
-
-    getValue : function(){
-        return this.getRawValue();
-    },
-    
-    getName: function() {
-        return this.name;
     },
 
-    setRawValue : function(v){
-        if(this.htmlEncode){
-            v = Ext.util.Format.htmlEncode(v);
+    disable: function() {
+        this.disabled = true;
+        if (this.tracker) {
+            this.tracker.disable();
         }
-        return this.rendered ? (this.el.dom.innerHTML = (Ext.isEmpty(v) ? '' : v)) : (this.value = v);
     },
 
-    setValue : function(v){
-        this.setRawValue(v);
-        return this;
+    enable: function() {
+        this.disabled = false;
+        if (this.tracker) {
+            this.tracker.enable();
+        }
     }
-    
-    
-    
-    
-    
-    
 });
 
-Ext.reg('displayfield', Ext.form.DisplayField);
+Ext.define('Ext.grid.plugin.RowEditing', {
+    extend: 'Ext.grid.plugin.Editing',
+    alias: 'plugin.rowediting',
 
-Ext.form.ComboBox = Ext.extend(Ext.form.TriggerField, {
-    
-    
-    
-    
-    
+    requires: [
+        'Ext.grid.RowEditor'
+    ],
+
+    editStyle: 'row',
 
     
-    defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
-    
-    
-    
-    
-    
-    
-    
-    listClass : '',
-    
-    selectedClass : 'x-combo-selected',
-    
-    listEmptyText: '',
-    
-    triggerClass : 'x-form-arrow-trigger',
-    
-    shadow : 'sides',
-    
-    listAlign : 'tl-bl?',
-    
-    maxHeight : 300,
-    
-    minHeight : 90,
-    
-    triggerAction : 'query',
-    
-    minChars : 4,
-    
-    autoSelect : true,
-    
-    typeAhead : false,
-    
-    queryDelay : 500,
-    
-    pageSize : 0,
-    
-    selectOnFocus : false,
-    
-    queryParam : 'query',
-    
-    loadingText : 'Loading...',
+    autoCancel: true,
+
     
-    resizable : false,
+
     
-    handleHeight : 8,
+    errorSummary: true,
+
     
-    allQuery: '',
     
-    mode: 'remote',
     
-    minListWidth : 70,
     
-    forceSelection : false,
     
-    typeAheadDelay : 250,
     
 
-    
-    lazyInit : true,
+    constructor: function() {
+        var me = this;
+        me.callParent(arguments);
 
-    
-    clearFilterOnReset : true,
+        if (!me.clicksToMoveEditor) {
+            me.clicksToMoveEditor = me.clicksToEdit;
+        }
 
-    
-    submitValue: undefined,
+        me.autoCancel = !!me.autoCancel;
+    },
 
     
+    destroy: function() {
+        var me = this;
+        Ext.destroy(me.editor);
+        me.callParent(arguments);
+    },
 
     
-    initComponent : function(){
-        Ext.form.ComboBox.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'expand',
-            
-            'collapse',
+    startEdit: function(record, columnHeader) {
+        var me = this,
+            editor = me.getEditor();
 
-            
-            'beforeselect',
-            
-            'select',
-            
-            'beforequery'
-        );
-        if(this.transform){
-            var s = Ext.getDom(this.transform);
-            if(!this.hiddenName){
-                this.hiddenName = s.name;
-            }
-            if(!this.store){
-                this.mode = 'local';
-                var d = [], opts = s.options;
-                for(var i = 0, len = opts.length;i < len; i++){
-                    var o = opts[i],
-                        value = (o.hasAttribute ? o.hasAttribute('value') : o.getAttributeNode('value').specified) ? o.value : o.text;
-                    if(o.selected && Ext.isEmpty(this.value, true)) {
-                        this.value = value;
-                    }
-                    d.push([value, o.text]);
-                }
-                this.store = new Ext.data.ArrayStore({
-                    'id': 0,
-                    fields: ['value', 'text'],
-                    data : d,
-                    autoDestroy: true
-                });
-                this.valueField = 'value';
-                this.displayField = 'text';
-            }
-            s.name = Ext.id(); 
-            if(!this.lazyRender){
-                this.target = true;
-                this.el = Ext.DomHelper.insertBefore(s, this.autoCreate || this.defaultAutoCreate);
-                this.render(this.el.parentNode, s);
-            }
-            Ext.removeNode(s);
-        }
-        
-        else if(this.store){
-            this.store = Ext.StoreMgr.lookup(this.store);
-            if(this.store.autoCreated){
-                this.displayField = this.valueField = 'field1';
-                if(!this.store.expandData){
-                    this.displayField = 'field2';
-                }
-                this.mode = 'local';
-            }
+        if (me.callParent(arguments) === false) {
+            return false;
         }
 
-        this.selectedIndex = -1;
-        if(this.mode == 'local'){
-            if(!Ext.isDefined(this.initialConfig.queryDelay)){
-                this.queryDelay = 10;
-            }
-            if(!Ext.isDefined(this.initialConfig.minChars)){
-                this.minChars = 0;
-            }
+        
+        if (editor.beforeEdit() !== false) {
+            editor.startEdit(me.context.record, me.context.column);
         }
     },
 
     
-    onRender : function(ct, position){
-        if(this.hiddenName && !Ext.isDefined(this.submitValue)){
-            this.submitValue = false;
-        }
-        Ext.form.ComboBox.superclass.onRender.call(this, ct, position);
-        if(this.hiddenName){
-            this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName,
-                    id: (this.hiddenId||this.hiddenName)}, 'before', true);
-
-        }
-        if(Ext.isGecko){
-            this.el.dom.setAttribute('autocomplete', 'off');
-        }
+    cancelEdit: function() {
+        var me = this;
 
-        if(!this.lazyInit){
-            this.initList();
-        }else{
-            this.on('focus', this.initList, this, {single: true});
+        if (me.editing) {
+            me.getEditor().cancelEdit();
+            me.callParent(arguments);
+            
+            me.fireEvent('canceledit', me.context);
         }
     },
 
     
-    initValue : function(){
-        Ext.form.ComboBox.superclass.initValue.call(this);
-        if(this.hiddenField){
-            this.hiddenField.value =
-                Ext.value(Ext.isDefined(this.hiddenValue) ? this.hiddenValue : this.value, '');
+    completeEdit: function() {
+        var me = this;
+
+        if (me.editing && me.validateEdit()) {
+            me.editing = false;
+            me.fireEvent('edit', me.context);
         }
     },
 
-    getParentZIndex : function(){
-        var zindex;
-        if (this.ownerCt){
-            this.findParentBy(function(ct){
-                zindex = parseInt(ct.getPositionEl().getStyle('z-index'), 10);
-                return !!zindex;
-            });
-        }
-        return zindex;
+    
+    validateEdit: function() {
+        var me             = this,
+            editor         = me.editor,
+            context        = me.context,
+            record         = context.record,
+            newValues      = {},
+            originalValues = {},
+            name;
+
+        editor.items.each(function(item) {
+            name = item.name;
+
+            newValues[name]      = item.getValue();
+            originalValues[name] = record.get(name);
+        });
+
+        Ext.apply(context, {
+            newValues      : newValues,
+            originalValues : originalValues
+        });
+
+        return me.callParent(arguments) && me.getEditor().completeEdit();
     },
+
     
-    getZIndex : function(listParent){
-        listParent = listParent || Ext.getDom(this.getListParent() || Ext.getBody());
-        var zindex = parseInt(Ext.fly(listParent).getStyle('z-index'), 10);
-        if(!zindex){
-            zindex = this.getParentZIndex();
+    getEditor: function() {
+        var me = this;
+
+        if (!me.editor) {
+            me.editor = me.initEditor();
         }
-        return (zindex || 12000) + 5;
+        return me.editor;
     },
 
     
-    initList : function(){
-        if(!this.list){
-            var cls = 'x-combo-list',
-                listParent = Ext.getDom(this.getListParent() || Ext.getBody());
+    initEditor: function() {
+        var me = this,
+            grid = me.grid,
+            view = me.view,
+            headerCt = grid.headerCt;
 
-            this.list = new Ext.Layer({
-                parentEl: listParent,
-                shadow: this.shadow,
-                cls: [cls, this.listClass].join(' '),
-                constrain:false,
-                zindex: this.getZIndex(listParent)
-            });
+        return Ext.create('Ext.grid.RowEditor', {
+            autoCancel: me.autoCancel,
+            errorSummary: me.errorSummary,
+            fields: headerCt.getGridColumns(),
+            hidden: true,
 
-            var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
-            this.list.setSize(lw, 0);
-            this.list.swallowEvent('mousewheel');
-            this.assetHeight = 0;
-            if(this.syncFont !== false){
-                this.list.setStyle('font-size', this.el.getStyle('font-size'));
-            }
-            if(this.title){
-                this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
-                this.assetHeight += this.header.getHeight();
-            }
+            
+            editingPlugin: me,
+            renderTo: view.el
+        });
+    },
 
-            this.innerList = this.list.createChild({cls:cls+'-inner'});
-            this.mon(this.innerList, 'mouseover', this.onViewOver, this);
-            this.mon(this.innerList, 'mousemove', this.onViewMove, this);
-            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
+    
+    initEditTriggers: function() {
+        var me = this,
+            grid = me.grid,
+            view = me.view,
+            headerCt = grid.headerCt,
+            moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick';
 
-            if(this.pageSize){
-                this.footer = this.list.createChild({cls:cls+'-ft'});
-                this.pageTb = new Ext.PagingToolbar({
-                    store: this.store,
-                    pageSize: this.pageSize,
-                    renderTo:this.footer
-                });
-                this.assetHeight += this.footer.getHeight();
-            }
+        me.callParent(arguments);
 
-            if(!this.tpl){
-                
-                this.tpl = '<tpl for="."><div class="'+cls+'-item">{' + this.displayField + '}</div></tpl>';
-                
-            }
+        if (me.clicksToMoveEditor !== me.clicksToEdit) {
+            me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me);
+        }
 
+        view.on('render', function() {
             
-            this.view = new Ext.DataView({
-                applyTo: this.innerList,
-                tpl: this.tpl,
-                singleSelect: true,
-                selectedClass: this.selectedClass,
-                itemSelector: this.itemSelector || '.' + cls + '-item',
-                emptyText: this.listEmptyText,
-                deferEmptyText: false
+            me.mon(headerCt, {
+                add: me.onColumnAdd,
+                remove: me.onColumnRemove,
+                columnresize: me.onColumnResize,
+                columnhide: me.onColumnHide,
+                columnshow: me.onColumnShow,
+                columnmove: me.onColumnMove,
+                scope: me
             });
+        }, me, { single: true });
+    },
 
-            this.mon(this.view, {
-                containerclick : this.onViewClick,
-                click : this.onViewClick,
-                scope :this
-            });
+    startEditByClick: function() {
+        var me = this;
+        if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) {
+            me.callParent(arguments);
+        }
+    },
+
+    moveEditorByClick: function() {
+        var me = this;
+        if (me.editing) {
+            me.superclass.startEditByClick.apply(me, arguments);
+        }
+    },
 
-            this.bindStore(this.store, true);
+    
+    onColumnAdd: function(ct, column) {
+        if (column.isHeader) {
+            var me = this,
+                editor;
 
-            if(this.resizable){
-                this.resizer = new Ext.Resizable(this.list,  {
-                   pinned:true, handles:'se'
-                });
-                this.mon(this.resizer, 'resize', function(r, w, h){
-                    this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
-                    this.listWidth = w;
-                    this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
-                    this.restrictHeight();
-                }, this);
+            me.initFieldAccessors(column);
+            editor = me.getEditor();
 
-                this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
+            if (editor && editor.onColumnAdd) {
+                editor.onColumnAdd(column);
             }
         }
     },
 
     
-    getListParent : function() {
-        return document.body;
-    },
+    onColumnRemove: function(ct, column) {
+        if (column.isHeader) {
+            var me = this,
+                editor = me.getEditor();
 
-    
-    getStore : function(){
-        return this.store;
+            if (editor && editor.onColumnRemove) {
+                editor.onColumnRemove(column);
+            }
+            me.removeFieldAccessors(column);
+        }
     },
 
     
-    bindStore : function(store, initial){
-        if(this.store && !initial){
-            if(this.store !== store && this.store.autoDestroy){
-                this.store.destroy();
-            }else{
-                this.store.un('beforeload', this.onBeforeLoad, this);
-                this.store.un('load', this.onLoad, this);
-                this.store.un('exception', this.collapse, this);
-            }
-            if(!store){
-                this.store = null;
-                if(this.view){
-                    this.view.bindStore(null);
-                }
-                if(this.pageTb){
-                    this.pageTb.bindStore(null);
-                }
+    onColumnResize: function(ct, column, width) {
+        if (column.isHeader) {
+            var me = this,
+                editor = me.getEditor();
+
+            if (editor && editor.onColumnResize) {
+                editor.onColumnResize(column, width);
             }
         }
-        if(store){
-            if(!initial) {
-                this.lastQuery = null;
-                if(this.pageTb) {
-                    this.pageTb.bindStore(store);
-                }
-            }
+    },
 
-            this.store = Ext.StoreMgr.lookup(store);
-            this.store.on({
-                scope: this,
-                beforeload: this.onBeforeLoad,
-                load: this.onLoad,
-                exception: this.collapse
-            });
+    
+    onColumnHide: function(ct, column) {
+        
+        var me = this,
+            editor = me.getEditor();
 
-            if(this.view){
-                this.view.bindStore(store);
-            }
+        if (editor && editor.onColumnHide) {
+            editor.onColumnHide(column);
         }
     },
 
-    reset : function(){
-        Ext.form.ComboBox.superclass.reset.call(this);
-        if(this.clearFilterOnReset && this.mode == 'local'){
-            this.store.clearFilter();
+    
+    onColumnShow: function(ct, column) {
+        
+        var me = this,
+            editor = me.getEditor();
+
+        if (editor && editor.onColumnShow) {
+            editor.onColumnShow(column);
         }
     },
 
     
-    initEvents : function(){
-        Ext.form.ComboBox.superclass.initEvents.call(this);
-
+    onColumnMove: function(ct, column, fromIdx, toIdx) {
         
-        this.keyNav = new Ext.KeyNav(this.el, {
-            "up" : function(e){
-                this.inKeyMode = true;
-                this.selectPrev();
-            },
+        var me = this,
+            editor = me.getEditor();
 
-            "down" : function(e){
-                if(!this.isExpanded()){
-                    this.onTriggerClick();
-                }else{
-                    this.inKeyMode = true;
-                    this.selectNext();
-                }
-            },
+        if (editor && editor.onColumnMove) {
+            editor.onColumnMove(column, fromIdx, toIdx);
+        }
+    },
 
-            "enter" : function(e){
-                this.onViewClick();
-            },
+    
+    setColumnField: function(column, field) {
+        var me = this;
+        me.callParent(arguments);
+        me.getEditor().setField(column.field, column);
+    }
+});
 
-            "esc" : function(e){
-                this.collapse();
-            },
 
-            "tab" : function(e){
-                if (this.forceSelection === true) {
-                    this.collapse();
-                } else {
-                    this.onViewClick(false);
-                }
-                return true;
-            },
+Ext.define('Ext.grid.property.Grid', {
 
-            scope : this,
+    extend: 'Ext.grid.Panel',
 
-            doRelay : function(e, h, hname){
-                if(hname == 'down' || this.scope.isExpanded()){
-                    
-                    var relay = Ext.KeyNav.prototype.doRelay.apply(this, arguments);
-                    if(!Ext.isIE && Ext.EventManager.useKeydown){
-                        
-                        this.scope.fireKey(e);
-                    }
-                    return relay;
-                }
-                return true;
-            },
+    alias: 'widget.propertygrid',
 
-            forceKeyDown : true,
-            defaultEventAction: 'stopEvent'
-        });
-        this.queryDelay = Math.max(this.queryDelay || 10,
-                this.mode == 'local' ? 10 : 250);
-        this.dqTask = new Ext.util.DelayedTask(this.initQuery, this);
-        if(this.typeAhead){
-            this.taTask = new Ext.util.DelayedTask(this.onTypeAhead, this);
-        }
-        if(!this.enableKeyEvents){
-            this.mon(this.el, 'keyup', this.onKeyUp, this);
-        }
-    },
+    alternateClassName: 'Ext.grid.PropertyGrid',
+
+    uses: [
+       'Ext.grid.plugin.CellEditing',
+       'Ext.grid.property.Store',
+       'Ext.grid.property.HeaderContainer',
+       'Ext.XTemplate',
+       'Ext.grid.CellEditor',
+       'Ext.form.field.Date',
+       'Ext.form.field.Text',
+       'Ext.form.field.Number'
+    ],
 
+   
 
     
-    onDestroy : function(){
-        if (this.dqTask){
-            this.dqTask.cancel();
-            this.dqTask = null;
-        }
-        this.bindStore(null);
-        Ext.destroy(
-            this.resizer,
-            this.view,
-            this.pageTb,
-            this.list
-        );
-        Ext.destroyMembers(this, 'hiddenField');
-        Ext.form.ComboBox.superclass.onDestroy.call(this);
-    },
 
     
-    fireKey : function(e){
-        if (!this.isExpanded()) {
-            Ext.form.ComboBox.superclass.fireKey.call(this, e);
-        }
-    },
 
     
-    onResize : function(w, h){
-        Ext.form.ComboBox.superclass.onResize.apply(this, arguments);
-        if(!isNaN(w) && this.isVisible() && this.list){
-            this.doResize(w);
-        }else{
-            this.bufferSize = w;
-        }
-    },
 
-    doResize: function(w){
-        if(!Ext.isDefined(this.listWidth)){
-            var lw = Math.max(w, this.minListWidth);
-            this.list.setWidth(lw);
-            this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
-        }
-    },
+    
 
     
-    onEnable : function(){
-        Ext.form.ComboBox.superclass.onEnable.apply(this, arguments);
-        if(this.hiddenField){
-            this.hiddenField.disabled = false;
-        }
-    },
+    valueField: 'value',
 
     
-    onDisable : function(){
-        Ext.form.ComboBox.superclass.onDisable.apply(this, arguments);
-        if(this.hiddenField){
-            this.hiddenField.disabled = true;
-        }
-    },
+    nameField: 'name',
 
     
-    onBeforeLoad : function(){
-        if(!this.hasFocus){
-            return;
-        }
-        this.innerList.update(this.loadingText ?
-               '<div class="loading-indicator">'+this.loadingText+'</div>' : '');
-        this.restrictHeight();
-        this.selectedIndex = -1;
-    },
 
     
-    onLoad : function(){
-        if(!this.hasFocus){
-            return;
-        }
-        if(this.store.getCount() > 0 || this.listEmptyText){
-            this.expand();
-            this.restrictHeight();
-            if(this.lastQuery == this.allQuery){
-                if(this.editable){
-                    this.el.dom.select();
-                }
+    enableColumnMove: false,
+    columnLines: true,
+    stripeRows: false,
+    trackMouseOver: false,
+    clicksToEdit: 1,
+    enableHdMenu: false,
 
-                if(this.autoSelect !== false && !this.selectByValue(this.value, true)){
-                    this.select(0, true);
-                }
-            }else{
-                if(this.autoSelect !== false){
-                    this.selectNext();
-                }
-                if(this.typeAhead && this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE){
-                    this.taTask.delay(this.typeAheadDelay);
+    
+    initComponent : function(){
+        var me = this;
+
+        me.addCls(Ext.baseCSSPrefix + 'property-grid');
+        me.plugins = me.plugins || [];
+
+        
+        me.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {
+            clicksToEdit: me.clicksToEdit,
+
+            
+            startEdit: function(record, column) {
+                
+                return this.self.prototype.startEdit.call(this, record, me.headerCt.child('#' + me.valueField));
+            }
+        }));
+
+        me.selModel = {
+            selType: 'cellmodel',
+            onCellSelect: function(position) {
+                if (position.column != 1) {
+                    position.column = 1;
                 }
+                return this.self.prototype.onCellSelect.call(this, position);
             }
-        }else{
-            this.collapse();
+        };
+        me.customRenderers = me.customRenderers || {};
+        me.customEditors = me.customEditors || {};
+
+        
+        if (!me.store) {
+            me.propStore = me.store = Ext.create('Ext.grid.property.Store', me, me.source);
         }
 
-    },
+        me.store.sort('name', 'ASC');
+        me.columns = Ext.create('Ext.grid.property.HeaderContainer', me, me.store);
 
-    
-    onTypeAhead : function(){
-        if(this.store.getCount() > 0){
-            var r = this.store.getAt(0);
-            var newValue = r.data[this.displayField];
-            var len = newValue.length;
-            var selStart = this.getRawValue().length;
-            if(selStart != len){
-                this.setRawValue(newValue);
-                this.selectText(selStart, newValue.length);
-            }
-        }
+        me.addEvents(
+            
+            'beforepropertychange',
+            
+            'propertychange'
+        );
+        me.callParent();
+
+        
+        me.getView().walkCells = this.walkCells;
+
+        
+        me.editors = {
+            'date'    : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date',   {selectOnFocus: true})}),
+            'string'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text',   {selectOnFocus: true})}),
+            'number'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
+            'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
+                editable: false,
+                store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]]
+            })})
+        };
+
+        
+        me.store.on('update', me.onUpdate, me);
     },
 
     
-    assertValue  : function(){
-        var val = this.getRawValue(),
-            rec = this.findRecord(this.displayField, val);
-
-        if(!rec && this.forceSelection){
-            if(val.length > 0 && val != this.emptyText){
-                this.el.dom.value = Ext.value(this.lastSelectionText, '');
-                this.applyEmptyText();
-            }else{
-                this.clearValue();
-            }
-        }else{
-            if(rec){
-                
-                
-                
-                if (val == rec.get(this.displayField) && this.value == rec.get(this.valueField)){
-                    return;
+    onUpdate : function(store, record, operation) {
+        var me = this,
+            v, oldValue;
+
+        if (operation == Ext.data.Model.EDIT) {
+            v = record.get(me.valueField);
+            oldValue = record.modified.value;
+            if (me.fireEvent('beforepropertychange', me.source, record.getId(), v, oldValue) !== false) {
+                if (me.source) {
+                    me.source[record.getId()] = v;
                 }
-                val = rec.get(this.valueField || this.displayField);
+                record.commit();
+                me.fireEvent('propertychange', me.source, record.getId(), v, oldValue);
+            } else {
+                record.reject();
             }
-            this.setValue(val);
         }
     },
 
     
-    onSelect : function(record, index){
-        if(this.fireEvent('beforeselect', this, record, index) !== false){
-            this.setValue(record.data[this.valueField || this.displayField]);
-            this.collapse();
-            this.fireEvent('select', this, record, index);
+    walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
+        if (direction == 'left') {
+            direction = 'up';
+        } else if (direction == 'right') {
+            direction = 'down';
         }
+        pos = Ext.view.Table.prototype.walkCells.call(this, pos, direction, e, preventWrap, verifierFn, scope);
+        if (!pos.column) {
+            pos.column = 1;
+        }
+        return pos;
     },
 
     
-    getName: function(){
-        var hf = this.hiddenField;
-        return hf && hf.name ? hf.name : this.hiddenName || Ext.form.ComboBox.superclass.getName.call(this);
-    },
-
     
-    getValue : function(){
-        if(this.valueField){
-            return Ext.isDefined(this.value) ? this.value : '';
-        }else{
-            return Ext.form.ComboBox.superclass.getValue.call(this);
+    getCellEditor : function(record, column) {
+        var me = this,
+            propName = record.get(me.nameField),
+            val = record.get(me.valueField),
+            editor = me.customEditors[propName];
+
+        
+        
+        if (editor) {
+            if (!(editor instanceof Ext.grid.CellEditor)) {
+                if (!(editor instanceof Ext.form.field.Base)) {
+                    editor = Ext.ComponentManager.create(editor, 'textfield');
+                }
+                editor = me.customEditors[propName] = Ext.create('Ext.grid.CellEditor', { field: editor });
+            }
+        } else if (Ext.isDate(val)) {
+            editor = me.editors.date;
+        } else if (Ext.isNumber(val)) {
+            editor = me.editors.number;
+        } else if (Ext.isBoolean(val)) {
+            editor = me.editors['boolean'];
+        } else {
+            editor = me.editors.string;
         }
+
+        
+        editor.editorId = propName;
+        return editor;
     },
 
-    
-    clearValue : function(){
-        if(this.hiddenField){
-            this.hiddenField.value = '';
-        }
-        this.setRawValue('');
-        this.lastSelectionText = '';
-        this.applyEmptyText();
-        this.value = '';
+    beforeDestroy: function() {
+        var me = this;
+        me.callParent();
+        me.destroyEditors(me.editors);
+        me.destroyEditors(me.customEditors);
+        delete me.source;
     },
 
-    
-    setValue : function(v){
-        var text = v;
-        if(this.valueField){
-            var r = this.findRecord(this.valueField, v);
-            if(r){
-                text = r.data[this.displayField];
-            }else if(Ext.isDefined(this.valueNotFoundText)){
-                text = this.valueNotFoundText;
+    destroyEditors: function (editors) {
+        for (var ed in editors) {
+            if (editors.hasOwnProperty(ed)) {
+                Ext.destroy(editors[ed]);
             }
         }
-        this.lastSelectionText = text;
-        if(this.hiddenField){
-            this.hiddenField.value = Ext.value(v, '');
-        }
-        Ext.form.ComboBox.superclass.setValue.call(this, text);
-        this.value = v;
-        return this;
     },
 
     
-    findRecord : function(prop, value){
-        var record;
-        if(this.store.getCount() > 0){
-            this.store.each(function(r){
-                if(r.data[prop] == value){
-                    record = r;
-                    return false;
-                }
-            });
-        }
-        return record;
+    setSource: function(source) {
+        this.source = source;
+        this.propStore.setSource(source);
     },
 
     
-    onViewMove : function(e, t){
-        this.inKeyMode = false;
+    getSource: function() {
+        return this.propStore.getSource();
     },
 
     
-    onViewOver : function(e, t){
-        if(this.inKeyMode){ 
-            return;
-        }
-        var item = this.view.findItemFromChild(t);
-        if(item){
-            var index = this.view.indexOf(item);
-            this.select(index, false);
-        }
+    setProperty: function(prop, value, create) {
+        this.propStore.setValue(prop, value, create);
     },
 
     
-    onViewClick : function(doFocus){
-        var index = this.view.getSelectedIndexes()[0],
-            s = this.store,
-            r = s.getAt(index);
-        if(r){
-            this.onSelect(r, index);
-        }else {
-            this.collapse();
-        }
-        if(doFocus !== false){
-            this.el.focus();
-        }
-    },
-
+    removeProperty: function(prop) {
+        this.propStore.remove(prop);
+    }
 
     
-    restrictHeight : function(){
-        this.innerList.dom.style.height = '';
-        var inner = this.innerList.dom,
-            pad = this.list.getFrameWidth('tb') + (this.resizable ? this.handleHeight : 0) + this.assetHeight,
-            h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight),
-            ha = this.getPosition()[1]-Ext.getBody().getScroll().top,
-            hb = Ext.lib.Dom.getViewHeight()-ha-this.getSize().height,
-            space = Math.max(ha, hb, this.minHeight || 0)-this.list.shadowOffset-pad-5;
+    
+    
+    
+});
 
-        h = Math.min(h, space, this.maxHeight);
+Ext.define('Ext.grid.property.HeaderContainer', {
 
-        this.innerList.setHeight(h);
-        this.list.beginUpdate();
-        this.list.setHeight(h+pad);
-        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
-        this.list.endUpdate();
-    },
+    extend: 'Ext.grid.header.Container',
 
+    alternateClassName: 'Ext.grid.PropertyColumnModel',
     
-    isExpanded : function(){
-        return this.list && this.list.isVisible();
-    },
+    nameWidth: 115,
 
     
-    selectByValue : function(v, scrollIntoView){
-        if(!Ext.isEmpty(v, true)){
-            var r = this.findRecord(this.valueField || this.displayField, v);
-            if(r){
-                this.select(this.store.indexOf(r), scrollIntoView);
-                return true;
-            }
-        }
-        return false;
-    },
+    nameText : 'Name',
+    valueText : 'Value',
+    dateFormat : 'm/j/Y',
+    trueText: 'true',
+    falseText: 'false',
 
     
-    select : function(index, scrollIntoView){
-        this.selectedIndex = index;
-        this.view.select(index);
-        if(scrollIntoView !== false){
-            var el = this.view.getNode(index);
-            if(el){
-                this.innerList.scrollChildIntoView(el, false);
-            }
-        }
+    nameColumnCls: Ext.baseCSSPrefix + 'grid-property-name',
 
+    
+    constructor : function(grid, store) {
+        var me = this;
+        
+        me.grid = grid;
+        me.store = store;
+        me.callParent([{
+            items: [{
+                header: me.nameText,
+                width: grid.nameColumnWidth || me.nameWidth,
+                sortable: true,
+                dataIndex: grid.nameField,
+                renderer: Ext.Function.bind(me.renderProp, me),
+                itemId: grid.nameField,
+                menuDisabled :true,
+                tdCls: me.nameColumnCls
+            }, {
+                header: me.valueText,
+                renderer: Ext.Function.bind(me.renderCell, me),
+                getEditor: Ext.Function.bind(me.getCellEditor, me),
+                flex: 1,
+                fixed: true,
+                dataIndex: grid.valueField,
+                itemId: grid.valueField,
+                menuDisabled: true
+            }]
+        }]);
     },
-
     
-    selectNext : function(){
-        var ct = this.store.getCount();
-        if(ct > 0){
-            if(this.selectedIndex == -1){
-                this.select(0);
-            }else if(this.selectedIndex < ct-1){
-                this.select(this.selectedIndex+1);
-            }
-        }
+    getCellEditor: function(record){
+        return this.grid.getCellEditor(record, this);
     },
 
     
-    selectPrev : function(){
-        var ct = this.store.getCount();
-        if(ct > 0){
-            if(this.selectedIndex == -1){
-                this.select(0);
-            }else if(this.selectedIndex !== 0){
-                this.select(this.selectedIndex-1);
-            }
-        }
+    
+    renderProp : function(v) {
+        return this.getPropertyName(v);
     },
 
     
-    onKeyUp : function(e){
-        var k = e.getKey();
-        if(this.editable !== false && this.readOnly !== true && (k == e.BACKSPACE || !e.isSpecialKey())){
+    
+    renderCell : function(val, meta, rec) {
+        var me = this,
+            renderer = me.grid.customRenderers[rec.get(me.grid.nameField)],
+            result = val;
 
-            this.lastKey = k;
-            this.dqTask.delay(this.queryDelay);
+        if (renderer) {
+            return renderer.apply(me, arguments);
+        }
+        if (Ext.isDate(val)) {
+            result = me.renderDate(val);
+        } else if (Ext.isBoolean(val)) {
+            result = me.renderBool(val);
         }
-        Ext.form.ComboBox.superclass.onKeyUp.call(this, e);
+        return Ext.util.Format.htmlEncode(result);
     },
 
     
-    validateBlur : function(){
-        return !this.list || !this.list.isVisible();
-    },
+    renderDate : Ext.util.Format.date,
 
     
-    initQuery : function(){
-        this.doQuery(this.getRawValue());
+    renderBool : function(bVal) {
+        return this[bVal ? 'trueText' : 'falseText'];
     },
 
     
-    beforeBlur : function(){
-        this.assertValue();
-    },
+    
+    getPropertyName : function(name) {
+        var pn = this.grid.propertyNames;
+        return pn && pn[name] ? pn[name] : name;
+    }
+});
+
+Ext.define('Ext.grid.property.Property', {
+    extend: 'Ext.data.Model',
+
+    alternateClassName: 'Ext.PropGridProperty',
+
+    fields: [{
+        name: 'name',
+        type: 'string'
+    }, {
+        name: 'value'
+    }],
+    idProperty: 'name'
+});
+
+Ext.define('Ext.grid.property.Store', {
+
+    extend: 'Ext.data.Store',
+
+    alternateClassName: 'Ext.grid.PropertyStore',
+
+    uses: ['Ext.data.reader.Reader', 'Ext.data.proxy.Proxy', 'Ext.data.ResultSet', 'Ext.grid.property.Property'],
 
     
-    postBlur  : function(){
-        Ext.form.ComboBox.superclass.postBlur.call(this);
-        this.collapse();
-        this.inKeyMode = false;
+    constructor : function(grid, source){
+        var me = this;
+        
+        me.grid = grid;
+        me.source = source;
+        me.callParent([{
+            data: source,
+            model: Ext.grid.property.Property,
+            proxy: me.getProxy()
+        }]);
     },
 
     
-    doQuery : function(q, forceAll){
-        q = Ext.isEmpty(q) ? '' : q;
-        var qe = {
-            query: q,
-            forceAll: forceAll,
-            combo: this,
-            cancel:false
-        };
-        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
-            return false;
+    getProxy: function() {
+        if (!this.proxy) {
+            Ext.grid.property.Store.prototype.proxy = Ext.create('Ext.data.proxy.Memory', {
+                model: Ext.grid.property.Property,
+                reader: this.getReader()
+            });
         }
-        q = qe.query;
-        forceAll = qe.forceAll;
-        if(forceAll === true || (q.length >= this.minChars)){
-            if(this.lastQuery !== q){
-                this.lastQuery = q;
-                if(this.mode == 'local'){
-                    this.selectedIndex = -1;
-                    if(forceAll){
-                        this.store.clearFilter();
-                    }else{
-                        this.store.filter(this.displayField, q);
+        return this.proxy;
+    },
+
+    
+    getReader: function() {
+        if (!this.reader) {
+            Ext.grid.property.Store.prototype.reader = Ext.create('Ext.data.reader.Reader', {
+                model: Ext.grid.property.Property,
+
+                buildExtractors: Ext.emptyFn,
+
+                read: function(dataObject) {
+                    return this.readRecords(dataObject);
+                },
+
+                readRecords: function(dataObject) {
+                    var val,
+                        propName,
+                        result = {
+                            records: [],
+                            success: true
+                        };
+
+                    for (propName in dataObject) {
+                        if (dataObject.hasOwnProperty(propName)) {
+                            val = dataObject[propName];
+                            if (this.isEditableValue(val)) {
+                                result.records.push(new Ext.grid.property.Property({
+                                    name: propName,
+                                    value: val
+                                }, propName));
+                            }
+                        }
                     }
-                    this.onLoad();
-                }else{
-                    this.store.baseParams[this.queryParam] = q;
-                    this.store.load({
-                        params: this.getParams(q)
-                    });
-                    this.expand();
+                    result.total = result.count = result.records.length;
+                    return Ext.create('Ext.data.ResultSet', result);
+                },
+
+                
+                isEditableValue: function(val){
+                    return Ext.isPrimitive(val) || Ext.isDate(val);
                 }
-            }else{
-                this.selectedIndex = -1;
-                this.onLoad();
-            }
+            });
         }
+        return this.reader;
     },
 
     
-    getParams : function(q){
-        var p = {};
-        
-        if(this.pageSize){
-            p.start = 0;
-            p.limit = this.pageSize;
-        }
-        return p;
+    setSource : function(dataObject) {
+        var me = this;
+
+        me.source = dataObject;
+        me.suspendEvents();
+        me.removeAll();
+        me.proxy.data = dataObject;
+        me.load();
+        me.resumeEvents();
+        me.fireEvent('datachanged', me);
     },
 
     
-    collapse : function(){
-        if(!this.isExpanded()){
-            return;
-        }
-        this.list.hide();
-        Ext.getDoc().un('mousewheel', this.collapseIf, this);
-        Ext.getDoc().un('mousedown', this.collapseIf, this);
-        this.fireEvent('collapse', this);
+    getProperty : function(row) {
+       return Ext.isNumber(row) ? this.getAt(row) : this.getById(row);
     },
 
     
-    collapseIf : function(e){
-        if(!this.isDestroyed && !e.within(this.wrap) && !e.within(this.list)){
-            this.collapse();
+    setValue : function(prop, value, create){
+        var me = this,
+            rec = me.getRec(prop);
+            
+        if (rec) {
+            rec.set('value', value);
+            me.source[prop] = value;
+        } else if (create) {
+            
+            me.source[prop] = value;
+            rec = new Ext.grid.property.Property({name: prop, value: value}, prop);
+            me.add(rec);
         }
     },
 
     
-    expand : function(){
-        if(this.isExpanded() || !this.hasFocus){
-            return;
+    remove : function(prop) {
+        var rec = this.getRec(prop);
+        if (rec) {
+            this.callParent([rec]);
+            delete this.source[prop];
         }
+    },
 
-        if(this.title || this.pageSize){
-            this.assetHeight = 0;
-            if(this.title){
-                this.assetHeight += this.header.getHeight();
-            }
-            if(this.pageSize){
-                this.assetHeight += this.footer.getHeight();
-            }
-        }
+    
+    getRec : function(prop) {
+        return this.getById(prop);
+    },
 
-        if(this.bufferSize){
-            this.doResize(this.bufferSize);
-            delete this.bufferSize;
-        }
-        this.list.alignTo.apply(this.list, [this.el].concat(this.listAlign));
+    
+    getSource : function() {
+        return this.source;
+    }
+});
+
+
+Ext.define('Ext.layout.component.Body', {
+
+    
+
+    alias: ['layout.body'],
+
+    extend: 'Ext.layout.component.Component',
+
+    uses: ['Ext.layout.container.Container'],
+
+    
+
+    type: 'body',
+    
+    onLayout: function(width, height) {
+        var me = this,
+            owner = me.owner;
+
+        
+        me.setTargetSize(width, height);
+
+        
+        me.setBodySize.apply(me, arguments);
 
         
-        this.list.setZIndex(this.getZIndex());
-        this.list.show();
-        if(Ext.isGecko2){
-            this.innerList.setOverflow('auto'); 
+        if (owner && owner.layout && owner.layout.isLayout) {
+            if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
+                owner.layout.bindToOwnerCtComponent = true;
+            }
+            else {
+                owner.layout.bindToOwnerCtComponent = false;
+            }
         }
-        this.mon(Ext.getDoc(), {
-            scope: this,
-            mousewheel: this.collapseIf,
-            mousedown: this.collapseIf
-        });
-        this.fireEvent('expand', this);
+        
+        me.callParent(arguments);
     },
 
     
-    
-    
-    onTriggerClick : function(){
-        if(this.readOnly || this.disabled){
-            return;
+    setBodySize: function(width, height) {
+        var me = this,
+            owner = me.owner,
+            frameSize = owner.frameSize,
+            isNumber = Ext.isNumber;
+
+        if (isNumber(width)) {
+            width -= owner.el.getFrameWidth('lr') - frameSize.left - frameSize.right;
         }
-        if(this.isExpanded()){
-            this.collapse();
-            this.el.focus();
-        }else {
-            this.onFocus({});
-            if(this.triggerAction == 'all') {
-                this.doQuery(this.allQuery, true);
-            } else {
-                this.doQuery(this.getRawValue());
-            }
-            this.el.focus();
+        if (isNumber(height)) {
+            height -= owner.el.getFrameWidth('tb') - frameSize.top - frameSize.bottom;
         }
+
+        me.setElementSize(owner.body, width, height);
     }
+});
 
-    
-    
-    
-    
+Ext.define('Ext.layout.component.FieldSet', {
+    extend: 'Ext.layout.component.Body',
+    alias: ['layout.fieldset'],
 
+    type: 'fieldset',
+
+    doContainerLayout: function() {
+        
+        if (!this.owner.collapsed) {
+            this.callParent();
+        }
+    }
 });
-Ext.reg('combo', Ext.form.ComboBox);
 
-Ext.form.Checkbox = Ext.extend(Ext.form.Field,  {
-    
-    focusClass : undefined,
-    
-    fieldClass : 'x-form-field',
-    
-    checked : false,
-    
-    boxLabel: '&#160;',
-    
-    defaultAutoCreate : { tag: 'input', type: 'checkbox', autocomplete: 'off'},
-    
-    
-    
-    
+Ext.define('Ext.layout.component.Tab', {
 
-    
-    actionMode : 'wrap',
+    alias: ['layout.tab'],
 
-       
-    initComponent : function(){
-        Ext.form.Checkbox.superclass.initComponent.call(this);
-        this.addEvents(
-            
-            'check'
-        );
-    },
+    extend: 'Ext.layout.component.Button',
 
     
-    onResize : function(){
-        Ext.form.Checkbox.superclass.onResize.apply(this, arguments);
-        if(!this.boxLabel && !this.fieldLabel){
-            this.el.alignTo(this.wrap, 'c-c');
+
+    beforeLayout: function() {
+        var me = this, dirty = me.lastClosable !== me.owner.closable;
+
+        if (dirty) {
+            delete me.adjWidth;
         }
-    },
 
-    
-    initEvents : function(){
-        Ext.form.Checkbox.superclass.initEvents.call(this);
-        this.mon(this.el, {
-            scope: this,
-            click: this.onClick,
-            change: this.onClick
-        });
+        return this.callParent(arguments) || dirty;
     },
 
+    onLayout: function () {
+        var me = this;
+
+        me.callParent(arguments);
+
+        me.lastClosable = me.owner.closable;
+    }
+});
+
+
+Ext.define('Ext.layout.component.field.File', {
+    alias: ['layout.filefield'],
+    extend: 'Ext.layout.component.field.Field',
+
+    type: 'filefield',
+
+    sizeBodyContents: function(width, height) {
+        var me = this,
+            owner = me.owner;
+
+        if (!owner.buttonOnly) {
+            
+            
+            me.setElementSize(owner.inputEl, Ext.isNumber(width) ? width - owner.button.getWidth() - owner.buttonMargin : width);
+        }
+    }
+});
+
+
+Ext.define('Ext.layout.component.field.Slider', {
+
     
-    markInvalid : Ext.emptyFn,
-    
-    clearInvalid : Ext.emptyFn,
+
+    alias: ['layout.sliderfield'],
+
+    extend: 'Ext.layout.component.field.Field',
 
     
-    onRender : function(ct, position){
-        Ext.form.Checkbox.superclass.onRender.call(this, ct, position);
-        if(this.inputValue !== undefined){
-            this.el.dom.value = this.inputValue;
-        }
-        this.wrap = this.el.wrap({cls: 'x-form-check-wrap'});
-        if(this.boxLabel){
-            this.wrap.createChild({tag: 'label', htmlFor: this.el.id, cls: 'x-form-cb-label', html: this.boxLabel});
-        }
-        if(this.checked){
-            this.setValue(true);
-        }else{
-            this.checked = this.el.dom.checked;
+
+    type: 'sliderfield',
+
+    sizeBodyContents: function(width, height) {
+        var owner = this.owner,
+            thumbs = owner.thumbs,
+            length = thumbs.length,
+            inputEl = owner.inputEl,
+            innerEl = owner.innerEl,
+            endEl = owner.endEl,
+            i = 0;
+
+        
+        for(; i < length; ++i) {
+            thumbs[i].el.stopAnimation();
         }
         
-        if (Ext.isIE && !Ext.isStrict) {
-            this.wrap.repaint();
+        if (owner.vertical) {
+            inputEl.setHeight(height);
+            innerEl.setHeight(Ext.isNumber(height) ? height - inputEl.getPadding('t') - endEl.getPadding('b') : height);
         }
-        this.resizeEl = this.positionEl = this.wrap;
-    },
+        else {
+            inputEl.setWidth(width);
+            innerEl.setWidth(Ext.isNumber(width) ? width - inputEl.getPadding('l') - endEl.getPadding('r') : width);
+        }
+        owner.syncThumbs();
+    }
+});
 
-    
-    onDestroy : function(){
-        Ext.destroy(this.wrap);
-        Ext.form.Checkbox.superclass.onDestroy.call(this);
-    },
+
+Ext.define('Ext.layout.container.Absolute', {
 
     
-    initValue : function() {
-        this.originalValue = this.getValue();
-    },
+
+    alias: 'layout.absolute',
+    extend: 'Ext.layout.container.Anchor',
+    alternateClassName: 'Ext.layout.AbsoluteLayout',
 
     
-    getValue : function(){
-        if(this.rendered){
-            return this.el.dom.checked;
+
+    itemCls: Ext.baseCSSPrefix + 'abs-layout-item',
+
+    type: 'absolute',
+
+    onLayout: function() {
+        var me = this,
+            target = me.getTarget(),
+            targetIsBody = target.dom === document.body;
+
+        
+        if (!targetIsBody) {
+            target.position();
         }
-        return this.checked;
+        me.paddingLeft = target.getPadding('l');
+        me.paddingTop = target.getPadding('t');
+        me.callParent(arguments);
     },
 
-       
-    onClick : function(){
-        if(this.el.dom.checked != this.checked){
-            this.setValue(this.el.dom.checked);
-        }
+    
+    adjustWidthAnchor: function(value, comp) {
+        
+        return value ? value - comp.getPosition(true)[0] : value;
     },
 
     
-    setValue : function(v){
-        var checked = this.checked ;
-        this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');
-        if(this.rendered){
-            this.el.dom.checked = this.checked;
-            this.el.dom.defaultChecked = this.checked;
-        }
-        if(checked != this.checked){
-            this.fireEvent('check', this, this.checked);
-            if(this.handler){
-                this.handler.call(this.scope || this, this, this.checked);
-            }
-        }
-        return this;
+    adjustHeightAnchor: function(value, comp) {
+        
+        return value ? value - comp.getPosition(true)[1] : value;
     }
 });
-Ext.reg('checkbox', Ext.form.Checkbox);
 
-Ext.form.CheckboxGroup = Ext.extend(Ext.form.Field, {
-    
-    
-    columns : 'auto',
-    
-    vertical : false,
+Ext.define('Ext.layout.container.Accordion', {
+    extend: 'Ext.layout.container.VBox',
+    alias: ['layout.accordion'],
+    alternateClassName: 'Ext.layout.AccordionLayout',
+
+    itemCls: Ext.baseCSSPrefix + 'box-item ' + Ext.baseCSSPrefix + 'accordion-item',
+
+    align: 'stretch',
+
     
-    allowBlank : true,
+    fill : true,
+
     
-    blankText : "You must select at least one item in this group",
+    autoWidth : true,
 
     
-    defaultType : 'checkbox',
+    titleCollapse : true,
 
     
-    groupCls : 'x-form-check-group',
+    hideCollapseTool : false,
 
     
-    initComponent: function(){
-        this.addEvents(
-            
-            'change'
-        );
-        this.on('change', this.validate, this);
-        Ext.form.CheckboxGroup.superclass.initComponent.call(this);
-    },
+    collapseFirst : false,
 
     
-    onRender : function(ct, position){
-        if(!this.el){
-            var panelCfg = {
-                autoEl: {
-                    id: this.id
-                },
-                cls: this.groupCls,
-                layout: 'column',
-                renderTo: ct,
-                bufferResize: false 
-            };
-            var colCfg = {
-                xtype: 'container',
-                defaultType: this.defaultType,
-                layout: 'form',
-                defaults: {
-                    hideLabel: true,
-                    anchor: '100%'
-                }
-            };
+    animate : true,
+    
+    activeOnTop : false,
+    
+    multi: false,
 
-            if(this.items[0].items){
+    constructor: function() {
+        var me = this;
 
-                
+        me.callParent(arguments);
 
-                Ext.apply(panelCfg, {
-                    layoutConfig: {columns: this.items.length},
-                    defaults: this.defaults,
-                    items: this.items
-                });
-                for(var i=0, len=this.items.length; i<len; i++){
-                    Ext.applyIf(this.items[i], colCfg);
-                }
+        
+        me.initialAnimate = me.animate;
+        me.animate = false;
 
-            }else{
+        
+        if (me.fill === false) {
+            me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
+        }
+    },
 
-                
-                
+    
+    
+    beforeLayout: function() {
+        var me = this;
+
+        me.callParent(arguments);
+        if (me.fill) {
+            if (!(me.owner.el.dom.style.height || me.getLayoutTargetSize().height)) {
+                return false;
+            }
+        } else {
+            me.owner.componentLayout.monitorChildren = false;
+            me.autoSize = true;
+            me.owner.setAutoScroll(true);
+        }
+    },
 
-                var numCols, cols = [];
+    renderItems : function(items, target) {
+        var me = this,
+            ln = items.length,
+            i = 0,
+            comp,
+            targetSize = me.getLayoutTargetSize(),
+            renderedPanels = [];
 
-                if(typeof this.columns == 'string'){ 
-                    this.columns = this.items.length;
+        for (; i < ln; i++) {
+            comp = items[i];
+            if (!comp.rendered) {
+                renderedPanels.push(comp);
+
+                
+                if (me.collapseFirst) {
+                    comp.collapseFirst = me.collapseFirst;
                 }
-                if(!Ext.isArray(this.columns)){
-                    var cs = [];
-                    for(var i=0; i<this.columns; i++){
-                        cs.push((100/this.columns)*.01); 
-                    }
-                    this.columns = cs;
+                if (me.hideCollapseTool) {
+                    comp.hideCollapseTool = me.hideCollapseTool;
+                    comp.titleCollapse = true;
+                }
+                else if (me.titleCollapse) {
+                    comp.titleCollapse = me.titleCollapse;
                 }
 
-                numCols = this.columns.length;
+                delete comp.hideHeader;
+                comp.collapsible = true;
+                comp.title = comp.title || '&#160;';
 
                 
-                for(var i=0; i<numCols; i++){
-                    var cc = Ext.apply({items:[]}, colCfg);
-                    cc[this.columns[i] <= 1 ? 'columnWidth' : 'width'] = this.columns[i];
-                    if(this.defaults){
-                        cc.defaults = Ext.apply(cc.defaults || {}, this.defaults);
-                    }
-                    cols.push(cc);
-                };
+                comp.width = targetSize.width;
+                if (me.fill) {
+                    delete comp.height;
+                    delete comp.flex;
 
-                
-                if(this.vertical){
-                    var rows = Math.ceil(this.items.length / numCols), ri = 0;
-                    for(var i=0, len=this.items.length; i<len; i++){
-                        if(i>0 && i%rows==0){
-                            ri++;
-                        }
-                        if(this.items[i].fieldLabel){
-                            this.items[i].hideLabel = false;
-                        }
-                        cols[ri].items.push(this.items[i]);
-                    };
-                }else{
-                    for(var i=0, len=this.items.length; i<len; i++){
-                        var ci = i % numCols;
-                        if(this.items[i].fieldLabel){
-                            this.items[i].hideLabel = false;
-                        }
-                        cols[ci].items.push(this.items[i]);
-                    };
+                    
+                    if (me.expandedItem !== undefined) {
+                        comp.collapsed = true;
+                    }
+                    
+                    else if (comp.hasOwnProperty('collapsed') && comp.collapsed === false) {
+                        comp.flex = 1;
+                        me.expandedItem = i;
+                    } else {
+                        comp.collapsed = true;
+                    }
+                    
+                    me.owner.mon(comp, {
+                        show: me.onComponentShow,
+                        beforeexpand: me.onComponentExpand,
+                        beforecollapse: me.onComponentCollapse,
+                        scope: me
+                    });
+                } else {
+                    delete comp.flex;
+                    comp.animCollapse = me.initialAnimate;
+                    comp.autoHeight = true;
+                    comp.autoScroll = false;
                 }
+                comp.border = comp.collapsed;
+            }
+        }
 
-                Ext.apply(panelCfg, {
-                    layoutConfig: {columns: numCols},
-                    items: cols
-                });
+        
+        if (ln && me.expandedItem === undefined) {
+            me.expandedItem = 0;
+            comp = items[0];
+            comp.collapsed = comp.border = false;
+            if (me.fill) {
+                comp.flex = 1;
             }
+        }
 
-            this.panel = new Ext.Container(panelCfg);
-            this.panel.ownerCt = this;
-            this.el = this.panel.getEl();
+        
+        me.callParent(arguments);
 
-            if(this.forId && this.itemCls){
-                var l = this.el.up(this.itemCls).child('label', true);
-                if(l){
-                    l.setAttribute('htmlFor', this.forId);
-                }
-            }
+        
+        ln = renderedPanels.length;
+        for (i = 0; i < ln; i++) {
+            comp = renderedPanels[i];
 
-            var fields = this.panel.findBy(function(c){
-                return c.isFormField;
-            }, this);
+            
+            delete comp.width;
 
-            this.items = new Ext.util.MixedCollection();
-            this.items.addAll(fields);
+            comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
+            comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
         }
-        Ext.form.CheckboxGroup.superclass.onRender.call(this, ct, position);
     },
 
-    initValue : function(){
-        if(this.value){
-            this.setValue.apply(this, this.buffered ? this.value : [this.value]);
-            delete this.buffered;
-            delete this.value;
+    onLayout: function() {
+        var me = this;
+
+
+        if (me.fill) {
+            me.callParent(arguments);
+        } else {
+            var targetSize = me.getLayoutTargetSize(),
+                items = me.getVisibleItems(),
+                len = items.length,
+                i = 0, comp;
+
+            for (; i < len; i++) {
+                comp = items[i];
+                if (comp.collapsed) {
+                    items[i].setWidth(targetSize.width);
+                } else {
+                    items[i].setSize(null, null);
+                }
+            }
         }
-    },
+        me.updatePanelClasses();
 
-    afterRender : function(){
-        Ext.form.CheckboxGroup.superclass.afterRender.call(this);
-        this.eachItem(function(item){
-            item.on('check', this.fireChecked, this);
-            item.inGroup = true;
-        });
+        return me;
     },
 
-    
-    doLayout: function(){
-        
-        if(this.rendered){
-            this.panel.forceLayout = this.ownerCt.forceLayout;
-            this.panel.doLayout();
+    updatePanelClasses: function() {
+        var children = this.getLayoutItems(),
+            ln = children.length,
+            siblingCollapsed = true,
+            i, child;
+
+        for (i = 0; i < ln; i++) {
+            child = children[i];
+
+            
+            
+            if (Ext.isWindows) {
+                child.el.dom.scrollTop = 0;
+            }
+
+            if (siblingCollapsed) {
+                child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
+            }
+            else {
+                child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
+            }
+
+            if (i + 1 == ln && child.collapsed) {
+                child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
+            }
+            else {
+                child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
+            }
+            siblingCollapsed = child.collapsed;
         }
     },
-
     
-    fireChecked: function(){
-        var arr = [];
-        this.eachItem(function(item){
-            if(item.checked){
-                arr.push(item);
-            }
+    animCallback: function(){
+        Ext.Array.forEach(this.toCollapse, function(comp){
+            comp.fireEvent('collapse', comp);
         });
-        this.fireEvent('change', this, arr);
+        
+        Ext.Array.forEach(this.toExpand, function(comp){
+            comp.fireEvent('expand', comp);
+        });    
     },
     
+    setupEvents: function(){
+        this.toCollapse = [];
+        this.toExpand = [];    
+    },
+
     
-    getErrors: function() {
-        var errors = Ext.form.CheckboxGroup.superclass.getErrors.apply(this, arguments);
+    
+    
+    onComponentExpand: function(toExpand) {
+        var me = this,
+            it = me.owner.items.items,
+            len = it.length,
+            i = 0,
+            comp;
+
+        me.setupEvents();
+        for (; i < len; i++) {
+            comp = it[i];
+            if (comp === toExpand && comp.collapsed) {
+                me.setExpanded(comp);
+            } else if (!me.multi && (comp.rendered && comp.header.rendered && comp !== toExpand && !comp.collapsed)) {
+                me.setCollapsed(comp);
+            }
+        }
+
+        me.animate = me.initialAnimate;
+        if (me.activeOnTop) {
+            
+            me.owner.insert(0, toExpand); 
+        } else {
+            me.layout();
+        }
+        me.animate = false;
+        return false;
+    },
+
+    onComponentCollapse: function(comp) {
+        var me = this,
+            toExpand = comp.next() || comp.prev(),
+            expanded = me.multi ? me.owner.query('>panel:not([collapsed])') : [];
+
+        me.setupEvents();
         
-        if (!this.allowBlank) {
-            var blank = true;
+        
+        if (me.multi) {
+            me.setCollapsed(comp);
+
             
-            this.eachItem(function(f){
-                if (f.checked) {
-                    return (blank = false);
-                }
-            });
             
-            if (blank) errors.push(this.blankText);
+            if (expanded.length === 1 && expanded[0] === comp) {
+                me.setExpanded(toExpand);
+            }
+
+            me.animate = me.initialAnimate;
+            me.layout();
+            me.animate = false;
         }
         
-        return errors;
+        else if (toExpand) {
+            me.onComponentExpand(toExpand);
+        }
+        return false;
     },
 
-    
-    isDirty: function(){
+    onComponentShow: function(comp) {
         
-        if (this.disabled || !this.rendered) {
-            return false;
-        }
+        this.onComponentExpand(comp);
+    },
+
+    setCollapsed: function(comp) {
+        var otherDocks = comp.getDockedItems(),
+            dockItem,
+            len = otherDocks.length,
+            i = 0;
 
-        var dirty = false;
         
-        this.eachItem(function(item){
-            if(item.isDirty()){
-                dirty = true;
-                return false;
+        comp.hiddenDocked = [];
+        for (; i < len; i++) {
+            dockItem = otherDocks[i];
+            if ((dockItem !== comp.header) && !dockItem.hidden) {
+                dockItem.hidden = true;
+                comp.hiddenDocked.push(dockItem);
             }
-        });
-        
-        return dirty;
+        }
+        comp.addCls(comp.collapsedCls);
+        comp.header.addCls(comp.collapsedHeaderCls);
+        comp.height = comp.header.getHeight();
+        comp.el.setHeight(comp.height);
+        comp.collapsed = true;
+        delete comp.flex;
+        if (this.initialAnimate) {
+            this.toCollapse.push(comp);
+        } else {
+            comp.fireEvent('collapse', comp);
+        }
+        if (comp.collapseTool) {
+            comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
+        }
     },
 
-    
-    setReadOnly : function(readOnly){
-        if(this.rendered){
-            this.eachItem(function(item){
-                item.setReadOnly(readOnly);
-            });
+    setExpanded: function(comp) {
+        var otherDocks = comp.hiddenDocked,
+            len = otherDocks ? otherDocks.length : 0,
+            i = 0;
+
+        
+        for (; i < len; i++) {
+            otherDocks[i].show();
         }
-        this.readOnly = readOnly;
-    },
+
+        
+        if (!comp.body.isVisible()) {
+            comp.body.show();
+        }
+        delete comp.collapsed;
+        delete comp.height;
+        delete comp.componentLayout.lastComponentSize;
+        comp.suspendLayout = false;
+        comp.flex = 1;
+        comp.removeCls(comp.collapsedCls);
+        comp.header.removeCls(comp.collapsedHeaderCls);
+         if (this.initialAnimate) {
+            this.toExpand.push(comp);
+        } else {
+            comp.fireEvent('expand', comp);
+        }
+        if (comp.collapseTool) {
+            comp.collapseTool.setType('collapse-' + comp.collapseDirection);
+        }
+        comp.setAutoScroll(comp.initialConfig.autoScroll);
+    }
+});
+
+Ext.define('Ext.resizer.Splitter', {
+    extend: 'Ext.Component',
+    requires: ['Ext.XTemplate'],
+    uses: ['Ext.resizer.SplitterTracker'],
+    alias: 'widget.splitter',
+
+    renderTpl: [
+        '<tpl if="collapsible===true">',
+            '<div id="{id}-collapseEl" class="', Ext.baseCSSPrefix, 'collapse-el ',
+                    Ext.baseCSSPrefix, 'layout-split-{collapseDir}">&nbsp;</div>',
+        '</tpl>'
+    ],
+
+    baseCls: Ext.baseCSSPrefix + 'splitter',
+    collapsedClsInternal: Ext.baseCSSPrefix + 'splitter-collapsed',
 
     
-    onDisable : function(){
-        this.eachItem(function(item){
-            item.disable();
-        });
-    },
+    collapsible: false,
 
     
-    onEnable : function(){
-        this.eachItem(function(item){
-            item.enable();
-        });
-    },
 
     
-    onResize : function(w, h){
-        this.panel.setSize(w, h);
-        this.panel.doLayout();
-    },
+    collapseOnDblClick: true,
 
     
-    reset : function(){
-        if (this.originalValue) {
-            
-            this.eachItem(function(c){
-                if(c.setValue){
-                    c.setValue(false);
-                    c.originalValue = c.getValue();
-                }
-            });
-            
-            
-            this.resetOriginal = true;
-            this.setValue(this.originalValue);
-            delete this.resetOriginal;
-        } else {
-            this.eachItem(function(c){
-                if(c.reset){
-                    c.reset();
-                }
-            });
-        }
-        
-        
-        (function() {
-            this.clearInvalid();
-        }).defer(50, this);
-    },
+    defaultSplitMin: 40,
 
     
-    setValue: function(){
-        if(this.rendered){
-            this.onSetValue.apply(this, arguments);
-        }else{
-            this.buffered = true;
-            this.value = arguments;
-        }
-        return this;
-    },
+    defaultSplitMax: 1000,
 
     
-    onSetValue: function(id, value){
-        if(arguments.length == 1){
-            if(Ext.isArray(id)){
-                Ext.each(id, function(val, idx){
-                    if (Ext.isObject(val) && val.setValue){ 
-                        val.setValue(true);
-                        if (this.resetOriginal === true) {
-                            val.originalValue = val.getValue();
-                        }
-                    } else { 
-                        var item = this.items.itemAt(idx);
-                        if(item){
-                            item.setValue(val);
-                        }
-                    }
-                }, this);
-            }else if(Ext.isObject(id)){
-                
-                for(var i in id){
-                    var f = this.getBox(i);
-                    if(f){
-                        f.setValue(id[i]);
-                    }
-                }
-            }else{
-                this.setValueForItem(id);
+
+    width: 5,
+    height: 5,
+
+    
+    collapseTarget: 'next',
+
+    
+
+    onRender: function() {
+        var me = this,
+            target = me.getCollapseTarget(),
+            collapseDir = me.getCollapseDirection();
+
+        Ext.applyIf(me.renderData, {
+            collapseDir: collapseDir,
+            collapsible: me.collapsible || target.collapsible
+        });
+
+        me.addChildEls('collapseEl');
+
+        this.callParent(arguments);
+
+        
+        if (me.performCollapse !== false) {
+            if (me.renderData.collapsible) {
+                me.mon(me.collapseEl, 'click', me.toggleTargetCmp, me);
             }
-        }else{
-            var f = this.getBox(id);
-            if(f){
-                f.setValue(value);
+            if (me.collapseOnDblClick) {
+                me.mon(me.el, 'dblclick', me.toggleTargetCmp, me);
             }
         }
+
+        
+        me.mon(target, 'collapse', me.onTargetCollapse, me);
+        me.mon(target, 'expand', me.onTargetExpand, me);
+
+        me.el.addCls(me.baseCls + '-' + me.orientation);
+        me.el.unselectable();
+
+        me.tracker = Ext.create('Ext.resizer.SplitterTracker', {
+            el: me.el
+        });
+
+        
+        me.relayEvents(me.tracker, [ 'beforedragstart', 'dragstart', 'dragend' ]);
+    },
+
+    getCollapseDirection: function() {
+        var me = this,
+            idx,
+            type = me.ownerCt.layout.type;
+
+        
+        
+        
+        
+        
+        
+        
+        if (me.collapseTarget.isComponent) {
+            idx = Number(me.ownerCt.items.indexOf(me.collapseTarget) == me.ownerCt.items.indexOf(me) - 1) << 1 | Number(type == 'hbox');
+        } else {
+            idx = Number(me.collapseTarget == 'prev') << 1 | Number(type == 'hbox');
+        }
+
+        
+        me.orientation = ['horizontal', 'vertical'][idx & 1];
+        return ['bottom', 'right', 'top', 'left'][idx];
     },
 
-    
-    beforeDestroy: function(){
-        Ext.destroy(this.panel);
-        Ext.form.CheckboxGroup.superclass.beforeDestroy.call(this);
+    getCollapseTarget: function() {
+        var me = this;
 
+        return me.collapseTarget.isComponent ? me.collapseTarget : me.collapseTarget == 'prev' ? me.previousSibling() : me.nextSibling();
     },
 
-    setValueForItem : function(val){
-        val = String(val).split(',');
-        this.eachItem(function(item){
-            if(val.indexOf(item.inputValue)> -1){
-                item.setValue(true);
-            }
-        });
+    onTargetCollapse: function(target) {
+        this.el.addCls([this.collapsedClsInternal, this.collapsedCls]);
     },
 
-    
-    getBox : function(id){
-        var box = null;
-        this.eachItem(function(f){
-            if(id == f || f.dataIndex == id || f.id == id || f.getName() == id){
-                box = f;
-                return false;
-            }
-        });
-        return box;
+    onTargetExpand: function(target) {
+        this.el.removeCls([this.collapsedClsInternal, this.collapsedCls]);
     },
 
-    
-    getValue : function(){
-        var out = [];
-        this.eachItem(function(item){
-            if(item.checked){
-                out.push(item);
+    toggleTargetCmp: function(e, t) {
+        var cmp = this.getCollapseTarget();
+
+        if (cmp.isVisible()) {
+            
+            if (cmp.collapsed) {
+                cmp.expand(cmp.animCollapse);
+            
+            } else {
+                cmp.collapse(this.renderData.collapseDir, cmp.animCollapse);
             }
-        });
-        return out;
+        }
     },
 
     
-    eachItem: function(fn, scope) {
-        if(this.items && this.items.each){
-            this.items.each(fn, scope || this);
+    setSize: function() {
+        var me = this;
+        me.callParent(arguments);
+        if (Ext.isIE) {
+            me.el.repaint();
         }
-    },
+    }
+});
 
-    
 
-    
-    getRawValue : Ext.emptyFn,
+Ext.define('Ext.layout.container.Border', {
 
-    
-    setRawValue : Ext.emptyFn
+    alias: ['layout.border'],
+    extend: 'Ext.layout.container.Container',
+    requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
+    alternateClassName: 'Ext.layout.BorderLayout',
 
-});
+    targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
 
-Ext.reg('checkboxgroup', Ext.form.CheckboxGroup);
+    itemCls: Ext.baseCSSPrefix + 'border-item',
 
-Ext.form.CompositeField = Ext.extend(Ext.form.Field, {
+    bindToOwnerCtContainer: true,
 
-    
-    defaultMargins: '0 5 0 0',
+    percentageRe: /(\d+)%/,
 
-    
-    skipLastItemMargin: true,
+    slideDirection: {
+        north: 't',
+        south: 'b',
+        west: 'l',
+        east: 'r'
+    },
 
-    
-    isComposite: true,
+    constructor: function(config) {
+        this.initialConfig = config;
+        this.callParent(arguments);
+    },
 
-    
-    combineErrors: true,
-    
-    
-    labelConnector: ', ',
+    onLayout: function() {
+        var me = this;
+        if (!me.borderLayoutInitialized) {
+            me.initializeBorderLayout();
+        }
 
-    
-    
-    initComponent: function() {
-        var labels = [],
-            items  = this.items,
-            item;
+        
+        me.fixHeightConstraints();
+        me.shadowLayout.onLayout();
+        if (me.embeddedContainer) {
+            me.embeddedContainer.layout.onLayout();
+        }
 
-        for (var i=0, j = items.length; i < j; i++) {
-            item = items[i];
+        
+        
+        if (!me.initialCollapsedComplete) {
+            Ext.iterate(me.regions, function(name, region){
+                if (region.borderCollapse) {
+                    me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
+                }
+            });
+            me.initialCollapsedComplete = true;
+        }
+    },
 
-            labels.push(item.fieldLabel);
+    isValidParent : function(item, target, position) {
+        if (!this.borderLayoutInitialized) {
+            this.initializeBorderLayout();
+        }
 
-            
-            Ext.apply(item, this.defaults);
+        
+        return this.shadowLayout.isValidParent(item, target, position);
+    },
 
-            
-            if (!(i == j - 1 && this.skipLastItemMargin)) {
-                Ext.applyIf(item, {margins: this.defaultMargins});
-            }
+    beforeLayout: function() {
+        if (!this.borderLayoutInitialized) {
+            this.initializeBorderLayout();
         }
 
-        this.fieldLabel = this.fieldLabel || this.buildLabel(labels);
+        
+        this.shadowLayout.beforeLayout();
 
         
-        this.fieldErrors = new Ext.util.MixedCollection(true, function(item) {
-            return item.field;
-        });
+    },
 
-        this.fieldErrors.on({
-            scope  : this,
-            add    : this.updateInvalidMark,
-            remove : this.updateInvalidMark,
-            replace: this.updateInvalidMark
-        });
+    renderItems: function(items, target) {
+    },
+
+    renderItem: function(item) {
+    },
+
+    renderChildren: function() {
+        if (!this.borderLayoutInitialized) {
+            this.initializeBorderLayout();
+        }
 
-        Ext.form.CompositeField.superclass.initComponent.apply(this, arguments);
+        this.shadowLayout.renderChildren();
     },
 
     
-    onRender: function(ct, position) {
-        if (!this.el) {
-            
-            var innerCt = this.innerCt = new Ext.Container({
-                layout  : 'hbox',
-                renderTo: ct,
-                items   : this.items,
-                cls     : 'x-form-composite',
-                defaultMargins: '0 3 0 0'
-            });
+    getVisibleItems: function() {
+        return Ext.ComponentQuery.query(':not([slideOutAnim])', this.callParent(arguments));
+    },
 
-            this.el = innerCt.getEl();
+    initializeBorderLayout: function() {
+        var me = this,
+            i = 0,
+            items = me.getLayoutItems(),
+            ln = items.length,
+            regions = (me.regions = {}),
+            vBoxItems = [],
+            hBoxItems = [],
+            horizontalFlex = 0,
+            verticalFlex = 0,
+            comp, percentage;
 
-            var fields = innerCt.findBy(function(c) {
-                return c.isFormField;
-            }, this);
+        
+        me.splitters = {};
 
-            
-            this.items = new Ext.util.MixedCollection();
-            this.items.addAll(fields);
+        
+        for (; i < ln; i++) {
+            comp = items[i];
+            regions[comp.region] = comp;
 
             
-            
-            if (this.combineErrors) {
-                this.eachItem(function(field) {
-                    Ext.apply(field, {
-                        markInvalid : this.onFieldMarkInvalid.createDelegate(this, [field], 0),
-                        clearInvalid: this.onFieldClearInvalid.createDelegate(this, [field], 0)
-                    });
+            if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
+
+                
+                comp.borderCollapse = comp.collapsed;
+                comp.collapsed = false;
+
+                comp.on({
+                    beforecollapse: me.onBeforeRegionCollapse,
+                    beforeexpand: me.onBeforeRegionExpand,
+                    destroy: me.onRegionDestroy,
+                    scope: me
                 });
+                me.setupState(comp);
+            }
+        }
+        comp = regions.center;
+        if (!comp.flex) {
+            comp.flex = 1;
+        }
+        delete comp.width;
+        comp.maintainFlex = true;
+
+        
+        comp = regions.west;
+        if (comp) {
+            comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
+            hBoxItems.push(comp);
+            if (comp.split) {
+                hBoxItems.push(me.splitters.west = me.createSplitter(comp));
+            }
+            percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
+            if (percentage) {
+                horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
+                delete comp.width;
             }
+        }
+        comp = regions.north;
+        if (comp) {
+            comp.collapseDirection = Ext.Component.DIRECTION_TOP;
+            vBoxItems.push(comp);
+            if (comp.split) {
+                vBoxItems.push(me.splitters.north = me.createSplitter(comp));
+            }
+            percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
+            if (percentage) {
+                verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
+                delete comp.height;
+            }
+        }
 
+        
+        if (regions.north || regions.south) {
+            if (regions.east || regions.west) {
+
+                
+                vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
+                    xtype: 'container',
+                    region: 'center',
+                    id: me.owner.id + '-embedded-center',
+                    cls: Ext.baseCSSPrefix + 'border-item',
+                    flex: regions.center.flex,
+                    maintainFlex: true,
+                    layout: {
+                        type: 'hbox',
+                        align: 'stretch',
+                        getVisibleItems: me.getVisibleItems
+                    }
+                }));
+                hBoxItems.push(regions.center);
+            }
             
-            var l = this.el.parent().parent().child('label', true);
-            if (l) {
-                l.setAttribute('for', this.items.items[0].id);
+            else {
+                vBoxItems.push(regions.center);
             }
         }
+        
+        else {
+            hBoxItems.push(regions.center);
+        }
 
-        Ext.form.CompositeField.superclass.onRender.apply(this, arguments);
-    },
+        
+        comp = regions.south;
+        if (comp) {
+            comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
+            if (comp.split) {
+                vBoxItems.push(me.splitters.south = me.createSplitter(comp));
+            }
+            percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
+            if (percentage) {
+                verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
+                delete comp.height;
+            }
+            vBoxItems.push(comp);
+        }
+        comp = regions.east;
+        if (comp) {
+            comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
+            if (comp.split) {
+                hBoxItems.push(me.splitters.east = me.createSplitter(comp));
+            }
+            percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
+            if (percentage) {
+                horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
+                delete comp.width;
+            }
+            hBoxItems.push(comp);
+        }
 
-    
-    onFieldMarkInvalid: function(field, message) {
-        var name  = field.getName(),
-            error = {field: name, error: message};
+        
+        
+        
+        
+        if (regions.north || regions.south) {
 
-        this.fieldErrors.replace(name, error);
+            me.shadowContainer = Ext.create('Ext.container.Container', {
+                ownerCt: me.owner,
+                el: me.getTarget(),
+                layout: Ext.applyIf({
+                    type: 'vbox',
+                    align: 'stretch',
+                    getVisibleItems: me.getVisibleItems
+                }, me.initialConfig)
+            });
+            me.createItems(me.shadowContainer, vBoxItems);
 
-        field.el.addClass(field.invalidClass);
-    },
+            
+            if (me.splitters.north) {
+                me.splitters.north.ownerCt = me.shadowContainer;
+            }
+            if (me.splitters.south) {
+                me.splitters.south.ownerCt = me.shadowContainer;
+            }
 
-    
-    onFieldClearInvalid: function(field) {
-        this.fieldErrors.removeKey(field.getName());
+            
+            if (me.embeddedContainer) {
+                me.embeddedContainer.ownerCt = me.shadowContainer;
+                me.createItems(me.embeddedContainer, hBoxItems);
 
-        field.el.removeClass(field.invalidClass);
-    },
+                
+                if (me.splitters.east) {
+                    me.splitters.east.ownerCt = me.embeddedContainer;
+                }
+                if (me.splitters.west) {
+                    me.splitters.west.ownerCt = me.embeddedContainer;
+                }
 
-    
-    updateInvalidMark: function() {
-        var ieStrict = Ext.isIE6 && Ext.isStrict;
+                
+                
+                
+                
+                
+                Ext.each([me.splitters.north, me.splitters.south], function (splitter) {
+                    if (splitter) {
+                        splitter.on('beforedragstart', me.fixHeightConstraints, me);
+                    }
+                });
 
-        if (this.fieldErrors.length == 0) {
-            this.clearInvalid();
+                
+                if (horizontalFlex) {
+                    regions.center.flex -= horizontalFlex;
+                }
+                
+                if (verticalFlex) {
+                    me.embeddedContainer.flex -= verticalFlex;
+                }
+            } else {
+                
+                if (verticalFlex) {
+                    regions.center.flex -= verticalFlex;
+                }
+            }
+        }
+        
+        
+        else {
+            me.shadowContainer = Ext.create('Ext.container.Container', {
+                ownerCt: me.owner,
+                el: me.getTarget(),
+                layout: Ext.applyIf({
+                    type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
+                    align: 'stretch'
+                }, me.initialConfig)
+            });
+            me.createItems(me.shadowContainer, hBoxItems);
 
             
-            if (ieStrict) {
-                this.clearInvalid.defer(50, this);
+            if (me.splitters.east) {
+                me.splitters.east.ownerCt = me.shadowContainer;
+            }
+            if (me.splitters.west) {
+                me.splitters.west.ownerCt = me.shadowContainer;
             }
-        } else {
-            var message = this.buildCombinedErrorMessage(this.fieldErrors.items);
-
-            this.sortErrors();
-            this.markInvalid(message);
 
             
-            if (ieStrict) {
-                this.markInvalid(message);
+            if (horizontalFlex) {
+                regions.center.flex -= verticalFlex;
             }
         }
-    },
 
-    
-    validateValue: function() {
-        var valid = true;
+        
+        for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
+            items[i].shadowOwnerCt = me.shadowContainer;
+        }
+        if (me.embeddedContainer) {
+            for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
+                items[i].shadowOwnerCt = me.embeddedContainer;
+            }
+        }
 
-        this.eachItem(function(field) {
-            if (!field.isValid()) valid = false;
-        });
+        
+        me.shadowLayout = me.shadowContainer.getLayout();
 
-        return valid;
+        me.borderLayoutInitialized = true;
     },
 
-    
-    buildCombinedErrorMessage: function(errors) {
-        var combined = [],
-            error;
-
-        for (var i = 0, j = errors.length; i < j; i++) {
-            error = errors[i];
-
-            combined.push(String.format("{0}: {1}", error.field, error.error));
-        }
+    setupState: function(comp){
+        var getState = comp.getState;
+        comp.getState = function(){
+            
+            var state = getState.call(comp) || {},
+                region = comp.region;
 
-        return combined.join("<br />");
+            state.collapsed = !!comp.collapsed;
+            if (region == 'west' || region == 'east') {
+                state.width = comp.getWidth();
+            } else {
+                state.height = comp.getHeight();
+            }
+            return state;
+        };
+        comp.addStateEvents(['collapse', 'expand', 'resize']);
     },
 
     
-    sortErrors: function() {
-        var fields = this.items;
-
-        this.fieldErrors.sort("ASC", function(a, b) {
-            var findByName = function(key) {
-                return function(field) {
-                    return field.getName() == key;
-                };
-            };
-
-            var aIndex = fields.findIndexBy(findByName(a.field)),
-                bIndex = fields.findIndexBy(findByName(b.field));
-
-            return aIndex < bIndex ? -1 : 1;
-        });
+    createItems: function(container, items){
+        
+        
+        delete container.items;
+        container.initItems();
+        container.items.addAll(items);
     },
 
     
-    reset: function() {
-        this.eachItem(function(item) {
-            item.reset();
+    
+    createSplitter: function(comp) {
+        var me = this,
+            interceptCollapse = (comp.collapseMode != 'header'),
+            resizer;
+
+        resizer = Ext.create('Ext.resizer.Splitter', {
+            hidden: !!comp.hidden,
+            collapseTarget: comp,
+            performCollapse: !interceptCollapse,
+            listeners: interceptCollapse ? {
+                click: {
+                    fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
+                    element: 'collapseEl'
+                }
+            } : null
         });
 
         
+        if (comp.collapseMode == 'mini') {
+            comp.placeholder = resizer;
+            resizer.collapsedCls = comp.collapsedCls;
+        }
+
         
-        (function() {
-            this.clearInvalid();
-        }).defer(50, this);
-    },
-    
-    
-    clearInvalidChildren: function() {
-        this.eachItem(function(item) {
-            item.clearInvalid();
+        comp.on({
+            hide: me.onRegionVisibilityChange,
+            show: me.onRegionVisibilityChange,
+            scope: me
         });
+        return resizer;
     },
 
     
-    buildLabel: function(segments) {
-        return Ext.clean(segments).join(this.labelConnector);
-    },
-
     
-    isDirty: function(){
-        
-        if (this.disabled || !this.rendered) {
-            return false;
+    fixHeightConstraints: function () {
+        var me = this,
+            ct = me.embeddedContainer,
+            maxHeight = 1e99, minHeight = -1;
+
+        if (!ct) {
+            return;
         }
 
-        var dirty = false;
-        this.eachItem(function(item){
-            if(item.isDirty()){
-                dirty = true;
-                return false;
+        ct.items.each(function (item) {
+            if (Ext.isNumber(item.maxHeight)) {
+                maxHeight = Math.max(maxHeight, item.maxHeight);
+            }
+            if (Ext.isNumber(item.minHeight)) {
+                minHeight = Math.max(minHeight, item.minHeight);
             }
         });
-        return dirty;
+
+        ct.maxHeight = maxHeight;
+        ct.minHeight = minHeight;
     },
 
     
-    eachItem: function(fn, scope) {
-        if(this.items && this.items.each){
-            this.items.each(fn, scope || this);
-        }
+    onRegionVisibilityChange: function(comp){
+        this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
+        this.layout();
     },
 
     
-    onResize: function(adjWidth, adjHeight, rawWidth, rawHeight) {
-        var innerCt = this.innerCt;
-
-        if (this.rendered && innerCt.rendered) {
-            innerCt.setSize(adjWidth, adjHeight);
+    
+    
+    onSplitterCollapseClick: function(comp) {
+        if (comp.collapsed) {
+            this.onPlaceHolderToolClick(null, null, null, {client: comp});
+        } else {
+            comp.collapse();
         }
-
-        Ext.form.CompositeField.superclass.onResize.apply(this, arguments);
     },
 
     
-    doLayout: function(shallow, force) {
-        if (this.rendered) {
-            var innerCt = this.innerCt;
+    getPlaceholder: function(comp) {
+        var me = this,
+            placeholder = comp.placeholder,
+            shadowContainer = comp.shadowOwnerCt,
+            shadowLayout = shadowContainer.layout,
+            oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
+            horiz = (comp.region == 'north' || comp.region == 'south');
 
-            innerCt.forceLayout = this.ownerCt.forceLayout;
-            innerCt.doLayout(shallow, force);
+        
+        if (comp.collapseMode == 'header') {
+            return;
         }
-    },
 
-    
-    beforeDestroy: function(){
-        Ext.destroy(this.innerCt);
+        
+        if (!placeholder) {
+            if (comp.collapseMode == 'mini') {
+                placeholder = Ext.create('Ext.resizer.Splitter', {
+                    id: 'collapse-placeholder-' + comp.id,
+                    collapseTarget: comp,
+                    performCollapse: false,
+                    listeners: {
+                        click: {
+                            fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
+                            element: 'collapseEl'
+                        }
+                    }
+                });
+                placeholder.addCls(placeholder.collapsedCls);
+            } else {
+                placeholder = {
+                    id: 'collapse-placeholder-' + comp.id,
+                    margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
+                    xtype: 'header',
+                    orientation: horiz ? 'horizontal' : 'vertical',
+                    title: comp.title,
+                    textCls: comp.headerTextCls,
+                    iconCls: comp.iconCls,
+                    baseCls: comp.baseCls + '-header',
+                    ui: comp.ui,
+                    indicateDrag: comp.draggable,
+                    cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder ' + comp.collapsedCls,
+                    listeners: comp.floatable ? {
+                        click: {
+                            fn: function(e) {
+                                me.floatCollapsedPanel(e, comp);
+                            },
+                            element: 'el'
+                        }
+                    } : null
+                };
+                
+                if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
+                    placeholder.width = 25;
+                }
+                if (!comp.hideCollapseTool) {
+                    placeholder[horiz ? 'tools' : 'items'] = [{
+                        xtype: 'tool',
+                        client: comp,
+                        type: 'expand-' + oppositeDirection,
+                        handler: me.onPlaceHolderToolClick,
+                        scope: me
+                    }];
+                }
+            }
+            placeholder = me.owner.createComponent(placeholder);
+            if (comp.isXType('panel')) {
+                comp.on({
+                    titlechange: me.onRegionTitleChange,
+                    iconchange: me.onRegionIconChange,
+                    scope: me
+                });
+            }
+        }
+
+        
+        comp.placeholder = placeholder;
+        placeholder.comp = comp;
 
-        Ext.form.CompositeField.superclass.beforeDestroy.call(this);
+        return placeholder;
     },
 
     
-    setReadOnly : function(readOnly) {
-        readOnly = readOnly || true;
-
-        if(this.rendered){
-            this.eachItem(function(item){
-                item.setReadOnly(readOnly);
-            });
-        }
-        this.readOnly = readOnly;
+    onRegionTitleChange: function(comp, newTitle) {
+        comp.placeholder.setTitle(newTitle);
     },
 
-    onShow : function() {
-        Ext.form.CompositeField.superclass.onShow.call(this);
-        this.doLayout();
+    
+    onRegionIconChange: function(comp, newIconCls) {
+        comp.placeholder.setIconCls(newIconCls);
     },
 
     
-    onDisable : function(){
-        this.eachItem(function(item){
-            item.disable();
-        });
+    calculateChildBox: function(comp) {
+        var me = this;
+        if (me.shadowContainer.items.contains(comp)) {
+            return me.shadowContainer.layout.calculateChildBox(comp);
+        }
+        else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
+            return me.embeddedContainer.layout.calculateChildBox(comp);
+        }
     },
 
     
-    onEnable : function(){
-        this.eachItem(function(item){
-            item.enable();
-        });
-    }
-});
+    onBeforeRegionCollapse: function(comp, direction, animate) {
+        if (comp.collapsedChangingLayout) {
+            return false;
+        }
+        comp.collapsedChangingLayout = true;
+        var me = this,
+            compEl = comp.el,
+            width,
+            miniCollapse = comp.collapseMode == 'mini',
+            shadowContainer = comp.shadowOwnerCt,
+            shadowLayout = shadowContainer.layout,
+            placeholder = comp.placeholder,
+            sl = me.owner.suspendLayout,
+            scsl = shadowContainer.suspendLayout,
+            isNorthOrWest = (comp.region == 'north' || comp.region == 'west'); 
 
-Ext.reg('compositefield', Ext.form.CompositeField);
+        
+        me.owner.suspendLayout = true;
+        shadowContainer.suspendLayout = true;
 
-Ext.form.Radio = Ext.extend(Ext.form.Checkbox, {
-    inputType: 'radio',
+        
+        shadowLayout.layoutBusy = true;
+        if (shadowContainer.componentLayout) {
+            shadowContainer.componentLayout.layoutBusy = true;
+        }
+        me.shadowContainer.layout.layoutBusy = true;
+        me.layoutBusy = true;
+        me.owner.componentLayout.layoutBusy = true;
 
-    
-    markInvalid : Ext.emptyFn,
-    
-    clearInvalid : Ext.emptyFn,
+        
+        if (!placeholder) {
+            placeholder = me.getPlaceholder(comp);
+        }
 
-    
-    getGroupValue : function(){
-       var p = this.el.up('form') || Ext.getBody();
-        var c = p.child('input[name='+this.el.dom.name+']:checked', true);
-        return c ? c.value : null;
-    },
+        
+        if (placeholder.shadowOwnerCt === shadowContainer) {
+            placeholder.show();
+        }
+        
+        
+        
+        else {
+            shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
+            placeholder.shadowOwnerCt = shadowContainer;
+            placeholder.ownerCt = me.owner;
+        }
 
-    
-    onClick : function(){
-       if(this.el.dom.checked != this.checked){
-                       var els = this.getCheckEl().select('input[name=' + this.el.dom.name + ']');
-                       els.each(function(el){
-                               if(el.dom.id == this.id){
-                                       this.setValue(true);
-                               }else{
-                                       Ext.getCmp(el.dom.id).setValue(false);
-                               }
-                       }, this);
-               }
-    },
+        
+        
+        
+        comp.hidden = true;
 
-    
-    setValue : function(v){
-       if (typeof v == 'boolean') {
-            Ext.form.Radio.superclass.setValue.call(this, v);
-        } else if (this.rendered) {
-            var r = this.getCheckEl().child('input[name=' + this.el.dom.name + '][value=' + v + ']', true);
-            if(r){
-                Ext.getCmp(r.id).setValue(true);
+        if (!placeholder.rendered) {
+            shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
+
+            
+            
+            
+            
+            
+            if (comp.region == 'north' || comp.region == 'south') {
+                placeholder.setCalculatedSize(comp.getWidth());
+            } else {
+                placeholder.setCalculatedSize(undefined, comp.getHeight());
             }
         }
-        return this;
-    },
 
-    
-    getCheckEl: function(){
-        if(this.inGroup){
-            return this.el.up('.x-form-radio-group')
+        
+        function afterCollapse() {
+            
+            me.owner.suspendLayout = sl;
+            shadowContainer.suspendLayout = scsl;
+            delete shadowLayout.layoutBusy;
+            if (shadowContainer.componentLayout) {
+                delete shadowContainer.componentLayout.layoutBusy;
+            }
+            delete me.shadowContainer.layout.layoutBusy;
+            delete me.layoutBusy;
+            delete me.owner.componentLayout.layoutBusy;
+            delete comp.collapsedChangingLayout;
+
+            
+            comp.collapsed = true;
+            comp.fireEvent('collapse', comp);
         }
-        return this.el.up('form') || Ext.getBody();
-    }
-});
-Ext.reg('radio', Ext.form.Radio);
 
-Ext.form.RadioGroup = Ext.extend(Ext.form.CheckboxGroup, {
-    
-    
-    allowBlank : true,
-    
-    blankText : 'You must select one item in this group',
-    
-    
-    defaultType : 'radio',
-    
-    
-    groupCls : 'x-form-radio-group',
-    
-    
-    
-    
-    getValue : function(){
-        var out = null;
-        this.eachItem(function(item){
-            if(item.checked){
-                out = item;
-                return false;
+        
+        if (comp.animCollapse && me.initialCollapsedComplete) {
+            shadowLayout.layout();
+            compEl.dom.style.zIndex = 100;
+
+            
+            if (!miniCollapse) {
+                placeholder.el.hide();
             }
-        });
-        return out;
-    },
-    
-    
-    onSetValue : function(id, value){
-        if(arguments.length > 1){
-            var f = this.getBox(id);
-            if(f){
-                f.setValue(value);
-                if(f.checked){
-                    this.eachItem(function(item){
-                        if (item !== f){
-                            item.setValue(false);
+            compEl.slideOut(me.slideDirection[comp.region], {
+                duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
+                listeners: {
+                    afteranimate: function() {
+                        compEl.show().setLeftTop(-10000, -10000);
+                        compEl.dom.style.zIndex = '';
+
+                        
+                       if (!miniCollapse) {
+                            placeholder.el.slideIn(me.slideDirection[comp.region], {
+                                easing: 'linear',
+                                duration: 100
+                            });
                         }
-                    });
+                        afterCollapse();
+                    }
                 }
-            }
-        }else{
-            this.setValueForItem(id);
+            });
+        } else {
+            compEl.setLeftTop(-10000, -10000);
+            shadowLayout.layout();
+            afterCollapse();
         }
+
+        return false;
     },
+
     
-    setValueForItem : function(val){
-        val = String(val).split(',')[0];
-        this.eachItem(function(item){
-            item.setValue(val == item.inputValue);
-        });
+    onBeforeRegionExpand: function(comp, animate) {
+        
+        this.onPlaceHolderToolClick(null, null, null, {client: comp, shouldFireBeforeexpand: false});
+        return false;
     },
+
     
-    
-    fireChecked : function(){
-        if(!this.checkTask){
-            this.checkTask = new Ext.util.DelayedTask(this.bufferChecked, this);
+    onPlaceHolderToolClick: function(e, target, owner, tool) {
+        var me = this,
+            comp = tool.client,
+
+            
+            hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
+            compEl = comp.el,
+            toCompBox,
+            placeholder = comp.placeholder,
+            placeholderEl = placeholder.el,
+            shadowContainer = comp.shadowOwnerCt,
+            shadowLayout = shadowContainer.layout,
+            curSize,
+            sl = me.owner.suspendLayout,
+            scsl = shadowContainer.suspendLayout,
+            isFloating;
+
+        if (comp.collapsedChangingLayout) {
+            return false;
         }
-        this.checkTask.delay(10);
-    },
-    
-    
-    bufferChecked : function(){
-        var out = null;
-        this.eachItem(function(item){
-            if(item.checked){
-                out = item;
-                return false;
-            }
-        });
-        this.fireEvent('change', this, out);
-    },
-    
-    onDestroy : function(){
-        if(this.checkTask){
-            this.checkTask.cancel();
-            this.checkTask = null;
+        if (tool.shouldFireBeforeexpand !== false && comp.fireEvent('beforeexpand', comp, true) === false) {
+            return false;
+        }
+        comp.collapsedChangingLayout = true;
+        
+        
+        
+        if (comp.getActiveAnimation()) {
+            comp.stopAnimation();
         }
-        Ext.form.RadioGroup.superclass.onDestroy.call(this);
-    }
 
-});
+        
+        
+        
+        if (comp.slideOutAnim) {
+            
+            compEl.un(comp.panelMouseMon);
+            placeholderEl.un(comp.placeholderMouseMon);
 
-Ext.reg('radiogroup', Ext.form.RadioGroup);
+            delete comp.slideOutAnim;
+            delete comp.panelMouseMon;
+            delete comp.placeholderMouseMon;
 
-Ext.form.Hidden = Ext.extend(Ext.form.Field, {
-    
-    inputType : 'hidden',
+            
+            isFloating = true;
+        }
 
-    
-    onRender : function(){
-        Ext.form.Hidden.superclass.onRender.apply(this, arguments);
-    },
+        
+        me.owner.suspendLayout = true;
+        shadowContainer.suspendLayout = true;
 
-    
-    initEvents : function(){
-        this.originalValue = this.getValue();
-    },
+        
+        shadowLayout.layoutBusy = true;
+        if (shadowContainer.componentLayout) {
+            shadowContainer.componentLayout.layoutBusy = true;
+        }
+        me.shadowContainer.layout.layoutBusy = true;
+        me.layoutBusy = true;
+        me.owner.componentLayout.layoutBusy = true;
 
-    
-    setSize : Ext.emptyFn,
-    setWidth : Ext.emptyFn,
-    setHeight : Ext.emptyFn,
-    setPosition : Ext.emptyFn,
-    setPagePosition : Ext.emptyFn,
-    markInvalid : Ext.emptyFn,
-    clearInvalid : Ext.emptyFn
-});
-Ext.reg('hidden', Ext.form.Hidden);
-Ext.form.BasicForm = Ext.extend(Ext.util.Observable, {
+        
+        
+        comp.hidden = false;
+        comp.collapsed = false;
+        if (hidePlaceholder) {
+            placeholder.hidden = true;
+        }
+        toCompBox = shadowLayout.calculateChildBox(comp);
 
-    constructor: function(el, config){
-        Ext.apply(this, config);
-        if(Ext.isString(this.paramOrder)){
-            this.paramOrder = this.paramOrder.split(/[\s,|]/);
+        
+        if (comp.collapseTool) {
+            comp.collapseTool.show();
         }
+
         
-        this.items = new Ext.util.MixedCollection(false, function(o){
-            return o.getItemId();
-        });
-        this.addEvents(
+        if (comp.animCollapse && !isFloating) {
+            compEl.setStyle('visibility', 'hidden');
+        }
+        compEl.setLeftTop(toCompBox.left, toCompBox.top);
+
+        
+        
+        curSize = comp.getSize();
+        if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
+            me.setItemSize(comp, toCompBox.width, toCompBox.height);
+        }
+
+        
+        function afterExpand() {
             
-            'beforeaction',
+            me.owner.suspendLayout = sl;
+            shadowContainer.suspendLayout = scsl;
+            delete shadowLayout.layoutBusy;
+            if (shadowContainer.componentLayout) {
+                delete shadowContainer.componentLayout.layoutBusy;
+            }
+            delete me.shadowContainer.layout.layoutBusy;
+            delete me.layoutBusy;
+            delete me.owner.componentLayout.layoutBusy;
+            delete comp.collapsedChangingLayout;
+
             
-            'actionfailed',
+            comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
+
             
-            'actioncomplete'
-        );
+            comp.fireEvent('expand', comp);
+        }
 
-        if(el){
-            this.initEl(el);
+        
+        if (hidePlaceholder) {
+            placeholder.el.hide();
+        }
+
+        
+        
+        if (comp.animCollapse && !isFloating) {
+            compEl.dom.style.zIndex = 100;
+            compEl.slideIn(me.slideDirection[comp.region], {
+                duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
+                listeners: {
+                    afteranimate: function() {
+                        compEl.dom.style.zIndex = '';
+                        comp.hidden = false;
+                        shadowLayout.onLayout();
+                        afterExpand();
+                    }
+                }
+            });
+        } else {
+            shadowLayout.onLayout();
+            afterExpand();
         }
-        Ext.form.BasicForm.superclass.constructor.call(this);
     },
 
-    
-    
-    
-    
-    
-    
-    
-    timeout: 30,
+    floatCollapsedPanel: function(e, comp) {
 
-    
+        if (comp.floatable === false) {
+            return;
+        }
 
-    
-    paramOrder: undefined,
+        var me = this,
+            compEl = comp.el,
+            placeholder = comp.placeholder,
+            placeholderEl = placeholder.el,
+            shadowContainer = comp.shadowOwnerCt,
+            shadowLayout = shadowContainer.layout,
+            placeholderBox = shadowLayout.getChildBox(placeholder),
+            scsl = shadowContainer.suspendLayout,
+            curSize, toCompBox, compAnim;
 
-    
-    paramsAsHash: false,
+        
+        if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
+            return;
+        }
 
-    
-    waitTitle: 'Please Wait...',
+        
+        
+        if (compEl.getActiveAnimation()) {
+            return;
+        }
 
-    
-    activeAction : null,
+        
+        
+        if (comp.slideOutAnim) {
+            me.slideOutFloatedComponent(comp);
+            return;
+        }
 
-    
-    trackResetOnLoad : false,
+        
+        
+        function onMouseLeaveFloated(e) {
+            var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
 
-    
-    
+            
+            if (!slideRegion.contains(e.getPoint())) {
+                me.slideOutFloatedComponent(comp);
+            }
+        }
 
-    
-    initEl : function(el){
-        this.el = Ext.get(el);
-        this.id = this.el.id || Ext.id();
-        if(!this.standardSubmit){
-            this.el.on('submit', this.onSubmit, this);
+        
+        comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
+
+        
+        shadowContainer.suspendLayout = true;
+
+        
+        me.layoutBusy = true;
+        me.owner.componentLayout.layoutBusy = true;
+
+        
+        
+        if (comp.collapseTool) {
+            comp.collapseTool.hide();
         }
-        this.el.addClass('x-form');
-    },
 
-    
-    getEl: function(){
-        return this.el;
-    },
+        
+        comp.hidden = false;
+        comp.collapsed = false;
+        placeholder.hidden = true;
 
-    
-    onSubmit : function(e){
-        e.stopEvent();
-    },
+        
+        toCompBox = shadowLayout.calculateChildBox(comp);
+        placeholder.hidden = false;
 
-    
-    destroy: function(bound){
-        if(bound !== true){
-            this.items.each(function(f){
-                Ext.destroy(f);
-            });
-            Ext.destroy(this.el);
+        
+        if (comp.region == 'north' || comp.region == 'west') {
+            toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
+        } else {
+            toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
         }
-        this.items.clear();
-        this.purgeListeners();
-    },
+        compEl.setStyle('visibility', 'hidden');
+        compEl.setLeftTop(toCompBox.left, toCompBox.top);
+
+        
+        
+        curSize = comp.getSize();
+        if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
+            me.setItemSize(comp, toCompBox.width, toCompBox.height);
+        }
+
+        
+        compAnim = {
+            listeners: {
+                afteranimate: function() {
+                    shadowContainer.suspendLayout = scsl;
+                    delete me.layoutBusy;
+                    delete me.owner.componentLayout.layoutBusy;
+
+                    
+                    compAnim.listeners = {
+                        afterAnimate: function() {
+                            compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
+
+                            
+                            comp.hidden = true;
+                            comp.collapsed = true;
+                            delete comp.slideOutAnim;
+                            delete comp.panelMouseMon;
+                            delete comp.placeholderMouseMon;
+                        }
+                    };
+                    comp.slideOutAnim = compAnim;
+                }
+            },
+            duration: 500
+        };
+
+        
+        compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
+
+        
+        compEl.slideIn(me.slideDirection[comp.region], compAnim);
+
+        
+        comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
 
-    
-    isValid : function(){
-        var valid = true;
-        this.items.each(function(f){
-           if(!f.validate()){
-               valid = false;
-           }
-        });
-        return valid;
     },
 
-    
-    isDirty : function(){
-        var dirty = false;
-        this.items.each(function(f){
-           if(f.isDirty()){
-               dirty = true;
-               return false;
-           }
-        });
-        return dirty;
+    slideOutFloatedComponent: function(comp) {
+        var compEl = comp.el,
+            slideOutAnim;
+
+        
+        compEl.un(comp.panelMouseMon);
+        comp.placeholder.el.un(comp.placeholderMouseMon);
+
+        
+        compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
+
+        delete comp.slideOutAnim;
+        delete comp.panelMouseMon;
+        delete comp.placeholderMouseMon;
     },
 
     
-    doAction : function(action, options){
-        if(Ext.isString(action)){
-            action = new Ext.form.Action.ACTION_TYPES[action](this, options);
+    onRegionDestroy: function(comp) {
+        var placeholder = comp.placeholder;
+        if (placeholder) {
+            delete placeholder.ownerCt;
+            placeholder.destroy();
         }
-        if(this.fireEvent('beforeaction', this, action) !== false){
-            this.beforeAction(action);
-            action.run.defer(100, action);
-        }
-        return this;
     },
 
     
-    submit : function(options){
-        options = options || {};
-        if(this.standardSubmit){
-            var v = options.clientValidation === false || this.isValid();
-            if(v){
-                var el = this.el.dom;
-                if(this.url && Ext.isEmpty(el.action)){
-                    el.action = this.url;
-                }
-                el.submit();
-            }
-            return v;
+    onDestroy: function() {
+        var me = this,
+            shadowContainer = me.shadowContainer,
+            embeddedContainer = me.embeddedContainer;
+
+        if (shadowContainer) {
+            delete shadowContainer.ownerCt;
+            Ext.destroy(shadowContainer);
         }
-        var submitAction = String.format('{0}submit', this.api ? 'direct' : '');
-        this.doAction(submitAction, options);
-        return this;
-    },
 
-    
-    load : function(options){
-        var loadAction = String.format('{0}load', this.api ? 'direct' : '');
-        this.doAction(loadAction, options);
-        return this;
-    },
+        if (embeddedContainer) {
+            delete embeddedContainer.ownerCt;
+            Ext.destroy(embeddedContainer);
+        }
+        delete me.regions;
+        delete me.splitters;
+        delete me.shadowContainer;
+        delete me.embeddedContainer;
+        me.callParent(arguments);
+    }
+});
+
+
+Ext.define('Ext.layout.container.Card', {
 
     
-    updateRecord : function(record){
-        record.beginEdit();
-        var fs = record.fields;
-        fs.each(function(f){
-            var field = this.findField(f.name);
-            if(field){
-                record.set(f.name, field.getValue());
-            }
-        }, this);
-        record.endEdit();
-        return this;
-    },
+
+    alias: ['layout.card'],
+    alternateClassName: 'Ext.layout.CardLayout',
+
+    extend: 'Ext.layout.container.AbstractCard',
 
     
-    loadRecord : function(record){
-        this.setValues(record.data);
-        return this;
-    },
 
     
-    beforeAction : function(action){
+    setActiveItem: function(newCard) {
+        var me = this,
+            owner = me.owner,
+            oldCard = me.activeItem,
+            newIndex;
+
+        newCard = me.parseActiveItem(newCard);
+        newIndex = owner.items.indexOf(newCard);
+
         
-        this.items.each(function(f){
-            if(f.isFormField && f.syncValue){
-                f.syncValue();
+        if (newIndex == -1) {
+            newIndex = owner.items.items.length;
+            owner.add(newCard);
+        }
+
+        
+        if (newCard && oldCard != newCard) {
+            
+            if (!newCard.rendered) {
+                me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
+                me.configureItem(newCard, 0);
             }
-        });
-        var o = action.options;
-        if(o.waitMsg){
-            if(this.waitMsgTarget === true){
-                this.el.mask(o.waitMsg, 'x-mask-loading');
-            }else if(this.waitMsgTarget){
-                this.waitMsgTarget = Ext.get(this.waitMsgTarget);
-                this.waitMsgTarget.mask(o.waitMsg, 'x-mask-loading');
-            }else{
-                Ext.MessageBox.wait(o.waitMsg, o.waitTitle || this.waitTitle);
+
+            me.activeItem = newCard;
+
+            
+            if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
+                return false;
+            }
+            if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
+                return false;
             }
-        }
-    },
 
-    
-    afterAction : function(action, success){
-        this.activeAction = null;
-        var o = action.options;
-        if(o.waitMsg){
-            if(this.waitMsgTarget === true){
-                this.el.unmask();
-            }else if(this.waitMsgTarget){
-                this.waitMsgTarget.unmask();
-            }else{
-                Ext.MessageBox.updateProgress(1);
-                Ext.MessageBox.hide();
+            
+            if (me.sizeAllCards) {
+                
+                me.onLayout();
             }
-        }
-        if(success){
-            if(o.reset){
-                this.reset();
+            else {
+                me.setItemBox(newCard, me.getTargetBox());
             }
-            Ext.callback(o.success, o.scope, [this, action]);
-            this.fireEvent('actioncomplete', this, action);
-        }else{
-            Ext.callback(o.failure, o.scope, [this, action]);
-            this.fireEvent('actionfailed', this, action);
+
+            me.owner.suspendLayout = true;
+
+            if (oldCard) {
+                if (me.hideInactive) {
+                    oldCard.hide();
+                }
+                oldCard.fireEvent('deactivate', oldCard, newCard);
+            }
+
+            
+            me.owner.suspendLayout = false;
+            if (newCard.hidden) {
+                newCard.show();
+            } else {
+                me.onLayout();
+            }
+
+            newCard.fireEvent('activate', newCard, oldCard);
+
+            return newCard;
         }
+        return false;
     },
 
-    
-    findField : function(id) {
-        var field = this.items.get(id);
+    configureItem: function(item) {
+        
+        
+        item.layoutManagedHeight = 0;
+        item.layoutManagedWidth = 0;
+
+        this.callParent(arguments);
+    }});
+
+Ext.define('Ext.layout.container.Column', {
+
+    extend: 'Ext.layout.container.Auto',
+    alias: ['layout.column'],
+    alternateClassName: 'Ext.layout.ColumnLayout',
+
+    type: 'column',
+
+    itemCls: Ext.baseCSSPrefix + 'column',
+
+    targetCls: Ext.baseCSSPrefix + 'column-layout-ct',
+
+    scrollOffset: 0,
+
+    bindToOwnerCtComponent: false,
+
+    getRenderTarget : function() {
+        if (!this.innerCt) {
 
-        if (!Ext.isObject(field)) {
             
-            var findMatchingField = function(f) {
-                if (f.isFormField) {
-                    if (f.dataIndex == id || f.id == id || f.getName() == id) {
-                        field = f;
-                        return false;
-                    } else if (f.isComposite && f.rendered) {
-                        return f.items.each(findMatchingField);
-                    }
-                }
-            };
+            
+            this.innerCt = this.getTarget().createChild({
+                cls: Ext.baseCSSPrefix + 'column-inner'
+            });
 
-            this.items.each(findMatchingField);
+            
+            
+            
+            this.clearEl = this.innerCt.createChild({
+                cls: Ext.baseCSSPrefix + 'clear',
+                role: 'presentation'
+            });
         }
-        return field || null;
+        return this.innerCt;
     },
 
-
     
-    markInvalid : function(errors){
-        if (Ext.isArray(errors)) {
-            for(var i = 0, len = errors.length; i < len; i++){
-                var fieldError = errors[i];
-                var f = this.findField(fieldError.id);
-                if(f){
-                    f.markInvalid(fieldError.msg);
-                }
+    onLayout : function() {
+        var me = this,
+            target = me.getTarget(),
+            items = me.getLayoutItems(),
+            len = items.length,
+            item,
+            i,
+            parallelMargins = [],
+            itemParallelMargins,
+            size,
+            availableWidth,
+            columnWidth;
+
+        size = me.getLayoutTargetSize();
+        if (size.width < len * 10) { 
+            return;
+        }
+
+        
+        
+        
+        if (me.adjustmentPass) {
+            if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
+                size.width = me.adjustedWidth;
             }
         } else {
-            var field, id;
-            for(id in errors){
-                if(!Ext.isFunction(errors[id]) && (field = this.findField(id))){
-                    field.markInvalid(errors[id]);
+            i = target.getStyle('overflow');
+            if (i && i != 'hidden') {
+                me.autoScroll = true;
+                if (!(Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks)) {
+                    target.setStyle('overflow', 'hidden');
+                    size = me.getLayoutTargetSize();
                 }
             }
         }
 
-        return this;
-    },
+        availableWidth = size.width - me.scrollOffset;
+        me.innerCt.setWidth(availableWidth);
 
-    
-    setValues : function(values){
-        if(Ext.isArray(values)){ 
-            for(var i = 0, len = values.length; i < len; i++){
-                var v = values[i];
-                var f = this.findField(v.id);
-                if(f){
-                    f.setValue(v.value);
-                    if(this.trackResetOnLoad){
-                        f.originalValue = f.getValue();
-                    }
-                }
-            }
-        }else{ 
-            var field, id;
-            for(id in values){
-                if(!Ext.isFunction(values[id]) && (field = this.findField(id))){
-                    field.setValue(values[id]);
-                    if(this.trackResetOnLoad){
-                        field.originalValue = field.getValue();
-                    }
-                }
+        
+        
+        for (i = 0; i < len; i++) {
+            item = items[i];
+            itemParallelMargins = parallelMargins[i] = item.getEl().getMargin('lr');
+            if (!item.columnWidth) {
+                availableWidth -= (item.getWidth() + itemParallelMargins);
             }
         }
-        return this;
-    },
 
-    
-    getValues : function(asString){
-        var fs = Ext.lib.Ajax.serializeForm(this.el.dom);
-        if(asString === true){
-            return fs;
+        availableWidth = availableWidth < 0 ? 0 : availableWidth;
+        for (i = 0; i < len; i++) {
+            item = items[i];
+            if (item.columnWidth) {
+                columnWidth = Math.floor(item.columnWidth * availableWidth) - parallelMargins[i];
+                me.setItemSize(item, columnWidth, item.height);
+            } else {
+                me.layoutItem(item);
+            }
         }
-        return Ext.urlDecode(fs);
-    },
 
-    
-    getFieldValues : function(dirtyOnly){
-        var o = {},
-            n,
-            key,
-            val;
-        this.items.each(function(f) {
-            if (dirtyOnly !== true || f.isDirty()) {
-                n = f.getName();
-                key = o[n];
-                val = f.getValue();
-
-                if(Ext.isDefined(key)){
-                    if(Ext.isArray(key)){
-                        o[n].push(val);
-                    }else{
-                        o[n] = [key, val];
-                    }
-                }else{
-                    o[n] = val;
-                }
+        
+        if (!me.adjustmentPass && me.autoScroll) {
+
+            
+            target.setStyle('overflow', 'auto');
+            me.adjustmentPass = (target.dom.scrollHeight > size.height);
+            if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
+                me.adjustedWidth = size.width - Ext.getScrollBarWidth();
+            } else {
+                target.setStyle('overflow', 'auto');
             }
-        });
-        return o;
-    },
 
-    
-    clearInvalid : function(){
-        this.items.each(function(f){
-           f.clearInvalid();
-        });
-        return this;
+            
+            if (me.adjustmentPass) {
+                me.onLayout();
+            }
+        }
+        delete me.adjustmentPass;
     },
 
-    
-    reset : function(){
-        this.items.each(function(f){
-            f.reset();
-        });
-        return this;
-    },
+    configureItem: function(item) {
+        this.callParent(arguments);
 
-    
-    add : function(){
-        this.items.addAll(Array.prototype.slice.call(arguments, 0));
-        return this;
-    },
+        if (item.columnWidth) {
+            item.layoutManagedWidth = 1;
+        }
+    }
+});
 
-    
-    remove : function(field){
-        this.items.remove(field);
-        return this;
-    },
+Ext.define('Ext.layout.container.Table', {
 
     
-    cleanDestroyed : function() {
-        this.items.filterBy(function(o) { return !!o.isDestroyed; }).each(this.remove, this);
-    },
 
-    
-    render : function(){
-        this.items.each(function(f){
-            if(f.isFormField && !f.rendered && document.getElementById(f.id)){ 
-                f.applyToMarkup(f.id);
-            }
-        });
-        return this;
-    },
+    alias: ['layout.table'],
+    extend: 'Ext.layout.container.Auto',
+    alternateClassName: 'Ext.layout.TableLayout',
 
     
-    applyToFields : function(o){
-        this.items.each(function(f){
-           Ext.apply(f, o);
-        });
-        return this;
-    },
 
     
-    applyIfToFields : function(o){
-        this.items.each(function(f){
-           Ext.applyIf(f, o);
-        });
-        return this;
-    },
-
-    callFieldMethod : function(fnName, args){
-        args = args || [];
-        this.items.each(function(f){
-            if(Ext.isFunction(f[fnName])){
-                f[fnName].apply(f, args);
-            }
-        });
-        return this;
-    }
-});
 
+    
+    monitorResize:false,
 
-Ext.BasicForm = Ext.form.BasicForm;
+    type: 'table',
 
-Ext.FormPanel = Ext.extend(Ext.Panel, {
-    
-    
-    
-    
-    
     
     
+    autoSize: true,
 
+    clearEl: true, 
 
-    
-    minButtonWidth : 75,
+    targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
+    tableCls: Ext.baseCSSPrefix + 'table-layout',
+    cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
 
     
-    labelAlign : 'left',
+    tableAttrs:null,
 
     
-    monitorValid : false,
 
     
-    monitorPoll : 200,
 
     
-    layout : 'form',
+    renderItems: function(items) {
+        var tbody = this.getTable().tBodies[0],
+            rows = tbody.rows,
+            i = 0,
+            len = items.length,
+            cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
 
-    
-    initComponent : function(){
-        this.form = this.createForm();
-        Ext.FormPanel.superclass.initComponent.call(this);
+        
+        cells = this.calculateCells(items);
 
-        this.bodyCfg = {
-            tag: 'form',
-            cls: this.baseCls + '-body',
-            method : this.method || 'POST',
-            id : this.formId || Ext.id()
-        };
-        if(this.fileUpload) {
-            this.bodyCfg.enctype = 'multipart/form-data';
-        }
-        this.initItems();
+        
+        
+        
+        for (; i < len; i++) {
+            curCell = cells[i];
+            rowIdx = curCell.rowIdx;
+            cellIdx = curCell.cellIdx;
+            item = items[i];
 
-        this.addEvents(
             
-            'clientvalidation'
-        );
+            trEl = rows[rowIdx];
+            if (!trEl) {
+                trEl = tbody.insertRow(rowIdx);
+                if (this.trAttrs) {
+                    trEl.set(this.trAttrs);
+                }
+            }
 
-        this.relayEvents(this.form, ['beforeaction', 'actionfailed', 'actioncomplete']);
-    },
+            
+            itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx));
+            if (this.needsDivWrap()) { 
+                itemCt = tdEl.first() || tdEl.createChild({tag: 'div'});
+                itemCt.setWidth(null);
+            }
 
-    
-    createForm : function(){
-        var config = Ext.applyIf({listeners: {}}, this.initialConfig);
-        return new Ext.form.BasicForm(null, config);
-    },
+            
+            if (!item.rendered) {
+                this.renderItem(item, itemCt, 0);
+            }
+            else if (!this.isValidParent(item, itemCt, 0)) {
+                this.moveItem(item, itemCt, 0);
+            }
 
-    
-    initFields : function(){
-        var f = this.form;
-        var formPanel = this;
-        var fn = function(c){
-            if(formPanel.isField(c)){
-                f.add(c);
-            }else if(c.findBy && c != formPanel){
-                formPanel.applySettings(c);
-                
-                if(c.items && c.items.each){
-                    c.items.each(fn, this);
+            
+            if (this.tdAttrs) {
+                tdEl.set(this.tdAttrs);
+            }
+            tdEl.set({
+                colSpan: item.colspan || 1,
+                rowSpan: item.rowspan || 1,
+                id: item.cellId || '',
+                cls: this.cellCls + ' ' + (item.cellCls || '')
+            });
+
+            
+            if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) {
+                cellIdx++;
+                while (trEl.cells[cellIdx]) {
+                    trEl.deleteCell(cellIdx);
                 }
             }
-        };
-        this.items.each(fn, this);
-    },
+        }
 
-    
-    applySettings: function(c){
-        var ct = c.ownerCt;
-        Ext.applyIf(c, {
-            labelAlign: ct.labelAlign,
-            labelWidth: ct.labelWidth,
-            itemCls: ct.itemCls
-        });
+        
+        rowIdx++;
+        while (tbody.rows[rowIdx]) {
+            tbody.deleteRow(rowIdx);
+        }
     },
 
-    
-    getLayoutTarget : function(){
-        return this.form.el;
-    },
+    afterLayout: function() {
+        this.callParent();
 
-    
-    getForm : function(){
-        return this.form;
+        if (this.needsDivWrap()) {
+            
+            Ext.Array.forEach(this.getLayoutItems(), function(item) {
+                Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth());
+            });
+        }
     },
 
     
-    onRender : function(ct, position){
-        this.initFields();
-        Ext.FormPanel.superclass.onRender.call(this, ct, position);
-        this.form.initEl(this.body);
-    },
+    calculateCells: function(items) {
+        var cells = [],
+            rowIdx = 0,
+            colIdx = 0,
+            cellIdx = 0,
+            totalCols = this.columns || Infinity,
+            rowspans = [], 
+            i = 0, j,
+            len = items.length,
+            item;
 
-    
-    beforeDestroy : function(){
-        this.stopMonitoring();
-        this.form.destroy(true);
-        Ext.FormPanel.superclass.beforeDestroy.call(this);
-    },
+        for (; i < len; i++) {
+            item = items[i];
 
-    
-    isField : function(c) {
-        return !!c.setValue && !!c.getValue && !!c.markInvalid && !!c.clearInvalid;
-    },
+            
+            while (colIdx >= totalCols || rowspans[colIdx] > 0) {
+                if (colIdx >= totalCols) {
+                    
+                    colIdx = 0;
+                    cellIdx = 0;
+                    rowIdx++;
 
-    
-    initEvents : function(){
-        Ext.FormPanel.superclass.initEvents.call(this);
-        
-        this.on({
-            scope: this,
-            add: this.onAddEvent,
-            remove: this.onRemoveEvent
-        });
-        if(this.monitorValid){ 
-            this.startMonitoring();
+                    
+                    for (j = 0; j < totalCols; j++) {
+                        if (rowspans[j] > 0) {
+                            rowspans[j]--;
+                        }
+                    }
+                } else {
+                    colIdx++;
+                }
+            }
+
+            
+            cells.push({
+                rowIdx: rowIdx,
+                cellIdx: cellIdx
+            });
+
+            
+            for (j = item.colspan || 1; j; --j) {
+                rowspans[colIdx] = item.rowspan || 1;
+                ++colIdx;
+            }
+            ++cellIdx;
         }
-    },
 
-    
-    onAdd: function(c){
-        Ext.FormPanel.superclass.onAdd.call(this, c);
-        this.processAdd(c);
+        return cells;
     },
 
     
-    onAddEvent: function(ct, c){
-        if(ct !== this){
-            this.processAdd(c);
+    getTable: function() {
+        var table = this.table;
+        if (!table) {
+            table = this.table = this.getTarget().createChild(
+                Ext.apply({
+                    tag: 'table',
+                    role: 'presentation',
+                    cls: this.tableCls,
+                    cellspacing: 0, 
+                    cn: {tag: 'tbody'}
+                }, this.tableAttrs),
+                null, true
+            );
         }
+        return table;
     },
 
     
-    processAdd : function(c){
-        
-        if(this.isField(c)){
-            this.form.add(c);
-        
-        }else if(c.findBy){
-            this.applySettings(c);
-            this.form.add.apply(this.form, c.findBy(this.isField));
-        }
-    },
+    needsDivWrap: function() {
+        return Ext.isOpera10_5;
+    }
+});
+
+Ext.define('Ext.menu.Item', {
+    extend: 'Ext.Component',
+    alias: 'widget.menuitem',
+    alternateClassName: 'Ext.menu.TextItem',
 
     
-    onRemove: function(c){
-        Ext.FormPanel.superclass.onRemove.call(this, c);
-        this.processRemove(c);
-    },
 
-    onRemoveEvent: function(ct, c){
-        if(ct !== this){
-            this.processRemove(c);
-        }
-    },
+    
 
     
-    processRemove: function(c){
-        if(!this.destroying){
-            
-            if(this.isField(c)){
-                this.form.remove(c);
-            
-            }else if (c.findBy){
-                Ext.each(c.findBy(this.isField), this.form.remove, this.form);
-                if (c.isDestroyed) {
-                    this.form.cleanDestroyed();
-                }
-            }
-        }
-    },
+    activeCls: Ext.baseCSSPrefix + 'menu-item-active',
 
     
-    startMonitoring : function(){
-        if(!this.validTask){
-            this.validTask = new Ext.util.TaskRunner();
-            this.validTask.start({
-                run : this.bindHandler,
-                interval : this.monitorPoll || 200,
-                scope: this
-            });
-        }
-    },
+    ariaRole: 'menuitem',
 
     
-    stopMonitoring : function(){
-        if(this.validTask){
-            this.validTask.stopAll();
-            this.validTask = null;
-        }
-    },
+    canActivate: true,
 
     
-    load : function(){
-        this.form.load.apply(this.form, arguments);
-    },
+    clickHideDelay: 1,
 
     
-    onDisable : function(){
-        Ext.FormPanel.superclass.onDisable.call(this);
-        if(this.form){
-            this.form.items.each(function(){
-                 this.disable();
-            });
-        }
-    },
+    destroyMenu: true,
 
     
-    onEnable : function(){
-        Ext.FormPanel.superclass.onEnable.call(this);
-        if(this.form){
-            this.form.items.each(function(){
-                 this.enable();
-            });
-        }
-    },
+    disabledCls: Ext.baseCSSPrefix + 'menu-item-disabled',
 
     
-    bindHandler : function(){
-        var valid = true;
-        this.form.items.each(function(f){
-            if(!f.isValid(true)){
-                valid = false;
-                return false;
-            }
-        });
-        if(this.fbar){
-            var fitems = this.fbar.items.items;
-            for(var i = 0, len = fitems.length; i < len; i++){
-                var btn = fitems[i];
-                if(btn.formBind === true && btn.disabled === valid){
-                    btn.setDisabled(!valid);
-                }
-            }
-        }
-        this.fireEvent('clientvalidation', this, valid);
-    }
-});
-Ext.reg('form', Ext.FormPanel);
 
-Ext.form.FormPanel = Ext.FormPanel;
+     
 
-Ext.form.FieldSet = Ext.extend(Ext.Panel, {
     
+    hideOnClick: true,
+
     
+
     
+
+    isMenuItem: true,
+
     
+
     
+    menuAlign: 'tl-tr?',
+
     
-    baseCls : 'x-fieldset',
+    menuExpandDelay: 200,
+
     
-    layout : 'form',
+    menuHideDelay: 200,
+
     
-    animCollapse : false,
+
+    renderTpl: [
+        '<tpl if="plain">',
+            '{text}',
+        '</tpl>',
+        '<tpl if="!plain">',
+            '<a id="{id}-itemEl" class="' + Ext.baseCSSPrefix + 'menu-item-link" href="{href}" <tpl if="hrefTarget">target="{hrefTarget}"</tpl> hidefocus="true" unselectable="on">',
+                '<img id="{id}-iconEl" src="{icon}" class="' + Ext.baseCSSPrefix + 'menu-item-icon {iconCls}" />',
+                '<span id="{id}-textEl" class="' + Ext.baseCSSPrefix + 'menu-item-text" <tpl if="menu">style="margin-right: 17px;"</tpl> >{text}</span>',
+                '<tpl if="menu">',
+                    '<img id="{id}-arrowEl" src="{blank}" class="' + Ext.baseCSSPrefix + 'menu-item-arrow" />',
+                '</tpl>',
+            '</a>',
+        '</tpl>'
+    ],
+
+    maskOnDisable: false,
 
     
-    onRender : function(ct, position){
-        if(!this.el){
-            this.el = document.createElement('fieldset');
-            this.el.id = this.id;
-            if (this.title || this.header || this.checkboxToggle) {
-                this.el.appendChild(document.createElement('legend')).className = this.baseCls + '-header';
-            }
-        }
 
-        Ext.form.FieldSet.superclass.onRender.call(this, ct, position);
+    activate: function() {
+        var me = this;
 
-        if(this.checkboxToggle){
-            var o = typeof this.checkboxToggle == 'object' ?
-                    this.checkboxToggle :
-                    {tag: 'input', type: 'checkbox', name: this.checkboxName || this.id+'-checkbox'};
-            this.checkbox = this.header.insertFirst(o);
-            this.checkbox.dom.checked = !this.collapsed;
-            this.mon(this.checkbox, 'click', this.onCheckClick, this);
+        if (!me.activated && me.canActivate && me.rendered && !me.isDisabled() && me.isVisible()) {
+            me.el.addCls(me.activeCls);
+            me.focus();
+            me.activated = true;
+            me.fireEvent('activate', me);
         }
     },
 
-    
-    onCollapse : function(doAnim, animArg){
-        if(this.checkbox){
-            this.checkbox.dom.checked = false;
+    blur: function() {
+        this.$focused = false;
+        this.callParent(arguments);
+    },
+
+    deactivate: function() {
+        var me = this;
+
+        if (me.activated) {
+            me.el.removeCls(me.activeCls);
+            me.blur();
+            me.hideMenu();
+            me.activated = false;
+            me.fireEvent('deactivate', me);
         }
-        Ext.form.FieldSet.superclass.onCollapse.call(this, doAnim, animArg);
+    },
+
+    deferExpandMenu: function() {
+        var me = this;
 
+        if (!me.menu.rendered || !me.menu.isVisible()) {
+            me.parentMenu.activeChild = me.menu;
+            me.menu.parentItem = me;
+            me.menu.parentMenu = me.menu.ownerCt = me.parentMenu;
+            me.menu.showBy(me, me.menuAlign);
+        }
     },
 
-    
-    onExpand : function(doAnim, animArg){
-        if(this.checkbox){
-            this.checkbox.dom.checked = true;
+    deferHideMenu: function() {
+        if (this.menu.isVisible()) {
+            this.menu.hide();
         }
-        Ext.form.FieldSet.superclass.onExpand.call(this, doAnim, animArg);
     },
 
-    
-    onCheckClick : function(){
-        this[this.checkbox.dom.checked ? 'expand' : 'collapse']();
-    }
+    deferHideParentMenus: function() {
+        Ext.menu.Manager.hideAll();
+    },
 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-});
-Ext.reg('fieldset', Ext.form.FieldSet);
+    expandMenu: function(delay) {
+        var me = this;
 
-Ext.form.HtmlEditor = Ext.extend(Ext.form.Field, {
-    
-    enableFormat : true,
-    
-    enableFontSize : true,
-    
-    enableColors : true,
-    
-    enableAlignments : true,
-    
-    enableLists : true,
-    
-    enableSourceEdit : true,
-    
-    enableLinks : true,
-    
-    enableFont : true,
-    
-    createLinkText : 'Please enter the URL for the link:',
-    
-    defaultLinkValue : 'http:/'+'/',
-    
-    fontFamilies : [
-        'Arial',
-        'Courier New',
-        'Tahoma',
-        'Times New Roman',
-        'Verdana'
-    ],
-    defaultFont: 'tahoma',
-    
-    defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
+        if (me.menu) {
+            clearTimeout(me.hideMenuTimer);
+            if (delay === 0) {
+                me.deferExpandMenu();
+            } else {
+                me.expandMenuTimer = Ext.defer(me.deferExpandMenu, Ext.isNumber(delay) ? delay : me.menuExpandDelay, me);
+            }
+        }
+    },
 
-    
-    actionMode: 'wrap',
-    validationEvent : false,
-    deferHeight: true,
-    initialized : false,
-    activated : false,
-    sourceEditMode : false,
-    onFocus : Ext.emptyFn,
-    iframePad:3,
-    hideMode:'offsets',
-    defaultAutoCreate : {
-        tag: "textarea",
-        style:"width:500px;height:300px;",
-        autocomplete: "off"
+    focus: function() {
+        this.$focused = true;
+        this.callParent(arguments);
     },
 
-    
-    initComponent : function(){
-        this.addEvents(
-            
-            'initialize',
-            
-            'activate',
-             
-            'beforesync',
-             
-            'beforepush',
-             
-            'sync',
-             
-            'push',
-             
-            'editmodechange'
-        );
+    getRefItems: function(deep){
+        var menu = this.menu,
+            items;
+
+        if (menu) {
+            items = menu.getRefItems(deep);
+            items.unshift(menu);
+        }
+        return items || [];
     },
 
-    
-    createFontOptions : function(){
-        var buf = [], fs = this.fontFamilies, ff, lc;
-        for(var i = 0, len = fs.length; i< len; i++){
-            ff = fs[i];
-            lc = ff.toLowerCase();
-            buf.push(
-                '<option value="',lc,'" style="font-family:',ff,';"',
-                    (this.defaultFont == lc ? ' selected="true">' : '>'),
-                    ff,
-                '</option>'
-            );
+    hideMenu: function(delay) {
+        var me = this;
+
+        if (me.menu) {
+            clearTimeout(me.expandMenuTimer);
+            me.hideMenuTimer = Ext.defer(me.deferHideMenu, Ext.isNumber(delay) ? delay : me.menuHideDelay, me);
         }
-        return buf.join('');
     },
 
-    
-    createToolbar : function(editor){
-        var items = [];
-        var tipsEnabled = Ext.QuickTips && Ext.QuickTips.isEnabled();
+    initComponent: function() {
+        var me = this,
+            prefix = Ext.baseCSSPrefix,
+            cls = [prefix + 'menu-item'];
 
+        me.addEvents(
+            
+            'activate',
 
-        function btn(id, toggle, handler){
-            return {
-                itemId : id,
-                cls : 'x-btn-icon',
-                iconCls: 'x-edit-'+id,
-                enableToggle:toggle !== false,
-                scope: editor,
-                handler:handler||editor.relayBtnCmd,
-                clickEvent:'mousedown',
-                tooltip: tipsEnabled ? editor.buttonTips[id] || undefined : undefined,
-                overflowText: editor.buttonTips[id].title || undefined,
-                tabIndex:-1
-            };
-        }
+            
+            'click',
 
+            
+            'deactivate'
+        );
 
-        if(this.enableFont && !Ext.isSafari2){
-            var fontSelectItem = new Ext.Toolbar.Item({
-               autoEl: {
-                    tag:'select',
-                    cls:'x-font-select',
-                    html: this.createFontOptions()
-               }
-            });
+        if (me.plain) {
+            cls.push(prefix + 'menu-item-plain');
+        }
 
-            items.push(
-                fontSelectItem,
-                '-'
-            );
+        if (me.cls) {
+            cls.push(me.cls);
         }
 
-        if(this.enableFormat){
-            items.push(
-                btn('bold'),
-                btn('italic'),
-                btn('underline')
-            );
+        me.cls = cls.join(' ');
+
+        if (me.menu) {
+            me.menu = Ext.menu.Manager.get(me.menu);
         }
 
-        if(this.enableFontSize){
-            items.push(
-                '-',
-                btn('increasefontsize', false, this.adjustFont),
-                btn('decreasefontsize', false, this.adjustFont)
-            );
+        me.callParent(arguments);
+    },
+
+    onClick: function(e) {
+        var me = this;
+
+        if (!me.href) {
+            e.stopEvent();
         }
 
-        if(this.enableColors){
-            items.push(
-                '-', {
-                    itemId:'forecolor',
-                    cls:'x-btn-icon',
-                    iconCls: 'x-edit-forecolor',
-                    clickEvent:'mousedown',
-                    tooltip: tipsEnabled ? editor.buttonTips.forecolor || undefined : undefined,
-                    tabIndex:-1,
-                    menu : new Ext.menu.ColorMenu({
-                        allowReselect: true,
-                        focus: Ext.emptyFn,
-                        value:'000000',
-                        plain:true,
-                        listeners: {
-                            scope: this,
-                            select: function(cp, color){
-                                this.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
-                                this.deferFocus();
-                            }
-                        },
-                        clickEvent:'mousedown'
-                    })
-                }, {
-                    itemId:'backcolor',
-                    cls:'x-btn-icon',
-                    iconCls: 'x-edit-backcolor',
-                    clickEvent:'mousedown',
-                    tooltip: tipsEnabled ? editor.buttonTips.backcolor || undefined : undefined,
-                    tabIndex:-1,
-                    menu : new Ext.menu.ColorMenu({
-                        focus: Ext.emptyFn,
-                        value:'FFFFFF',
-                        plain:true,
-                        allowReselect: true,
-                        listeners: {
-                            scope: this,
-                            select: function(cp, color){
-                                if(Ext.isGecko){
-                                    this.execCmd('useCSS', false);
-                                    this.execCmd('hilitecolor', color);
-                                    this.execCmd('useCSS', true);
-                                    this.deferFocus();
-                                }else{
-                                    this.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
-                                    this.deferFocus();
-                                }
-                            }
-                        },
-                        clickEvent:'mousedown'
-                    })
-                }
-            );
+        if (me.disabled) {
+            return;
         }
 
-        if(this.enableAlignments){
-            items.push(
-                '-',
-                btn('justifyleft'),
-                btn('justifycenter'),
-                btn('justifyright')
-            );
+        if (me.hideOnClick) {
+            me.deferHideParentMenusTimer = Ext.defer(me.deferHideParentMenus, me.clickHideDelay, me);
         }
 
-        if(!Ext.isSafari2){
-            if(this.enableLinks){
-                items.push(
-                    '-',
-                    btn('createlink', false, this.createLink)
-                );
-            }
+        Ext.callback(me.handler, me.scope || me, [me, e]);
+        me.fireEvent('click', me, e);
 
-            if(this.enableLists){
-                items.push(
-                    '-',
-                    btn('insertorderedlist'),
-                    btn('insertunorderedlist')
-                );
-            }
-            if(this.enableSourceEdit){
-                items.push(
-                    '-',
-                    btn('sourceedit', true, function(btn){
-                        this.toggleSourceEdit(!this.sourceEditMode);
-                    })
-                );
-            }
+        if (!me.hideOnClick) {
+            me.focus();
         }
+    },
 
-        
-        var tb = new Ext.Toolbar({
-            renderTo: this.wrap.dom.firstChild,
-            items: items
-        });
+    onDestroy: function() {
+        var me = this;
 
-        if (fontSelectItem) {
-            this.fontSelect = fontSelectItem.el;
+        clearTimeout(me.expandMenuTimer);
+        clearTimeout(me.hideMenuTimer);
+        clearTimeout(me.deferHideParentMenusTimer);
 
-            this.mon(this.fontSelect, 'change', function(){
-                var font = this.fontSelect.dom.value;
-                this.relayCmd('fontname', font);
-                this.deferFocus();
-            }, this);
+        if (me.menu) {
+            delete me.menu.parentItem;
+            delete me.menu.parentMenu;
+            delete me.menu.ownerCt;
+            if (me.destroyMenu !== false) {
+                me.menu.destroy();
+            }
         }
+        me.callParent(arguments);
+    },
 
-        
-        this.mon(tb.el, 'click', function(e){
-            e.preventDefault();
+    onRender: function(ct, pos) {
+        var me = this,
+            blank = Ext.BLANK_IMAGE_URL;
+
+        Ext.applyIf(me.renderData, {
+            href: me.href || '#',
+            hrefTarget: me.hrefTarget,
+            icon: me.icon || blank,
+            iconCls: me.iconCls + (me.checkChangeDisabled ? ' ' + me.disabledCls : ''),
+            menu: Ext.isDefined(me.menu),
+            plain: me.plain,
+            text: me.text,
+            blank: blank
         });
 
-        this.tb = tb;
-        this.tb.doLayout();
-    },
+        me.addChildEls('itemEl', 'iconEl', 'textEl', 'arrowEl');
 
-    onDisable: function(){
-        this.wrap.mask();
-        Ext.form.HtmlEditor.superclass.onDisable.call(this);
+        me.callParent(arguments);
     },
 
-    onEnable: function(){
-        this.wrap.unmask();
-        Ext.form.HtmlEditor.superclass.onEnable.call(this);
+    
+    setHandler: function(fn, scope) {
+        this.handler = fn || null;
+        this.scope = scope;
     },
 
-    setReadOnly: function(readOnly){
+    
+    setIconCls: function(iconCls) {
+        var me = this;
 
-        Ext.form.HtmlEditor.superclass.setReadOnly.call(this, readOnly);
-        if(this.initialized){
-            if(Ext.isIE){
-                this.getEditorBody().contentEditable = !readOnly;
-            }else{
-                this.setDesignMode(!readOnly);
+        if (me.iconEl) {
+            if (me.iconCls) {
+                me.iconEl.removeCls(me.iconCls);
             }
-            var bd = this.getEditorBody();
-            if(bd){
-                bd.style.cursor = this.readOnly ? 'default' : 'text';
+
+            if (iconCls) {
+                me.iconEl.addCls(iconCls);
             }
-            this.disableItems(readOnly);
         }
-    },
 
-    
-    getDocMarkup : function(){
-        var h = Ext.fly(this.iframe).getHeight() - this.iframePad * 2;
-        return String.format('<html><head><style type="text/css">body{border: 0; margin: 0; padding: {0}px; height: {1}px; cursor: text}</style></head><body></body></html>', this.iframePad, h);
+        me.iconCls = iconCls;
     },
 
     
-    getEditorBody : function(){
-        var doc = this.getDoc();
-        return doc.body || doc.documentElement;
-    },
+    setText: function(text) {
+        var me = this,
+            el = me.textEl || me.el;
+
+        me.text = text;
+
+        if (me.rendered) {
+            el.update(text || '');
+            
+            me.ownerCt.redoComponentLayout();
+        }
+    }
+});
 
-    
-    getDoc : function(){
-        return Ext.isIE ? this.getWin().document : (this.iframe.contentDocument || this.getWin().document);
-    },
+
+Ext.define('Ext.menu.CheckItem', {
+    extend: 'Ext.menu.Item',
+    alias: 'widget.menucheckitem',
 
     
-    getWin : function(){
-        return Ext.isIE ? this.iframe.contentWindow : window.frames[this.iframe.name];
-    },
+    checkedCls: Ext.baseCSSPrefix + 'menu-item-checked',
+    
+    uncheckedCls: Ext.baseCSSPrefix + 'menu-item-unchecked',
+    
+    groupCls: Ext.baseCSSPrefix + 'menu-group-icon',
 
     
-    onRender : function(ct, position){
-        Ext.form.HtmlEditor.superclass.onRender.call(this, ct, position);
-        this.el.dom.style.border = '0 none';
-        this.el.dom.setAttribute('tabIndex', -1);
-        this.el.addClass('x-hidden');
-        if(Ext.isIE){ 
-            this.el.applyStyles('margin-top:-1px;margin-bottom:-1px;');
-        }
-        this.wrap = this.el.wrap({
-            cls:'x-html-editor-wrap', cn:{cls:'x-html-editor-tb'}
-        });
+    hideOnClick: false,
+
+    afterRender: function() {
+        var me = this;
+        this.callParent();
+        me.checked = !me.checked;
+        me.setChecked(!me.checked, true);
+    },
 
-        this.createToolbar(this);
+    initComponent: function() {
+        var me = this;
+        me.addEvents(
+            
+            'beforecheckchange',
 
-        this.disableItems(true);
+            
+            'checkchange'
+        );
 
-        this.tb.doLayout();
+        me.callParent(arguments);
 
-        this.createIFrame();
+        Ext.menu.Manager.registerCheckable(me);
 
-        if(!this.width){
-            var sz = this.el.getSize();
-            this.setSize(sz.width, this.height || sz.height);
+        if (me.group) {
+            if (!me.iconCls) {
+                me.iconCls = me.groupCls;
+            }
+            if (me.initialConfig.hideOnClick !== false) {
+                me.hideOnClick = true;
+            }
         }
-        this.resizeEl = this.positionEl = this.wrap;
     },
 
-    createIFrame: function(){
-        var iframe = document.createElement('iframe');
-        iframe.name = Ext.id();
-        iframe.frameBorder = '0';
-        iframe.style.overflow = 'auto';
-
-        this.wrap.dom.appendChild(iframe);
-        this.iframe = iframe;
+    
+    disableCheckChange: function() {
+        var me = this;
 
-        this.monitorTask = Ext.TaskMgr.start({
-            run: this.checkDesignMode,
-            scope: this,
-            interval:100
-        });
+        if (me.iconEl) {
+            me.iconEl.addCls(me.disabledCls);
+        }
+        me.checkChangeDisabled = true;
     },
 
-    initFrame : function(){
-        Ext.TaskMgr.stop(this.monitorTask);
-        var doc = this.getDoc();
-        this.win = this.getWin();
+    
+    enableCheckChange: function() {
+        var me = this;
 
-        doc.open();
-        doc.write(this.getDocMarkup());
-        doc.close();
+        me.iconEl.removeCls(me.disabledCls);
+        me.checkChangeDisabled = false;
+    },
 
-        var task = { 
-            run : function(){
-                var doc = this.getDoc();
-                if(doc.body || doc.readyState == 'complete'){
-                    Ext.TaskMgr.stop(task);
-                    this.setDesignMode(true);
-                    this.initEditor.defer(10, this);
-                }
-            },
-            interval : 10,
-            duration:10000,
-            scope: this
-        };
-        Ext.TaskMgr.start(task);
+    onClick: function(e) {
+        var me = this;
+        if(!me.disabled && !me.checkChangeDisabled && !(me.checked && me.group)) {
+            me.setChecked(!me.checked);
+        }
+        this.callParent([e]);
     },
 
+    onDestroy: function() {
+        Ext.menu.Manager.unregisterCheckable(this);
+        this.callParent(arguments);
+    },
 
-    checkDesignMode : function(){
-        if(this.wrap && this.wrap.dom.offsetWidth){
-            var doc = this.getDoc();
-            if(!doc){
-                return;
+    
+    setChecked: function(checked, suppressEvents) {
+        var me = this;
+        if (me.checked !== checked && (suppressEvents || me.fireEvent('beforecheckchange', me, checked) !== false)) {
+            if (me.el) {
+                me.el[checked  ? 'addCls' : 'removeCls'](me.checkedCls)[!checked ? 'addCls' : 'removeCls'](me.uncheckedCls);
             }
-            if(!doc.editorInitialized || this.getDesignMode() != 'on'){
-                this.initFrame();
+            me.checked = checked;
+            Ext.menu.Manager.onCheckChange(me, checked);
+            if (!suppressEvents) {
+                Ext.callback(me.checkHandler, me.scope, [me, checked]);
+                me.fireEvent('checkchange', me, checked);
             }
         }
-    },
+    }
+});
 
+
+Ext.define('Ext.menu.KeyNav', {
+    extend: 'Ext.util.KeyNav',
+
+    requires: ['Ext.FocusManager'],
     
-    setDesignMode : function(mode){
-        var doc ;
-        if(doc = this.getDoc()){
-            if(this.readOnly){
-                mode = false;
-            }
-            doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
-        }
+    constructor: function(menu) {
+        var me = this;
 
+        me.menu = menu;
+        me.callParent([menu.el, {
+            down: me.down,
+            enter: me.enter,
+            esc: me.escape,
+            left: me.left,
+            right: me.right,
+            space: me.enter,
+            tab: me.tab,
+            up: me.up
+        }]);
     },
 
-    
-    getDesignMode : function(){
-        var doc = this.getDoc();
-        if(!doc){ return ''; }
-        return String(doc.designMode).toLowerCase();
+    down: function(e) {
+        var me = this,
+            fi = me.menu.focusedItem;
 
+        if (fi && e.getKey() == Ext.EventObject.DOWN && me.isWhitelisted(fi)) {
+            return true;
+        }
+        me.focusNextItem(1);
     },
 
-    disableItems: function(disabled){
-        if(this.fontSelect){
-            this.fontSelect.dom.disabled = disabled;
+    enter: function(e) {
+        var menu = this.menu,
+            focused = menu.focusedItem;
+        if (menu.activeItem) {
+            menu.onClick(e);
+        } else if (focused && focused.isFormField) {
+            
+            return true;
         }
-        this.tb.items.each(function(item){
-            if(item.getItemId() != 'sourceedit'){
-                item.setDisabled(disabled);
-            }
-        });
     },
 
-    
-    onResize : function(w, h){
-        Ext.form.HtmlEditor.superclass.onResize.apply(this, arguments);
-        if(this.el && this.iframe){
-            if(Ext.isNumber(w)){
-                var aw = w - this.wrap.getFrameWidth('lr');
-                this.el.setWidth(aw);
-                this.tb.setWidth(aw);
-                this.iframe.style.width = Math.max(aw, 0) + 'px';
+    escape: function(e) {
+        Ext.menu.Manager.hideAll();
+    },
+
+    focusNextItem: function(step) {
+        var menu = this.menu,
+            items = menu.items,
+            focusedItem = menu.focusedItem,
+            startIdx = focusedItem ? items.indexOf(focusedItem) : -1,
+            idx = startIdx + step;
+
+        while (idx != startIdx) {
+            if (idx < 0) {
+                idx = items.length - 1;
+            } else if (idx >= items.length) {
+                idx = 0;
             }
-            if(Ext.isNumber(h)){
-                var ah = h - this.wrap.getFrameWidth('tb') - this.tb.el.getHeight();
-                this.el.setHeight(ah);
-                this.iframe.style.height = Math.max(ah, 0) + 'px';
-                var bd = this.getEditorBody();
-                if(bd){
-                    bd.style.height = Math.max((ah - (this.iframePad*2)), 0) + 'px';
-                }
+
+            var item = items.getAt(idx);
+            if (menu.canActivateItem(item)) {
+                menu.setActiveItem(item);
+                break;
             }
+            idx += step;
         }
     },
 
-    
-    toggleSourceEdit : function(sourceEditMode){
-        var iframeHeight,
-            elHeight;
+    isWhitelisted: function(item) {
+        return Ext.FocusManager.isWhitelisted(item);
+    },
+
+    left: function(e) {
+        var menu = this.menu,
+            fi = menu.focusedItem,
+            ai = menu.activeItem;
 
-        if (sourceEditMode === undefined) {
-            sourceEditMode = !this.sourceEditMode;
+        if (fi && this.isWhitelisted(fi)) {
+            return true;
         }
-        this.sourceEditMode = sourceEditMode === true;
-        var btn = this.tb.getComponent('sourceedit');
 
-        if (btn.pressed !== this.sourceEditMode) {
-            btn.toggle(this.sourceEditMode);
-            if (!btn.xtbHidden) {
-                return;
-            }
+        menu.hide();
+        if (menu.parentMenu) {
+            menu.parentMenu.focus();
         }
-        if (this.sourceEditMode) {
-            
-            this.previousSize = this.getSize();
+    },
 
-            iframeHeight = Ext.get(this.iframe).getHeight();
+    right: function(e) {
+        var menu = this.menu,
+            fi = menu.focusedItem,
+            ai = menu.activeItem,
+            am;
 
-            this.disableItems(true);
-            this.syncValue();
-            this.iframe.className = 'x-hidden';
-            this.el.removeClass('x-hidden');
-            this.el.dom.removeAttribute('tabIndex');
-            this.el.focus();
-            this.el.dom.style.height = iframeHeight + 'px';
+        if (fi && this.isWhitelisted(fi)) {
+            return true;
         }
-        else {
-            elHeight = parseInt(this.el.dom.style.height, 10);
-            if (this.initialized) {
-                this.disableItems(this.readOnly);
-            }
-            this.pushValue();
-            this.iframe.className = '';
-            this.el.addClass('x-hidden');
-            this.el.dom.setAttribute('tabIndex', -1);
-            this.deferFocus();
 
-            this.setSize(this.previousSize);
-            delete this.previousSize;
-            this.iframe.style.height = elHeight + 'px';
+        if (ai) {
+            am = menu.activeItem.menu;
+            if (am) {
+                ai.expandMenu(0);
+                Ext.defer(function() {
+                    am.setActiveItem(am.items.getAt(0));
+                }, 25);
+            }
         }
-        this.fireEvent('editmodechange', this, this.sourceEditMode);
     },
 
-    
-    createLink : function() {
-        var url = prompt(this.createLinkText, this.defaultLinkValue);
-        if(url && url != 'http:/'+'/'){
-            this.relayCmd('createlink', url);
+    tab: function(e) {
+        var me = this;
+
+        if (e.shiftKey) {
+            me.up(e);
+        } else {
+            me.down(e);
         }
     },
 
+    up: function(e) {
+        var me = this,
+            fi = me.menu.focusedItem;
+
+        if (fi && e.getKey() == Ext.EventObject.UP && me.isWhitelisted(fi)) {
+            return true;
+        }
+        me.focusNextItem(-1);
+    }
+});
+
+Ext.define('Ext.menu.Separator', {
+    extend: 'Ext.menu.Item',
+    alias: 'widget.menuseparator',
+
     
-    initEvents : function(){
-        this.originalValue = this.getValue();
-    },
 
     
-    markInvalid : Ext.emptyFn,
+    canActivate: false,
 
     
-    clearInvalid : Ext.emptyFn,
 
     
-    setValue : function(v){
-        Ext.form.HtmlEditor.superclass.setValue.call(this, v);
-        this.pushValue();
-        return this;
-    },
 
     
-    cleanHtml: function(html) {
-        html = String(html);
-        if(Ext.isWebKit){ 
-            html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
-        }
 
-        
-        if(html.charCodeAt(0) == this.defaultValue.replace(/\D/g, '')){
-            html = html.substring(1);
-        }
-        return html;
-    },
+    focusable: false,
 
     
-    syncValue : function(){
-        if(this.initialized){
-            var bd = this.getEditorBody();
-            var html = bd.innerHTML;
-            if(Ext.isWebKit){
-                var bs = bd.getAttribute('style'); 
-                var m = bs.match(/text-align:(.*?);/i);
-                if(m && m[1]){
-                    html = '<div style="'+m[0]+'">' + html + '</div>';
-                }
-            }
-            html = this.cleanHtml(html);
-            if(this.fireEvent('beforesync', this, html) !== false){
-                this.el.dom.value = html;
-                this.fireEvent('sync', this, html);
-            }
-        }
-    },
 
     
-    getValue : function() {
-        this[this.sourceEditMode ? 'pushValue' : 'syncValue']();
-        return Ext.form.HtmlEditor.superclass.getValue.call(this);
-    },
 
     
-    pushValue : function(){
-        if(this.initialized){
-            var v = this.el.dom.value;
-            if(!this.activated && v.length < 1){
-                v = this.defaultValue;
-            }
-            if(this.fireEvent('beforepush', this, v) !== false){
-                this.getEditorBody().innerHTML = v;
-                if(Ext.isGecko){
-                    
-                    this.setDesignMode(false);  
-                    this.setDesignMode(true);
-                }
-                this.fireEvent('push', this, v);
-            }
+    hideOnClick: false,
 
-        }
-    },
+    
 
     
-    deferFocus : function(){
-        this.focus.defer(10, this);
-    },
 
     
-    focus : function(){
-        if(this.win && !this.sourceEditMode){
-            this.win.focus();
-        }else{
-            this.el.focus();
-        }
-    },
 
     
-    initEditor : function(){
-        
-        try{
-            var dbody = this.getEditorBody(),
-                ss = this.el.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
-                doc,
-                fn;
 
-            ss['background-attachment'] = 'fixed'; 
-            dbody.bgProperties = 'fixed'; 
+    
 
-            Ext.DomHelper.applyStyles(dbody, ss);
+    
 
-            doc = this.getDoc();
+    
+    plain: true,
 
-            if(doc){
-                try{
-                    Ext.EventManager.removeAll(doc);
-                }catch(e){}
-            }
+    
+    separatorCls: Ext.baseCSSPrefix + 'menu-item-separator',
 
-            
-            fn = this.onEditorEvent.createDelegate(this);
-            Ext.EventManager.on(doc, {
-                mousedown: fn,
-                dblclick: fn,
-                click: fn,
-                keyup: fn,
-                buffer:100
-            });
+    
+    text: '&#160;',
 
-            if(Ext.isGecko){
-                Ext.EventManager.on(doc, 'keypress', this.applyCommand, this);
-            }
-            if(Ext.isIE || Ext.isWebKit || Ext.isOpera){
-                Ext.EventManager.on(doc, 'keydown', this.fixKeys, this);
-            }
-            doc.editorInitialized = true;
-            this.initialized = true;
-            this.pushValue();
-            this.setReadOnly(this.readOnly);
-            this.fireEvent('initialize', this);
-        }catch(e){}
-    },
+    onRender: function(ct, pos) {
+        var me = this,
+            sepCls = me.separatorCls;
+
+        me.cls += ' ' + sepCls;
+
+        me.callParent(arguments);
+    }
+});
+
+Ext.define('Ext.menu.Menu', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.menu',
+    requires: [
+        'Ext.layout.container.Fit',
+        'Ext.layout.container.VBox',
+        'Ext.menu.CheckItem',
+        'Ext.menu.Item',
+        'Ext.menu.KeyNav',
+        'Ext.menu.Manager',
+        'Ext.menu.Separator'
+    ],
 
     
-    onDestroy : function(){
-        if(this.monitorTask){
-            Ext.TaskMgr.stop(this.monitorTask);
-        }
-        if(this.rendered){
-            Ext.destroy(this.tb);
-            var doc = this.getDoc();
-            if(doc){
-                try{
-                    Ext.EventManager.removeAll(doc);
-                    for (var prop in doc){
-                        delete doc[prop];
-                    }
-                }catch(e){}
-            }
-            if(this.wrap){
-                this.wrap.dom.innerHTML = '';
-                this.wrap.remove();
-            }
-        }
 
-        if(this.el){
-            this.el.removeAllListeners();
-            this.el.remove();
-        }
-        this.purgeListeners();
-    },
+    
+    allowOtherMenus: false,
 
     
-    onFirstFocus : function(){
-        this.activated = true;
-        this.disableItems(this.readOnly);
-        if(Ext.isGecko){ 
-            this.win.focus();
-            var s = this.win.getSelection();
-            if(!s.focusNode || s.focusNode.nodeType != 3){
-                var r = s.getRangeAt(0);
-                r.selectNodeContents(this.getEditorBody());
-                r.collapse(true);
-                this.deferFocus();
-            }
-            try{
-                this.execCmd('useCSS', true);
-                this.execCmd('styleWithCSS', false);
-            }catch(e){}
-        }
-        this.fireEvent('activate', this);
-    },
+    ariaRole: 'menu',
 
     
-    adjustFont: function(btn){
-        var adjust = btn.getItemId() == 'increasefontsize' ? 1 : -1,
-            doc = this.getDoc(),
-            v = parseInt(doc.queryCommandValue('FontSize') || 2, 10);
-        if((Ext.isSafari && !Ext.isSafari2) || Ext.isChrome || Ext.isAir){
-            
-            
-            if(v <= 10){
-                v = 1 + adjust;
-            }else if(v <= 13){
-                v = 2 + adjust;
-            }else if(v <= 16){
-                v = 3 + adjust;
-            }else if(v <= 18){
-                v = 4 + adjust;
-            }else if(v <= 24){
-                v = 5 + adjust;
-            }else {
-                v = 6 + adjust;
-            }
-            v = v.constrain(1, 6);
-        }else{
-            if(Ext.isSafari){ 
-                adjust *= 2;
-            }
-            v = Math.max(1, v+adjust) + (Ext.isSafari ? 'px' : 0);
-        }
-        this.execCmd('FontSize', v);
-    },
 
     
-    onEditorEvent : function(e){
-        this.updateToolbar();
-    },
+    defaultAlign: 'tl-bl?',
 
+    
+    floating: true,
 
     
-    updateToolbar: function(){
+    constrain: true,
 
-        if(this.readOnly){
-            return;
+    
+    hidden: true,
+
+    hideMode: 'visibility',
+
+    
+    ignoreParentClicks: false,
+
+    isMenu: true,
+
+    
+
+    
+    showSeparator : true,
+
+    
+    minWidth: 120,
+
+    
+
+    initComponent: function() {
+        var me = this,
+            prefix = Ext.baseCSSPrefix,
+            cls = [prefix + 'menu'],
+            bodyCls = me.bodyCls ? [me.bodyCls] : [];
+
+        me.addEvents(
+            
+            'click',
+
+            
+            'mouseenter',
+
+            
+            'mouseleave',
+
+            
+            'mouseover'
+        );
+
+        Ext.menu.Manager.register(me);
+
+        
+        if (me.plain) {
+            cls.push(prefix + 'menu-plain');
         }
+        me.cls = cls.join(' ');
 
-        if(!this.activated){
-            this.onFirstFocus();
-            return;
+        
+        bodyCls.unshift(prefix + 'menu-body');
+        me.bodyCls = bodyCls.join(' ');
+
+        
+        
+        
+        
+        me.layout = {
+            type: 'vbox',
+            align: 'stretchmax',
+            autoSize: true,
+            clearInnerCtOnLayout: true,
+            overflowHandler: 'Scroller'
+        };
+
+        
+        if (me.floating === false && me.initialConfig.hidden !== true) {
+            me.hidden = false;
         }
 
-        var btns = this.tb.items.map,
-            doc = this.getDoc();
+        me.callParent(arguments);
 
-        if(this.enableFont && !Ext.isSafari2){
-            var name = (doc.queryCommandValue('FontName')||this.defaultFont).toLowerCase();
-            if(name != this.fontSelect.dom.value){
-                this.fontSelect.dom.value = name;
+        me.on('beforeshow', function() {
+            var hasItems = !!me.items.length;
+            
+            
+            
+            if (hasItems && me.rendered) {
+                me.el.setStyle('visibility', null);
             }
-        }
-        if(this.enableFormat){
-            btns.bold.toggle(doc.queryCommandState('bold'));
-            btns.italic.toggle(doc.queryCommandState('italic'));
-            btns.underline.toggle(doc.queryCommandState('underline'));
-        }
-        if(this.enableAlignments){
-            btns.justifyleft.toggle(doc.queryCommandState('justifyleft'));
-            btns.justifycenter.toggle(doc.queryCommandState('justifycenter'));
-            btns.justifyright.toggle(doc.queryCommandState('justifyright'));
-        }
-        if(!Ext.isSafari2 && this.enableLists){
-            btns.insertorderedlist.toggle(doc.queryCommandState('insertorderedlist'));
-            btns.insertunorderedlist.toggle(doc.queryCommandState('insertunorderedlist'));
+            return hasItems;
+        });
+    },
+
+    afterRender: function(ct) {
+        var me = this,
+            prefix = Ext.baseCSSPrefix,
+            space = '&#160;';
+
+        me.callParent(arguments);
+
+        
+        if (me.showSeparator) {
+            me.iconSepEl = me.layout.getRenderTarget().insertFirst({
+                cls: prefix + 'menu-icon-separator',
+                html: space
+            });
         }
 
-        Ext.menu.MenuMgr.hideAll();
+        me.focusEl = me.el.createChild({
+            cls: prefix + 'menu-focus',
+            tabIndex: '-1',
+            html: space
+        });
 
-        this.syncValue();
-    },
+        me.mon(me.el, {
+            click: me.onClick,
+            mouseover: me.onMouseOver,
+            scope: me
+        });
+        me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me);
 
-    
-    relayBtnCmd : function(btn){
-        this.relayCmd(btn.getItemId());
+        if (me.showSeparator && ((!Ext.isStrict && Ext.isIE) || Ext.isIE6)) {
+            me.iconSepEl.setHeight(me.el.getHeight());
+        }
+
+        me.keyNav = Ext.create('Ext.menu.KeyNav', me);
     },
 
+    afterLayout: function() {
+        var me = this;
+        me.callParent(arguments);
+
+        
+        
+        
+        
+        if ((!Ext.isStrict && Ext.isIE) || Ext.isIE6) {
+            var innerCt = me.layout.getRenderTarget(),
+                innerCtWidth = 0,
+                dis = me.dockedItems,
+                l = dis.length,
+                i = 0,
+                di, clone, newWidth;
+
+            innerCtWidth = innerCt.getWidth();
+
+            newWidth = innerCtWidth + me.body.getBorderWidth('lr') + me.body.getPadding('lr');
+
+            
+            me.body.setWidth(newWidth);
+
+            
+            for (; i < l, di = dis.getAt(i); i++) {
+                if (di.dock == 'left' || di.dock == 'right') {
+                    newWidth += di.getWidth();
+                }
+            }
+            me.el.setWidth(newWidth);
+        }
+    },
     
-    relayCmd : function(cmd, value){
-        (function(){
-            this.focus();
-            this.execCmd(cmd, value);
-            this.updateToolbar();
-        }).defer(10, this);
+    getBubbleTarget: function(){
+        return this.parentMenu || this.callParent();
     },
 
     
-    execCmd : function(cmd, value){
-        var doc = this.getDoc();
-        doc.execCommand(cmd, false, value === undefined ? null : value);
-        this.syncValue();
+    canActivateItem: function(item) {
+        return item && !item.isDisabled() && item.isVisible() && (item.canActivate || item.getXTypes().indexOf('menuitem') < 0);
     },
 
     
-    applyCommand : function(e){
-        if(e.ctrlKey){
-            var c = e.getCharCode(), cmd;
-            if(c > 0){
-                c = String.fromCharCode(c);
-                switch(c){
-                    case 'b':
-                        cmd = 'bold';
-                    break;
-                    case 'i':
-                        cmd = 'italic';
-                    break;
-                    case 'u':
-                        cmd = 'underline';
-                    break;
-                }
-                if(cmd){
-                    this.win.focus();
-                    this.execCmd(cmd);
-                    this.deferFocus();
-                    e.preventDefault();
-                }
+    deactivateActiveItem: function() {
+        var me = this;
+
+        if (me.activeItem) {
+            me.activeItem.deactivate();
+            if (!me.activeItem.activated) {
+                delete me.activeItem;
             }
         }
-    },
 
-    
-    insertAtCursor : function(text){
-        if(!this.activated){
-            return;
-        }
-        if(Ext.isIE){
-            this.win.focus();
-            var doc = this.getDoc(),
-                r = doc.selection.createRange();
-            if(r){
-                r.pasteHTML(text);
-                this.syncValue();
-                this.deferFocus();
+        
+        if (me.focusedItem && !me.filtered) {
+            me.focusedItem.blur();
+            if (!me.focusedItem.$focused) {
+                delete me.focusedItem;
             }
-        }else{
-            this.win.focus();
-            this.execCmd('InsertHTML', text);
-            this.deferFocus();
         }
     },
 
-    
-    fixKeys : function(){ 
-        if(Ext.isIE){
-            return function(e){
-                var k = e.getKey(),
-                    doc = this.getDoc(),
-                        r;
-                if(k == e.TAB){
-                    e.stopEvent();
-                    r = doc.selection.createRange();
-                    if(r){
-                        r.collapse(true);
-                        r.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
-                        this.deferFocus();
-                    }
-                }else if(k == e.ENTER){
-                    r = doc.selection.createRange();
-                    if(r){
-                        var target = r.parentElement();
-                        if(!target || target.tagName.toLowerCase() != 'li'){
-                            e.stopEvent();
-                            r.pasteHTML('<br />');
-                            r.collapse(false);
-                            r.select();
-                        }
-                    }
-                }
-            };
-        }else if(Ext.isOpera){
-            return function(e){
-                var k = e.getKey();
-                if(k == e.TAB){
-                    e.stopEvent();
-                    this.win.focus();
-                    this.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
-                    this.deferFocus();
+    clearStretch: function () {
+        
+        
+        if (this.rendered) {
+            this.items.each(function (item) {
+                
+                if (item.componentLayout) {
+                    delete item.componentLayout.lastComponentSize;
                 }
-            };
-        }else if(Ext.isWebKit){
-            return function(e){
-                var k = e.getKey();
-                if(k == e.TAB){
-                    e.stopEvent();
-                    this.execCmd('InsertText','\t');
-                    this.deferFocus();
-                }else if(k == e.ENTER){
-                    e.stopEvent();
-                    this.execCmd('InsertHtml','<br /><br />');
-                    this.deferFocus();
+                if (item.el) {
+                    item.el.setWidth(null);
                 }
-             };
+            });
         }
-    }(),
+    },
 
-    
-    getToolbar : function(){
-        return this.tb;
+    onAdd: function () {
+        var me = this;
+
+        me.clearStretch();
+        me.callParent(arguments);
+
+        if (Ext.isIE6 || Ext.isIE7) {
+            
+            Ext.Function.defer(me.doComponentLayout, 10, me);
+        }
     },
 
-    
-    buttonTips : {
-        bold : {
-            title: 'Bold (Ctrl+B)',
-            text: 'Make the selected text bold.',
-            cls: 'x-html-editor-tip'
-        },
-        italic : {
-            title: 'Italic (Ctrl+I)',
-            text: 'Make the selected text italic.',
-            cls: 'x-html-editor-tip'
-        },
-        underline : {
-            title: 'Underline (Ctrl+U)',
-            text: 'Underline the selected text.',
-            cls: 'x-html-editor-tip'
-        },
-        increasefontsize : {
-            title: 'Grow Text',
-            text: 'Increase the font size.',
-            cls: 'x-html-editor-tip'
-        },
-        decreasefontsize : {
-            title: 'Shrink Text',
-            text: 'Decrease the font size.',
-            cls: 'x-html-editor-tip'
-        },
-        backcolor : {
-            title: 'Text Highlight Color',
-            text: 'Change the background color of the selected text.',
-            cls: 'x-html-editor-tip'
-        },
-        forecolor : {
-            title: 'Font Color',
-            text: 'Change the color of the selected text.',
-            cls: 'x-html-editor-tip'
-        },
-        justifyleft : {
-            title: 'Align Text Left',
-            text: 'Align text to the left.',
-            cls: 'x-html-editor-tip'
-        },
-        justifycenter : {
-            title: 'Center Text',
-            text: 'Center text in the editor.',
-            cls: 'x-html-editor-tip'
-        },
-        justifyright : {
-            title: 'Align Text Right',
-            text: 'Align text to the right.',
-            cls: 'x-html-editor-tip'
-        },
-        insertunorderedlist : {
-            title: 'Bullet List',
-            text: 'Start a bulleted list.',
-            cls: 'x-html-editor-tip'
-        },
-        insertorderedlist : {
-            title: 'Numbered List',
-            text: 'Start a numbered list.',
-            cls: 'x-html-editor-tip'
-        },
-        createlink : {
-            title: 'Hyperlink',
-            text: 'Make the selected text a hyperlink.',
-            cls: 'x-html-editor-tip'
-        },
-        sourceedit : {
-            title: 'Source Edit',
-            text: 'Switch to source editing mode.',
-            cls: 'x-html-editor-tip'
+    onRemove: function () {
+        this.clearStretch();
+        this.callParent(arguments);
+
+    },
+
+    redoComponentLayout: function () {
+        if (this.rendered) {
+            this.clearStretch();
+            this.doComponentLayout();
         }
-    }
+    },
 
     
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-});
-Ext.reg('htmleditor', Ext.form.HtmlEditor);
+    getFocusEl: function() {
+        return this.focusEl;
+    },
 
-Ext.form.TimeField = Ext.extend(Ext.form.ComboBox, {
-    
-    minValue : undefined,
-    
-    maxValue : undefined,
-    
-    minText : "The time in this field must be equal to or after {0}",
-    
-    maxText : "The time in this field must be equal to or before {0}",
-    
-    invalidText : "{0} is not a valid time",
-    
-    format : "g:i A",
-    
-    altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",
     
-    increment: 15,
+    hide: function() {
+        this.deactivateActiveItem();
+        this.callParent(arguments);
+    },
 
     
-    mode: 'local',
-    
-    triggerAction: 'all',
-    
-    typeAhead: false,
+    getItemFromEvent: function(e) {
+        return this.getChildByElement(e.getTarget());
+    },
 
-    
-    
-    
-    initDate: '1/1/2008',
+    lookupComponent: function(cmp) {
+        var me = this;
 
-    initDateFormat: 'j/n/Y',
+        if (Ext.isString(cmp)) {
+            cmp = me.lookupItemFromString(cmp);
+        } else if (Ext.isObject(cmp)) {
+            cmp = me.lookupItemFromObject(cmp);
+        }
+
+        
+        
+        cmp.minWidth = cmp.minWidth || me.minWidth;
+
+        return cmp;
+    },
 
     
-    initComponent : function(){
-        if(Ext.isDefined(this.minValue)){
-            this.setMinValue(this.minValue, true);
-        }
-        if(Ext.isDefined(this.maxValue)){
-            this.setMaxValue(this.maxValue, true);
+    lookupItemFromObject: function(cmp) {
+        var me = this,
+            prefix = Ext.baseCSSPrefix,
+            cls,
+            intercept;
+
+        if (!cmp.isComponent) {
+            if (!cmp.xtype) {
+                cmp = Ext.create('Ext.menu.' + (Ext.isBoolean(cmp.checked) ? 'Check': '') + 'Item', cmp);
+            } else {
+                cmp = Ext.ComponentManager.create(cmp, cmp.xtype);
+            }
         }
-        if(!this.store){
-            this.generateStore(true);
+
+        if (cmp.isMenuItem) {
+            cmp.parentMenu = me;
         }
-        Ext.form.TimeField.superclass.initComponent.call(this);
-    },
 
-    
-    setMinValue: function(value,  initial){
-        this.setLimit(value, true, initial);
-        return this;
+        if (!cmp.isMenuItem && !cmp.dock) {
+            cls = [prefix + 'menu-item', prefix + 'menu-item-cmp'];
+            intercept = Ext.Function.createInterceptor;
+
+            
+            cmp.focus = intercept(cmp.focus, function() {
+                this.$focused = true;
+            }, cmp);
+            cmp.blur = intercept(cmp.blur, function() {
+                this.$focused = false;
+            }, cmp);
+
+            if (!me.plain && (cmp.indent === true || cmp.iconCls === 'no-icon')) {
+                cls.push(prefix + 'menu-item-indent');
+            }
+
+            if (cmp.rendered) {
+                cmp.el.addCls(cls);
+            } else {
+                cmp.cls = (cmp.cls ? cmp.cls : '') + ' ' + cls.join(' ');
+            }
+            cmp.isMenuItem = true;
+        }
+        return cmp;
     },
 
     
-    setMaxValue: function(value,  initial){
-        this.setLimit(value, false, initial);
-        return this;
+    lookupItemFromString: function(cmp) {
+        return (cmp == 'separator' || cmp == '-') ?
+            Ext.createWidget('menuseparator')
+            : Ext.createWidget('menuitem', {
+                canActivate: false,
+                hideOnClick: false,
+                plain: true,
+                text: cmp
+            });
     },
 
-    
-    generateStore: function(initial){
-        var min = this.minValue || new Date(this.initDate).clearTime(),
-            max = this.maxValue || new Date(this.initDate).clearTime().add('mi', (24 * 60) - 1),
-            times = [];
+    onClick: function(e) {
+        var me = this,
+            item;
 
-        while(min <= max){
-            times.push(min.dateFormat(this.format));
-            min = min.add('mi', this.increment);
+        if (me.disabled) {
+            e.stopEvent();
+            return;
         }
-        this.bindStore(times, initial);
-    },
 
-    
-    setLimit: function(value, isMin, initial){
-        var d;
-        if(Ext.isString(value)){
-            d = this.parseDate(value);
-        }else if(Ext.isDate(value)){
-            d = value;
-        }
-        if(d){
-            var val = new Date(this.initDate).clearTime();
-            val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
-            this[isMin ? 'minValue' : 'maxValue'] = val;
-            if(!initial){
-                this.generateStore();
+        if ((e.getTarget() == me.focusEl.dom) || e.within(me.layout.getRenderTarget())) {
+            item = me.getItemFromEvent(e) || me.activeItem;
+
+            if (item) {
+                if (item.getXTypes().indexOf('menuitem') >= 0) {
+                    if (!item.menu || !me.ignoreParentClicks) {
+                        item.onClick(e);
+                    } else {
+                        e.stopEvent();
+                    }
+                }
             }
+            me.fireEvent('click', me, item, e);
         }
     },
 
-    
-    getValue : function(){
-        var v = Ext.form.TimeField.superclass.getValue.call(this);
-        return this.formatDate(this.parseDate(v)) || '';
-    },
+    onDestroy: function() {
+        var me = this;
 
-    
-    setValue : function(value){
-        return Ext.form.TimeField.superclass.setValue.call(this, this.formatDate(this.parseDate(value)));
+        Ext.menu.Manager.unregister(me);
+        if (me.rendered) {
+            me.el.un(me.mouseMonitor);
+            me.keyNav.destroy();
+            delete me.keyNav;
+        }
+        me.callParent(arguments);
     },
 
-    
-    validateValue : Ext.form.DateField.prototype.validateValue,
+    onMouseLeave: function(e) {
+        var me = this;
 
-    formatDate : Ext.form.DateField.prototype.formatDate,
+        me.deactivateActiveItem();
 
-    parseDate: function(value) {
-        if (!value || Ext.isDate(value)) {
-            return value;
+        if (me.disabled) {
+            return;
         }
 
-        var id = this.initDate + ' ',
-            idf = this.initDateFormat + ' ',
-            v = Date.parseDate(id + value, idf + this.format), 
-            af = this.altFormats;
+        me.fireEvent('mouseleave', me, e);
+    },
 
-        if (!v && af) {
-            if (!this.altFormatsArray) {
-                this.altFormatsArray = af.split("|");
-            }
-            for (var i = 0, afa = this.altFormatsArray, len = afa.length; i < len && !v; i++) {
-                v = Date.parseDate(id + value, idf + afa[i]);
-            }
+    onMouseOver: function(e) {
+        var me = this,
+            fromEl = e.getRelatedTarget(),
+            mouseEnter = !me.el.contains(fromEl),
+            item = me.getItemFromEvent(e);
+
+        if (mouseEnter && me.parentMenu) {
+            me.parentMenu.setActiveItem(me.parentItem);
+            me.parentMenu.mouseMonitor.mouseenter();
         }
 
-        return v;
-    }
-});
-Ext.reg('timefield', Ext.form.TimeField);
-Ext.form.SliderField = Ext.extend(Ext.form.Field, {
-    
-    
-    useTips : true,
-    
-    
-    tipText : null,
-    
-    
-    actionMode: 'wrap',
-    
-    
-    initComponent : function() {
-        var cfg = Ext.copyTo({
-            id: this.id + '-slider'
-        }, this.initialConfig, ['vertical', 'minValue', 'maxValue', 'decimalPrecision', 'keyIncrement', 'increment', 'clickToChange', 'animate']);
-        
-        
-        if (this.useTips) {
-            var plug = this.tipText ? {getText: this.tipText} : {};
-            cfg.plugins = [new Ext.slider.Tip(plug)];
+        if (me.disabled) {
+            return;
         }
-        this.slider = new Ext.Slider(cfg);
-        Ext.form.SliderField.superclass.initComponent.call(this);
-    },    
-    
-    
-    onRender : function(ct, position){
-        this.autoCreate = {
-            id: this.id,
-            name: this.name,
-            type: 'hidden',
-            tag: 'input'    
-        };
-        Ext.form.SliderField.superclass.onRender.call(this, ct, position);
-        this.wrap = this.el.wrap({cls: 'x-form-field-wrap'});
-        this.resizeEl = this.positionEl = this.wrap;
-        this.slider.render(this.wrap);
-    },
-    
-    
-    onResize : function(w, h, aw, ah){
-        Ext.form.SliderField.superclass.onResize.call(this, w, h, aw, ah);
-        this.slider.setSize(w, h);    
-    },
-    
-    
-    initEvents : function(){
-        Ext.form.SliderField.superclass.initEvents.call(this);
-        this.slider.on('change', this.onChange, this);   
-    },
-    
-    
-    onChange : function(slider, v){
-        this.setValue(v, undefined, true);
-    },
-    
-    
-    onEnable : function(){
-        Ext.form.SliderField.superclass.onEnable.call(this);
-        this.slider.enable();
-    },
-    
-    
-    onDisable : function(){
-        Ext.form.SliderField.superclass.onDisable.call(this);
-        this.slider.disable();    
-    },
-    
-    
-    beforeDestroy : function(){
-        Ext.destroy(this.slider);
-        Ext.form.SliderField.superclass.beforeDestroy.call(this);
-    },
-    
-    
-    alignErrorIcon : function(){
-        this.errorIcon.alignTo(this.slider.el, 'tl-tr', [2, 0]);
-    },
-    
-    
-    setMinValue : function(v){
-        this.slider.setMinValue(v);
-        return this;    
-    },
-    
-    
-    setMaxValue : function(v){
-        this.slider.setMaxValue(v);
-        return this;    
-    },
-    
-    
-    setValue : function(v, animate,  silent){
-        
-        
-        if(!silent){
-            this.slider.setValue(v, animate);
+
+        if (item) {
+            me.setActiveItem(item);
+            if (item.activated && item.expandMenu) {
+                item.expandMenu();
+            }
         }
-        return Ext.form.SliderField.superclass.setValue.call(this, this.slider.getValue());
+        if (mouseEnter) {
+            me.fireEvent('mouseenter', me, e);
+        }
+        me.fireEvent('mouseover', me, item, e);
     },
-    
-    
-    getValue : function(){
-        return this.slider.getValue();    
-    }
-});
 
-Ext.reg('sliderfield', Ext.form.SliderField);
-Ext.form.Label = Ext.extend(Ext.BoxComponent, {
-    
-    
-    
+    setActiveItem: function(item) {
+        var me = this;
 
-    
-    onRender : function(ct, position){
-        if(!this.el){
-            this.el = document.createElement('label');
-            this.el.id = this.getId();
-            this.el.innerHTML = this.text ? Ext.util.Format.htmlEncode(this.text) : (this.html || '');
-            if(this.forId){
-                this.el.setAttribute('for', this.forId);
+        if (item && (item != me.activeItem && item != me.focusedItem)) {
+            me.deactivateActiveItem();
+            if (me.canActivateItem(item)) {
+                if (item.activate) {
+                    item.activate();
+                    if (item.activated) {
+                        me.activeItem = item;
+                        me.focusedItem = item;
+                        me.focus();
+                    }
+                } else {
+                    item.focus();
+                    me.focusedItem = item;
+                }
             }
+            item.el.scrollIntoView(me.layout.getRenderTarget());
         }
-        Ext.form.Label.superclass.onRender.call(this, ct, position);
     },
 
     
-    setText : function(t, encode){
-        var e = encode === false;
-        this[!e ? 'text' : 'html'] = t;
-        delete this[e ? 'text' : 'html'];
-        if(this.rendered){
-            this.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(t) : t;
-        }
-        return this;
-    }
-});
-
-Ext.reg('label', Ext.form.Label);
-Ext.form.Action = function(form, options){
-    this.form = form;
-    this.options = options || {};
-};
-
+    showBy: function(cmp, pos, off) {
+        var me = this,
+            xy,
+            region;
 
-Ext.form.Action.CLIENT_INVALID = 'client';
+        if (me.floating && cmp) {
+            me.layout.autoSize = true;
 
-Ext.form.Action.SERVER_INVALID = 'server';
+            
+            me.doAutoRender();
+            delete me.needsLayout;
 
-Ext.form.Action.CONNECT_FAILURE = 'connect';
+            
+            cmp = cmp.el || cmp;
 
-Ext.form.Action.LOAD_FAILURE = 'load';
+            
+            xy = me.el.getAlignToXY(cmp, pos || me.defaultAlign, off);
+            if (me.floatParent) {
+                region = me.floatParent.getTargetEl().getViewRegion();
+                xy[0] -= region.x;
+                xy[1] -= region.y;
+            }
+            me.showAt(xy);
+        }
+        return me;
+    },
 
-Ext.form.Action.prototype = {
+    doConstrain : function() {
+        var me = this,
+            y = me.el.getY(),
+            max, full,
+            vector,
+            returnY = y, normalY, parentEl, scrollTop, viewHeight;
 
+        delete me.height;
+        me.setSize();
+        full = me.getHeight();
+        if (me.floating) {
+            
+            parentEl = Ext.fly(me.el.getScopeParent());
+            scrollTop = parentEl.getScroll().top;
+            viewHeight = parentEl.getViewSize().height;
+            
+            
+            normalY = y - scrollTop;
+            max = me.maxHeight ? me.maxHeight : viewHeight - normalY;
+            if (full > viewHeight) {
+                max = viewHeight;
+                
+                returnY = y - normalY;
+            } else if (max < full) {
+                returnY = y - (full - max);
+                max = full;
+            }
+        }else{
+            max = me.getHeight();
+        }
+        
+        if (me.maxHeight){
+            max = Math.min(me.maxHeight, max);
+        }
+        if (full > max && max > 0){
+            me.layout.autoSize = false;
+            me.setHeight(max);
+            if (me.showSeparator){
+                me.iconSepEl.setHeight(me.layout.getRenderTarget().dom.scrollHeight);
+            }
+        }
+        vector = me.getConstrainVector(me.el.getScopeParent());
+        if (vector) {
+            me.setPosition(me.getPosition()[0] + vector[0]);
+        }
+        me.el.setY(returnY);
+    }
+});
 
 
+ Ext.define('Ext.menu.ColorPicker', {
+     extend: 'Ext.menu.Menu',
 
+     alias: 'widget.colormenu',
 
+     requires: [
+        'Ext.picker.Color'
+     ],
 
+    
+    hideOnClick : true,
 
+    
+    pickerId : null,
 
+    
 
+    
 
+    
 
+    
 
+    initComponent : function(){
+        var me = this,
+            cfg = Ext.apply({}, me.initialConfig);
 
+        
+        delete cfg.listeners;
+        Ext.apply(me, {
+            plain: true,
+            showSeparator: false,
+            items: Ext.applyIf({
+                cls: Ext.baseCSSPrefix + 'menu-color-item',
+                id: me.pickerId,
+                xtype: 'colorpicker'
+            }, cfg)
+        });
 
-    type : 'default',
+        me.callParent(arguments);
 
+        me.picker = me.down('colorpicker');
 
-    
-    run : function(options){
+        
+        me.relayEvents(me.picker, ['select']);
 
+        if (me.hideOnClick) {
+            me.on('select', me.hidePickerOnSelect, me);
+        }
     },
 
     
-    success : function(response){
+    hidePickerOnSelect: function() {
+        Ext.menu.Manager.hideAll();
+    }
+ });
 
-    },
+ Ext.define('Ext.menu.DatePicker', {
+     extend: 'Ext.menu.Menu',
 
-    
-    handleResponse : function(response){
+     alias: 'widget.datemenu',
 
-    },
+     requires: [
+        'Ext.picker.Date'
+     ],
 
     
-    failure : function(response){
-        this.response = response;
-        this.failureType = Ext.form.Action.CONNECT_FAILURE;
-        this.form.afterAction(this, false);
-    },
+    hideOnClick : true,
 
     
-    
-    
-    processResponse : function(response){
-        this.response = response;
-        if(!response.responseText && !response.responseXML){
-            return true;
-        }
-        this.result = this.handleResponse(response);
-        return this.result;
-    },
+    pickerId : null,
 
     
-    getUrl : function(appendParams){
-        var url = this.options.url || this.form.url || this.form.el.dom.action;
-        if(appendParams){
-            var p = this.getParams();
-            if(p){
-                url = Ext.urlAppend(url, p);
-            }
-        }
-        return url;
-    },
 
     
-    getMethod : function(){
-        return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
-    },
 
     
-    getParams : function(){
-        var bp = this.form.baseParams;
-        var p = this.options.params;
-        if(p){
-            if(typeof p == "object"){
-                p = Ext.urlEncode(Ext.applyIf(p, bp));
-            }else if(typeof p == 'string' && bp){
-                p += '&' + Ext.urlEncode(bp);
-            }
-        }else if(bp){
-            p = Ext.urlEncode(bp);
-        }
-        return p;
-    },
 
     
-    createCallback : function(opts){
-        var opts = opts || {};
-        return {
-            success: this.success,
-            failure: this.failure,
-            scope: this,
-            timeout: (opts.timeout*1000) || (this.form.timeout*1000),
-            upload: this.form.fileUpload ? this.success : undefined
-        };
-    }
-};
 
+    initComponent : function(){
+        var me = this;
 
-Ext.form.Action.Submit = function(form, options){
-    Ext.form.Action.Submit.superclass.constructor.call(this, form, options);
-};
+        Ext.apply(me, {
+            showSeparator: false,
+            plain: true,
+            border: false,
+            bodyPadding: 0, 
+            items: Ext.applyIf({
+                cls: Ext.baseCSSPrefix + 'menu-date-item',
+                id: me.pickerId,
+                xtype: 'datepicker'
+            }, me.initialConfig)
+        });
 
-Ext.extend(Ext.form.Action.Submit, Ext.form.Action, {
-    
-    
-    type : 'submit',
+        me.callParent(arguments);
 
-    
-    run : function(){
-        var o = this.options,
-            method = this.getMethod(),
-            isGet = method == 'GET';
-        if(o.clientValidation === false || this.form.isValid()){
-            if (o.submitEmptyText === false) {
-                var fields = this.form.items,
-                    emptyFields = [];
-                fields.each(function(f) {
-                    if (f.el.getValue() == f.emptyText) {
-                        emptyFields.push(f);
-                        f.el.dom.value = "";
-                    }
-                });
-            }
-            Ext.Ajax.request(Ext.apply(this.createCallback(o), {
-                form:this.form.el.dom,
-                url:this.getUrl(isGet),
-                method: method,
-                headers: o.headers,
-                params:!isGet ? this.getParams() : null,
-                isUpload: this.form.fileUpload
-            }));
-            if (o.submitEmptyText === false) {
-                Ext.each(emptyFields, function(f) {
-                    if (f.applyEmptyText) {
-                        f.applyEmptyText();
-                    }
-                });
-            }
-        }else if (o.clientValidation !== false){ 
-            this.failureType = Ext.form.Action.CLIENT_INVALID;
-            this.form.afterAction(this, false);
-        }
-    },
+        me.picker = me.down('datepicker');
+        
+        me.relayEvents(me.picker, ['select']);
 
-    
-    success : function(response){
-        var result = this.processResponse(response);
-        if(result === true || result.success){
-            this.form.afterAction(this, true);
-            return;
-        }
-        if(result.errors){
-            this.form.markInvalid(result.errors);
+        if (me.hideOnClick) {
+            me.on('select', me.hidePickerOnSelect, me);
         }
-        this.failureType = Ext.form.Action.SERVER_INVALID;
-        this.form.afterAction(this, false);
     },
 
-    
-    handleResponse : function(response){
-        if(this.form.errorReader){
-            var rs = this.form.errorReader.read(response);
-            var errors = [];
-            if(rs.records){
-                for(var i = 0, len = rs.records.length; i < len; i++) {
-                    var r = rs.records[i];
-                    errors[i] = r.data;
-                }
-            }
-            if(errors.length < 1){
-                errors = null;
-            }
-            return {
-                success : rs.success,
-                errors : errors
-            };
-        }
-        return Ext.decode(response.responseText);
+    hidePickerOnSelect: function() {
+        Ext.menu.Manager.hideAll();
     }
-});
+ });
 
+Ext.define('Ext.panel.Tool', {
+    extend: 'Ext.Component',
+    requires: ['Ext.tip.QuickTipManager'],
+    alias: 'widget.tool',
 
+    baseCls: Ext.baseCSSPrefix + 'tool',
+    disabledCls: Ext.baseCSSPrefix + 'tool-disabled',
+    toolPressedCls: Ext.baseCSSPrefix + 'tool-pressed',
+    toolOverCls: Ext.baseCSSPrefix + 'tool-over',
+    ariaRole: 'button',
+    renderTpl: ['<img id="{id}-toolEl" src="{blank}" class="{baseCls}-{type}" role="presentation"/>'],
 
-Ext.form.Action.Load = function(form, options){
-    Ext.form.Action.Load.superclass.constructor.call(this, form, options);
-    this.reader = this.form.reader;
-};
+    
 
-Ext.extend(Ext.form.Action.Load, Ext.form.Action, {
     
-    type : 'load',
 
     
-    run : function(){
-        Ext.Ajax.request(Ext.apply(
-                this.createCallback(this.options), {
-                    method:this.getMethod(),
-                    url:this.getUrl(false),
-                    headers: this.options.headers,
-                    params:this.getParams()
-        }));
-    },
 
     
-    success : function(response){
-        var result = this.processResponse(response);
-        if(result === true || !result.success || !result.data){
-            this.failureType = Ext.form.Action.LOAD_FAILURE;
-            this.form.afterAction(this, false);
-            return;
-        }
-        this.form.clearInvalid();
-        this.form.setValues(result.data);
-        this.form.afterAction(this, true);
-    },
+
+     
+    tooltipType: 'qtip',
 
     
-    handleResponse : function(response){
-        if(this.form.reader){
-            var rs = this.form.reader.read(response);
-            var data = rs.records && rs.records[0] ? rs.records[0].data : null;
-            return {
-                success : rs.success,
-                data : data
-            };
-        }
-        return Ext.decode(response.responseText);
-    }
-});
+    stopEvent: true,
 
+    initComponent: function() {
+        var me = this;
+        me.addEvents(
+            
+            'click'
+        );
 
 
+        me.type = me.type || me.id;
 
-Ext.form.Action.DirectLoad = Ext.extend(Ext.form.Action.Load, {
-    constructor: function(form, opts) {
-        Ext.form.Action.DirectLoad.superclass.constructor.call(this, form, opts);
-    },
-    type : 'directload',
+        Ext.applyIf(me.renderData, {
+            baseCls: me.baseCls,
+            blank: Ext.BLANK_IMAGE_URL,
+            type: me.type
+        });
 
-    run : function(){
-        var args = this.getParams();
-        args.push(this.success, this);
-        this.form.api.load.apply(window, args);
+        me.addChildEls('toolEl');
+
+        
+        me.tooltip = me.tooltip || me.qtip;
+        me.callParent();
     },
 
-    getParams : function() {
-        var buf = [], o = {};
-        var bp = this.form.baseParams;
-        var p = this.options.params;
-        Ext.apply(o, p, bp);
-        var paramOrder = this.form.paramOrder;
-        if(paramOrder){
-            for(var i = 0, len = paramOrder.length; i < len; i++){
-                buf.push(o[paramOrder[i]]);
+    
+    afterRender: function() {
+        var me = this,
+            attr;
+
+        me.callParent(arguments);
+        if (me.tooltip) {
+            if (Ext.isObject(me.tooltip)) {
+                Ext.tip.QuickTipManager.register(Ext.apply({
+                    target: me.id
+                }, me.tooltip));
+            }
+            else {
+                attr = me.tooltipType == 'qtip' ? 'data-qtip' : 'title';
+                me.toolEl.dom.setAttribute(attr, me.tooltip);
             }
-        }else if(this.form.paramsAsHash){
-            buf.push(o);
         }
-        return buf;
+
+        me.mon(me.toolEl, {
+            click: me.onClick,
+            mousedown: me.onMouseDown,
+            mouseover: me.onMouseOver,
+            mouseout: me.onMouseOut,
+            scope: me
+        });
     },
+
     
+    setType: function(type) {
+        var me = this;
+
+        me.type = type;
+        if (me.rendered) {
+            me.toolEl.dom.className = me.baseCls + '-' + type;
+        }
+        return me;
+    },
+
     
-    
-    processResponse : function(result) {
-        this.result = result;
-        return result;
+    bindTo: function(component) {
+        this.owner = component;
     },
 
-    success : function(response, trans){
-        if(trans.type == Ext.Direct.exceptions.SERVER){
-            response = {};
+    
+    onClick: function(e, target) {
+        var me = this,
+            owner;
+
+        if (me.disabled) {
+            return false;
         }
-        Ext.form.Action.DirectLoad.superclass.success.call(this, response);
-    }
-});
+        owner = me.owner || me.ownerCt;
+
+        
+        me.el.removeCls(me.toolPressedCls);
+        me.el.removeCls(me.toolOverCls);
 
+        if (me.stopEvent !== false) {
+            e.stopEvent();
+        }
 
-Ext.form.Action.DirectSubmit = Ext.extend(Ext.form.Action.Submit, {
-    constructor : function(form, opts) {
-        Ext.form.Action.DirectSubmit.superclass.constructor.call(this, form, opts);
+        Ext.callback(me.handler, me.scope || me, [e, target, owner, me]);
+        me.fireEvent('click', me, e);
+        return true;
     },
-    type : 'directsubmit',
+
     
-    run : function(){
-        var o = this.options;
-        if(o.clientValidation === false || this.form.isValid()){
-            
-            
-            this.success.params = this.getParams();
-            this.form.api.submit(this.form.el.dom, this.success, this);
-        }else if (o.clientValidation !== false){ 
-            this.failureType = Ext.form.Action.CLIENT_INVALID;
-            this.form.afterAction(this, false);
+    onDestroy: function(){
+        if (Ext.isObject(this.tooltip)) {
+            Ext.tip.QuickTipManager.unregister(this.id);
         }
+        this.callParent();
     },
 
-    getParams : function() {
-        var o = {};
-        var bp = this.form.baseParams;
-        var p = this.options.params;
-        Ext.apply(o, p, bp);
-        return o;
-    },
-    
     
-    
-    processResponse : function(result) {
-        this.result = result;
-        return result;
+    onMouseDown: function() {
+        if (this.disabled) {
+            return false;
+        }
+
+        this.el.addCls(this.toolPressedCls);
     },
 
-    success : function(response, trans){
-        if(trans.type == Ext.Direct.exceptions.SERVER){
-            response = {};
+    
+    onMouseOver: function() {
+        if (this.disabled) {
+            return false;
         }
-        Ext.form.Action.DirectSubmit.superclass.success.call(this, response);
+        this.el.addCls(this.toolOverCls);
+    },
+
+    
+    onMouseOut: function() {
+        this.el.removeCls(this.toolOverCls);
     }
 });
 
-Ext.form.Action.ACTION_TYPES = {
-    'load' : Ext.form.Action.Load,
-    'submit' : Ext.form.Action.Submit,
-    'directload' : Ext.form.Action.DirectLoad,
-    'directsubmit' : Ext.form.Action.DirectSubmit
-};
-
-Ext.form.VTypes = function(){
+Ext.define('Ext.resizer.Handle', {
+    extend: 'Ext.Component',
+    handleCls: '',
+    baseHandleCls: Ext.baseCSSPrefix + 'resizable-handle',
     
-    var alpha = /^[a-zA-Z_]+$/,
-        alphanum = /^[a-zA-Z0-9_]+$/,
-        email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
-        url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
-
     
-    return {
-        
-        'email' : function(v){
-            return email.test(v);
-        },
-        
-        'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
-        
-        'emailMask' : /[a-z0-9_\.\-@\+]/i,
+    region: '',
 
-        
-        'url' : function(v){
-            return url.test(v);
-        },
-        
-        'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
+    onRender: function() {
+        this.addCls(
+            this.baseHandleCls,
+            this.baseHandleCls + '-' + this.region,
+            this.handleCls
+        );
+        this.callParent(arguments);
+        this.el.unselectable();
+    }
+});
 
-        
-        'alpha' : function(v){
-            return alpha.test(v);
-        },
-        
-        'alphaText' : 'This field should only contain letters and _',
-        
-        'alphaMask' : /[a-z_]/i,
 
-        
-        'alphanum' : function(v){
-            return alphanum.test(v);
-        },
-        
-        'alphanumText' : 'This field should only contain letters, numbers and _',
-        
-        'alphanumMask' : /[a-z0-9_]/i
-    };
-}();
+Ext.define('Ext.resizer.Resizer', {
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+    uses: ['Ext.resizer.ResizeTracker', 'Ext.Component'],
+
+    alternateClassName: 'Ext.Resizable',
+
+    handleCls: Ext.baseCSSPrefix + 'resizable-handle',
+    pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned',
+    overCls:   Ext.baseCSSPrefix + 'resizable-over',
+    wrapCls:   Ext.baseCSSPrefix + 'resizable-wrap',
 
-Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
-    
-    autoExpandColumn : false,
-    
-    autoExpandMax : 1000,
-    
-    autoExpandMin : 50,
-    
-    columnLines : false,
-    
-    
-    
-    
-    
-    ddText : '{0} selected row{1}',
-    
-    deferRowRender : true,
-    
-    
-    
-    enableColumnHide : true,
-    
-    enableColumnMove : true,
-    
-    enableDragDrop : false,
-    
-    enableHdMenu : true,
-    
-    
-    loadMask : false,
     
+    dynamic: true,
+
     
-    minColumnWidth : 25,
+    handles: 's e se',
+
     
+    height : null,
+
     
+    width : null,
+
     
+    heightIncrement : 0,
+
     
-    stripeRows : false,
+    widthIncrement : 0,
+
     
-    trackMouseOver : true,
+    minHeight : 20,
+
     
-    stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
+    minWidth : 20,
+
     
-    view : null,
+    maxHeight : 10000,
 
     
-    bubbleEvents: [],
+    maxWidth : 10000,
 
     
+    pinned: false,
 
     
-    rendered : false,
+    preserveRatio: false,
+
     
-    viewReady : false,
+    transparent: false,
 
     
-    initComponent : function(){
-        Ext.grid.GridPanel.superclass.initComponent.call(this);
 
-        if(this.columnLines){
-            this.cls = (this.cls || '') + ' x-grid-with-col-lines';
-        }
-        
-        
-        this.autoScroll = false;
-        this.autoWidth = false;
+    possiblePositions: {
+        n:  'north',
+        s:  'south',
+        e:  'east',
+        w:  'west',
+        se: 'southeast',
+        sw: 'southwest',
+        nw: 'northwest',
+        ne: 'northeast'
+    },
 
-        if(Ext.isArray(this.columns)){
-            this.colModel = new Ext.grid.ColumnModel(this.columns);
-            delete this.columns;
-        }
+    
 
-        
-        if(this.ds){
-            this.store = this.ds;
-            delete this.ds;
-        }
-        if(this.cm){
-            this.colModel = this.cm;
-            delete this.cm;
-        }
-        if(this.sm){
-            this.selModel = this.sm;
-            delete this.sm;
-        }
-        this.store = Ext.StoreMgr.lookup(this.store);
+    
 
-        this.addEvents(
-            
-            
-            'click',
-            
-            'dblclick',
-            
-            'contextmenu',
-            
-            'mousedown',
-            
-            'mouseup',
-            
-            'mouseover',
-            
-            'mouseout',
-            
-            'keypress',
-            
-            'keydown',
+    constructor: function(config) {
+        var me = this,
+            target,
+            tag,
+            handles = me.handles,
+            handleCls,
+            possibles,
+            len,
+            i = 0,
+            pos;
 
+        this.addEvents(
             
+            'beforeresize',
             
-            'cellmousedown',
-            
-            'rowmousedown',
-            
-            'headermousedown',
-
-            
-            'groupmousedown',
-
+            'resizedrag',
             
-            'rowbodymousedown',
+            'resize'
+        );
 
-            
-            'containermousedown',
+        if (Ext.isString(config) || Ext.isElement(config) || config.dom) {
+            target = config;
+            config = arguments[1] || {};
+            config.target = target;
+        }
+        
+        me.mixins.observable.constructor.call(me, config);
 
-            
-            'cellclick',
-            
-            'celldblclick',
-            
-            'rowclick',
-            
-            'rowdblclick',
-            
-            'headerclick',
-            
-            'headerdblclick',
-            
-            'groupclick',
-            
-            'groupdblclick',
-            
-            'containerclick',
-            
-            'containerdblclick',
+        
+        
+        target = me.target;
+        if (target) {
+            if (target.isComponent) {
+                me.el = target.getEl();
+                if (target.minWidth) {
+                    me.minWidth = target.minWidth;
+                }
+                if (target.minHeight) {
+                    me.minHeight = target.minHeight;
+                }
+                if (target.maxWidth) {
+                    me.maxWidth = target.maxWidth;
+                }
+                if (target.maxHeight) {
+                    me.maxHeight = target.maxHeight;
+                }
+                if (target.floating) {
+                    if (!this.hasOwnProperty('handles')) {
+                        this.handles = 'n ne e se s sw w nw';
+                    }
+                }
+            } else {
+                me.el = me.target = Ext.get(target);
+            }
+        }
+        
+        else {
+            me.target = me.el = Ext.get(me.el);
+        }
 
+        
+        
+        
+        tag = me.el.dom.tagName;
+        if (tag == 'TEXTAREA' || tag == 'IMG') {
             
-            'rowbodyclick',
-            
-            'rowbodydblclick',
+            me.originalTarget = me.target;
+            me.target = me.el = me.el.wrap({
+                cls: me.wrapCls,
+                id: me.el.id + '-rzwrap'
+            });
 
             
-            'rowcontextmenu',
-            
-            'cellcontextmenu',
-            
-            'headercontextmenu',
-            
-            'groupcontextmenu',
-            
-            'containercontextmenu',
-            
-            'rowbodycontextmenu',
-            
-            'bodyscroll',
-            
-            'columnresize',
-            
-            'columnmove',
-            
-            'sortchange',
-            
-            'groupchange',
-            
-            'reconfigure',
-            
-            'viewready'
-        );
-    },
-
-    
-    onRender : function(ct, position){
-        Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
-
-        var c = this.getGridEl();
+            me.el.setPositioning(me.originalTarget.getPositioning());
+            me.originalTarget.clearPositioning();
+            var box = me.originalTarget.getBox();
+            me.el.setBox(box);
+        }
 
-        this.el.addClass('x-grid-panel');
+        
+        
+        me.el.position();
+        if (me.pinned) {
+            me.el.addCls(me.pinnedCls);
+        }
 
-        this.mon(c, {
-            scope: this,
-            mousedown: this.onMouseDown,
-            click: this.onClick,
-            dblclick: this.onDblClick,
-            contextmenu: this.onContextMenu
+        
+        me.resizeTracker = Ext.create('Ext.resizer.ResizeTracker', {
+            disabled: me.disabled,
+            target: me.target,
+            constrainTo: me.constrainTo,
+            overCls: me.overCls,
+            throttle: me.throttle,
+            originalTarget: me.originalTarget,
+            delegate: '.' + me.handleCls,
+            dynamic: me.dynamic,
+            preserveRatio: me.preserveRatio,
+            heightIncrement: me.heightIncrement,
+            widthIncrement: me.widthIncrement,
+            minHeight: me.minHeight,
+            maxHeight: me.maxHeight,
+            minWidth: me.minWidth,
+            maxWidth: me.maxWidth
         });
 
-        this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
-
-        var view = this.getView();
-        view.init(this);
-        view.render();
-        this.getSelectionModel().init(this);
-    },
-
-    
-    initEvents : function(){
-        Ext.grid.GridPanel.superclass.initEvents.call(this);
+        
+        me.resizeTracker.on('mousedown', me.onBeforeResize, me);
+        me.resizeTracker.on('drag', me.onResize, me);
+        me.resizeTracker.on('dragend', me.onResizeEnd, me);
 
-        if(this.loadMask){
-            this.loadMask = new Ext.LoadMask(this.bwrap,
-                    Ext.apply({store:this.store}, this.loadMask));
+        if (me.handles == 'all') {
+            me.handles = 'n s e w ne nw se sw';
         }
-    },
 
-    initStateEvents : function(){
-        Ext.grid.GridPanel.superclass.initStateEvents.call(this);
-        this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
-    },
+        handles = me.handles = me.handles.split(/ |\s*?[,;]\s*?/);
+        possibles = me.possiblePositions;
+        len = handles.length;
+        handleCls = me.handleCls + ' ' + (this.target.isComponent ? (me.target.baseCls + '-handle ') : '') + me.handleCls + '-';
 
-    applyState : function(state){
-        var cm = this.colModel,
-            cs = state.columns,
-            store = this.store,
-            s,
-            c,
-            oldIndex;
+        for(; i < len; i++){
+            
+            if (handles[i] && possibles[handles[i]]) {
+                pos = possibles[handles[i]];
+                
 
-        if(cs){
-            for(var i = 0, len = cs.length; i < len; i++){
-                s = cs[i];
-                c = cm.getColumnById(s.id);
-                if(c){
-                    cm.setState(i, {
-                        hidden: s.hidden,
-                        width: s.width    
-                    });
-                    oldIndex = cm.getIndexById(s.id);
-                    if(oldIndex != i){
-                        cm.moveColumn(oldIndex, i);
-                    }
+                me[pos] = Ext.create('Ext.Component', {
+                    owner: this,
+                    region: pos,
+                    cls: handleCls + pos,
+                    renderTo: me.el
+                });
+                me[pos].el.unselectable();
+                if (me.transparent) {
+                    me[pos].el.setOpacity(0);
                 }
             }
         }
-        if(store){
-            s = state.sort;
-            if(s){
-                store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
-            }
-            s = state.group;
-            if(store.groupBy){
-                if(s){
-                    store.groupBy(s);
-                }else{
-                    store.clearGrouping();
-                }
-            }
 
+        
+        if (Ext.isNumber(me.width)) {
+            me.width = Ext.Number.constrain(me.width, me.minWidth, me.maxWidth);
         }
-        var o = Ext.apply({}, state);
-        delete o.columns;
-        delete o.sort;
-        Ext.grid.GridPanel.superclass.applyState.call(this, o);
-    },
-
-    getState : function(){
-        var o = {columns: []},
-            store = this.store,
-            ss,
-            gs;
-
-        for(var i = 0, c; (c = this.colModel.config[i]); i++){
-            o.columns[i] = {
-                id: c.id,
-                width: c.width
-            };
-            if(c.hidden){
-                o.columns[i].hidden = true;
-            }
+        if (Ext.isNumber(me.height)) {
+            me.height = Ext.Number.constrain(me.height, me.minHeight, me.maxHeight);
         }
-        if(store){
-            ss = store.getSortState();
-            if(ss){
-                o.sort = ss;
-            }
-            if(store.getGroupState){
-                gs = store.getGroupState();
-                if(gs){
-                    o.group = gs;
-                }
+
+        
+        if (me.width != null || me.height != null) {
+            if (me.originalTarget) {
+                me.originalTarget.setWidth(me.width);
+                me.originalTarget.setHeight(me.height);
             }
+            me.resizeTo(me.width, me.height);
         }
-        return o;
+
+        me.forceHandlesHeight();
     },
 
-    
-    afterRender : function(){
-        Ext.grid.GridPanel.superclass.afterRender.call(this);
-        var v = this.view;
-        this.on('bodyresize', v.layout, v);
-        v.layout();
-        if(this.deferRowRender){
-            if (!this.deferRowRenderTask){
-                this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
-            }
-            this.deferRowRenderTask.delay(10);
-        }else{
-            v.afterRender();
-        }
-        this.viewReady = true;
+    disable: function() {
+        this.resizeTracker.disable();
     },
 
-    
-    reconfigure : function(store, colModel){
-        var rendered = this.rendered;
-        if(rendered){
-            if(this.loadMask){
-                this.loadMask.destroy();
-                this.loadMask = new Ext.LoadMask(this.bwrap,
-                        Ext.apply({}, {store:store}, this.initialConfig.loadMask));
-            }
-        }
-        if(this.view){
-            this.view.initData(store, colModel);
-        }
-        this.store = store;
-        this.colModel = colModel;
-        if(rendered){
-            this.view.refresh(true);
-        }
-        this.fireEvent('reconfigure', this, store, colModel);
+    enable: function() {
+        this.resizeTracker.enable();
     },
 
     
-    onDestroy : function(){
-        if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
-            this.deferRowRenderTask.cancel();
-        }
-        if(this.rendered){
-            Ext.destroy(this.view, this.loadMask);
-        }else if(this.store && this.store.autoDestroy){
-            this.store.destroy();
-        }
-        Ext.destroy(this.colModel, this.selModel);
-        this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
-        Ext.grid.GridPanel.superclass.onDestroy.call(this);
+    onBeforeResize: function(tracker, e) {
+        var b = this.target.getBox();
+        return this.fireEvent('beforeresize', this, b.width, b.height, e);
     },
 
     
-    processEvent : function(name, e){
-        this.view.processEvent(name, e);
+    onResize: function(tracker, e) {
+        var me = this,
+            b = me.target.getBox();
+        me.forceHandlesHeight();
+        return me.fireEvent('resizedrag', me, b.width, b.height, e);
     },
 
     
-    onClick : function(e){
-        this.processEvent('click', e);
+    onResizeEnd: function(tracker, e) {
+        var me = this,
+            b = me.target.getBox();
+        me.forceHandlesHeight();
+        return me.fireEvent('resize', me, b.width, b.height, e);
     },
 
     
-    onMouseDown : function(e){
-        this.processEvent('mousedown', e);
+    resizeTo : function(width, height){
+        this.target.setSize(width, height);
+        this.fireEvent('resize', this, width, height, null);
     },
 
     
-    onContextMenu : function(e, t){
-        this.processEvent('contextmenu', e);
+    getEl : function() {
+        return this.el;
     },
 
     
-    onDblClick : function(e){
-        this.processEvent('dblclick', e);
+    getTarget: function() {
+        return this.target;
     },
 
-    
-    walkCells : function(row, col, step, fn, scope){
-        var cm    = this.colModel,
-            clen  = cm.getColumnCount(),
-            ds    = this.store,
-            rlen  = ds.getCount(),
-            first = true;
+    destroy: function() {
+        var h;
+        for (var i = 0, l = this.handles.length; i < l; i++) {
+            h = this[this.possiblePositions[this.handles[i]]];
+            delete h.owner;
+            Ext.destroy(h);
+        }
+    },
 
-        if(step < 0){
-            if(col < 0){
-                row--;
-                first = false;
+    
+    forceHandlesHeight : function() {
+        var me = this,
+            handle;
+        if (Ext.isIE6) {
+            handle = me.east;
+            if (handle) {
+                handle.setHeight(me.el.getHeight());
             }
-            while(row >= 0){
-                if(!first){
-                    col = clen-1;
-                }
-                first = false;
-                while(col >= 0){
-                    if(fn.call(scope || this, row, col, cm) === true){
-                        return [row, col];
-                    }
-                    col--;
-                }
-                row--;
+            handle = me.west;
+            if (handle) {
+                handle.setHeight(me.el.getHeight());
             }
-        } else {
-            if(col >= clen){
-                row++;
-                first = false;
+            me.el.repaint();
+        }
+    }
+});
+
+
+Ext.define('Ext.resizer.ResizeTracker', {
+    extend: 'Ext.dd.DragTracker',
+    dynamic: true,
+    preserveRatio: false,
+
+    
+    constrainTo: null,
+    
+    proxyCls:  Ext.baseCSSPrefix + 'resizable-proxy',
+
+    constructor: function(config) {
+        var me = this;
+
+        if (!config.el) {
+            if (config.target.isComponent) {
+                me.el = config.target.getEl();
+            } else {
+                me.el = config.target;
             }
-            while(row < rlen){
-                if(!first){
-                    col = 0;
-                }
-                first = false;
-                while(col < clen){
-                    if(fn.call(scope || this, row, col, cm) === true){
-                        return [row, col];
-                    }
-                    col++;
-                }
-                row++;
+        }
+        this.callParent(arguments);
+
+        
+        if (me.preserveRatio && me.minWidth && me.minHeight) {
+            var widthRatio = me.minWidth / me.el.getWidth(),
+                heightRatio = me.minHeight / me.el.getHeight();
+
+            
+            
+            
+            if (heightRatio > widthRatio) {
+                me.minWidth = me.el.getWidth() * heightRatio;
+            } else {
+                me.minHeight = me.el.getHeight() * widthRatio;
             }
         }
-        return null;
-    },
 
-    
-    getGridEl : function(){
-        return this.body;
+        
+        
+        if (me.throttle) {
+            var throttledResizeFn = Ext.Function.createThrottled(function() {
+                    Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
+                }, me.throttle);
+
+            me.resize = function(box, direction, atEnd) {
+                if (atEnd) {
+                    Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
+                } else {
+                    throttledResizeFn.apply(null, arguments);
+                }
+            };
+        }
     },
 
-    
-    stopEditing : Ext.emptyFn,
+    onBeforeStart: function(e) {
+        
+        this.startBox = this.el.getBox();
+    },
 
     
-    getSelectionModel : function(){
-        if(!this.selModel){
-            this.selModel = new Ext.grid.RowSelectionModel(
-                    this.disableSelection ? {selectRow: Ext.emptyFn} : null);
+    getDynamicTarget: function() {
+        var me = this,
+            target = me.target;
+            
+        if (me.dynamic) {
+            return target;
+        } else if (!me.proxy) {
+            me.proxy = me.createProxy(target);
         }
-        return this.selModel;
+        me.proxy.show();
+        return me.proxy;
     },
-
     
-    getStore : function(){
-        return this.store;
+    
+    createProxy: function(target){
+        var proxy,
+            cls = this.proxyCls,
+            renderTo;
+            
+        if (target.isComponent) {
+            proxy = target.getProxy().addCls(cls);
+        } else {
+            renderTo = Ext.getBody();
+            if (Ext.scopeResetCSS) {
+                renderTo = Ext.getBody().createChild({
+                    cls: Ext.baseCSSPrefix + 'reset'
+                });
+            }
+            proxy = target.createProxy({
+                tag: 'div',
+                cls: cls,
+                id: target.id + '-rzproxy'
+            }, renderTo);
+        }
+        proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
+        return proxy;
     },
 
-    
-    getColumnModel : function(){
-        return this.colModel;
+    onStart: function(e) {
+        
+        this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
+
+        
+        if (!this.dynamic) {
+            this.resize(this.startBox, {
+                horizontal: 'none',
+                vertical: 'none'
+            });
+        }
     },
 
-    
-    getView : function(){
-        if(!this.view){
-            this.view = new Ext.grid.GridView(this.viewConfig);
+    onDrag: function(e) {
+        
+        if (this.dynamic || this.proxy) {
+            this.updateDimensions(e);
         }
-        return this.view;
     },
-    
-    getDragDropText : function(){
-        var count = this.selModel.getCount();
-        return String.format(this.ddText, count, count == 1 ? '' : 's');
-    }
 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    updateDimensions: function(e, atEnd) {
+        var me = this,
+            region = me.activeResizeHandle.region,
+            offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
+            box = me.startBox,
+            ratio,
+            widthAdjust = 0,
+            heightAdjust = 0,
+            snappedWidth,
+            snappedHeight,
+            adjustX = 0,
+            adjustY = 0,
+            dragRatio,
+            horizDir = offset[0] < 0 ? 'right' : 'left',
+            vertDir = offset[1] < 0 ? 'down' : 'up',
+            oppositeCorner,
+            axis; 
+
+        switch (region) {
+            case 'south':
+                heightAdjust = offset[1];
+                axis = 2;
+                break;
+            case 'north':
+                heightAdjust = -offset[1];
+                adjustY = -heightAdjust;
+                axis = 2;
+                break;
+            case 'east':
+                widthAdjust = offset[0];
+                axis = 1;
+                break;
+            case 'west':
+                widthAdjust = -offset[0];
+                adjustX = -widthAdjust;
+                axis = 1;
+                break;
+            case 'northeast':
+                heightAdjust = -offset[1];
+                adjustY = -heightAdjust;
+                widthAdjust = offset[0];
+                oppositeCorner = [box.x, box.y + box.height];
+                axis = 3;
+                break;
+            case 'southeast':
+                heightAdjust = offset[1];
+                widthAdjust = offset[0];
+                oppositeCorner = [box.x, box.y];
+                axis = 3;
+                break;
+            case 'southwest':
+                widthAdjust = -offset[0];
+                adjustX = -widthAdjust;
+                heightAdjust = offset[1];
+                oppositeCorner = [box.x + box.width, box.y];
+                axis = 3;
+                break;
+            case 'northwest':
+                heightAdjust = -offset[1];
+                adjustY = -heightAdjust;
+                widthAdjust = -offset[0];
+                adjustX = -widthAdjust;
+                oppositeCorner = [box.x + box.width, box.y + box.height];
+                axis = 3;
+                break;
+        }
 
+        var newBox = {
+            width: box.width + widthAdjust,
+            height: box.height + heightAdjust,
+            x: box.x + adjustX,
+            y: box.y + adjustY
+        };
 
+        
+        snappedWidth = Ext.Number.snap(newBox.width, me.widthIncrement);
+        snappedHeight = Ext.Number.snap(newBox.height, me.heightIncrement);
+        if (snappedWidth != newBox.width || snappedHeight != newBox.height){
+            switch (region) {
+                case 'northeast':
+                    newBox.y -= snappedHeight - newBox.height;
+                    break;
+                case 'north':
+                    newBox.y -= snappedHeight - newBox.height;
+                    break;
+                case 'southwest':
+                    newBox.x -= snappedWidth - newBox.width;
+                    break;
+                case 'west':
+                    newBox.x -= snappedWidth - newBox.width;
+                    break;
+                case 'northwest':
+                    newBox.x -= snappedWidth - newBox.width;
+                    newBox.y -= snappedHeight - newBox.height;
+            }
+            newBox.width = snappedWidth;
+            newBox.height = snappedHeight;
+        }
 
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    
-});
-Ext.reg('grid', Ext.grid.GridPanel);
-Ext.grid.GridView = Ext.extend(Ext.util.Observable, {
-    
+        
+        if (newBox.width < me.minWidth || newBox.width > me.maxWidth) {
+            newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
 
-    
+            
+            if (adjustX) {
+                newBox.x = box.x + (box.width - newBox.width);
+            }
+        } else {
+            me.lastX = newBox.x;
+        }
+        if (newBox.height < me.minHeight || newBox.height > me.maxHeight) {
+            newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
 
-    
+            
+            if (adjustY) {
+                newBox.y = box.y + (box.height - newBox.height);
+            }
+        } else {
+            me.lastY = newBox.y;
+        }
 
-    
+        
+        if (me.preserveRatio || e.shiftKey) {
+            var newHeight,
+                newWidth;
 
-    
+            ratio = me.startBox.width / me.startBox.height;
 
-    
-    deferEmptyText : true,
+            
+            newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
+            newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
 
-    
-    scrollOffset : undefined,
+            
+            if (axis == 1) {
+                newBox.height = newHeight;
+            }
 
-    
-    autoFill : false,
+            
+            else if (axis == 2) {
+                newBox.width = newWidth;
+            }
 
-    
-    forceFit : false,
+            
+            else {
+                
+                
+                dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
 
-    
-    sortClasses : ['sort-asc', 'sort-desc'],
+                
+                if (dragRatio > ratio) {
+                    newBox.height = newHeight;
+                } else {
+                    newBox.width = newWidth;
+                }
 
-    
-    sortAscText : 'Sort Ascending',
+                
+                if (region == 'northeast') {
+                    newBox.y = box.y - (newBox.height - box.height);
+                } else if (region == 'northwest') {
+                    newBox.y = box.y - (newBox.height - box.height);
+                    newBox.x = box.x - (newBox.width - box.width);
+                } else if (region == 'southwest') {
+                    newBox.x = box.x - (newBox.width - box.width);
+                }
+            }
+        }
 
-    
-    sortDescText : 'Sort Descending',
+        if (heightAdjust === 0) {
+            vertDir = 'none';
+        }
+        if (widthAdjust === 0) {
+            horizDir = 'none';
+        }
+        me.resize(newBox, {
+            horizontal: horizDir,
+            vertical: vertDir
+        }, atEnd);
+    },
 
-    
-    columnsText : 'Columns',
+    getResizeTarget: function(atEnd) {
+        return atEnd ? this.target : this.getDynamicTarget();
+    },
 
-    
-    selectedRowClass : 'x-grid3-row-selected',
+    resize: function(box, direction, atEnd) {
+        var target = this.getResizeTarget(atEnd);
+        if (target.isComponent) {
+            if (target.floating) {
+                target.setPagePosition(box.x, box.y);
+            }
+            target.setSize(box.width, box.height);
+        } else {
+            target.setBox(box);
+            
+            if (this.originalTarget) {
+                this.originalTarget.setBox(box);
+            }
+        }
+    },
 
-    
-    borderWidth : 2,
-    tdClass : 'x-grid3-cell',
-    hdCls : 'x-grid3-hd',
-    markDirty : true,
+    onEnd: function(e) {
+        this.updateDimensions(e, true);
+        if (this.proxy) {
+            this.proxy.hide();
+        }
+    }
+});
 
-    
-    cellSelectorDepth : 4,
-    
-    rowSelectorDepth : 10,
 
+Ext.define('Ext.resizer.SplitterTracker', {
+    extend: 'Ext.dd.DragTracker',
+    requires: ['Ext.util.Region'],
+    enabled: true,
     
-    rowBodySelectorDepth : 10,
+    overlayCls: Ext.baseCSSPrefix + 'resizable-overlay',
+
+    getPrevCmp: function() {
+        var splitter = this.getSplitter();
+        return splitter.previousSibling();
+    },
+
+    getNextCmp: function() {
+        var splitter = this.getSplitter();
+        return splitter.nextSibling();
+    },
 
     
-    cellSelector : 'td.x-grid3-cell',
     
-    rowSelector : 'div.x-grid3-row',
+    onBeforeStart: function(e) {
+        var me = this,
+            prevCmp = me.getPrevCmp(),
+            nextCmp = me.getNextCmp(),
+            collapseEl = me.getSplitter().collapseEl,
+            overlay;
+            
+        if (collapseEl && (e.getTarget() === me.getSplitter().collapseEl.dom)) {
+            return false;
+        }
 
-    
-    rowBodySelector : 'div.x-grid3-row-body',
+        
+        if (nextCmp.collapsed || prevCmp.collapsed) {
+            return false;
+        }
+        
+        overlay = me.overlay =  Ext.getBody().createChild({
+            cls: me.overlayCls, 
+            html: '&#160;'
+        });
+        overlay.unselectable();
+        overlay.setSize(Ext.Element.getViewWidth(true), Ext.Element.getViewHeight(true));
+        overlay.show();
+        
+        
+        me.prevBox  = prevCmp.getEl().getBox();
+        me.nextBox  = nextCmp.getEl().getBox();
+        me.constrainTo = me.calculateConstrainRegion();
+    },
 
     
-    firstRowCls: 'x-grid3-row-first',
-    lastRowCls: 'x-grid3-row-last',
-    rowClsRe: /(?:^|\s+)x-grid3-row-(first|last|alt)(?:\s+|$)/g,
+    onStart: function(e) {
+        var splitter = this.getSplitter();
+        splitter.addCls(splitter.baseCls + '-active');
+    },
 
-    constructor : function(config){
-        Ext.apply(this, config);
-        
-        this.addEvents(
+    
+    calculateConstrainRegion: function() {
+        var me         = this,
+            splitter   = me.getSplitter(),
+            splitWidth = splitter.getWidth(),
+            defaultMin = splitter.defaultSplitMin,
+            orient     = splitter.orientation,
+            prevBox    = me.prevBox,
+            prevCmp    = me.getPrevCmp(),
+            nextBox    = me.nextBox,
+            nextCmp    = me.getNextCmp(),
             
-            'beforerowremoved',
             
-            'beforerowsinserted',
             
-            'beforerefresh',
+            prevConstrainRegion, nextConstrainRegion;
+
+        
+        if (orient === 'vertical') {
+
             
-            'rowremoved',
             
-            'rowsinserted',
+            prevConstrainRegion = Ext.create('Ext.util.Region',
+                prevBox.y,
+                
+                
+                (prevCmp.maxWidth ? prevBox.x + prevCmp.maxWidth : nextBox.right - (nextCmp.minWidth || defaultMin)) + splitWidth,
+                prevBox.bottom,
+                prevBox.x + (prevCmp.minWidth || defaultMin)
+            );
             
-            'rowupdated',
+            nextConstrainRegion = Ext.create('Ext.util.Region',
+                nextBox.y,
+                nextBox.right - (nextCmp.minWidth || defaultMin),
+                nextBox.bottom,
+                
+                
+                (nextCmp.maxWidth ? nextBox.right - nextCmp.maxWidth : prevBox.x + (prevBox.minWidth || defaultMin)) - splitWidth
+            );
+        } else {
             
-            'refresh'
-        );
-        Ext.grid.GridView.superclass.constructor.call(this);
-    },
-
-    
-
-    
-    initTemplates : function(){
-        var ts = this.templates || {};
-        if(!ts.master){
-            ts.master = new Ext.Template(
-                '<div class="x-grid3" hidefocus="true">',
-                    '<div class="x-grid3-viewport">',
-                        '<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
-                        '<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
-                    '</div>',
-                    '<div class="x-grid3-resize-marker">&#160;</div>',
-                    '<div class="x-grid3-resize-proxy">&#160;</div>',
-                '</div>'
+            prevConstrainRegion = Ext.create('Ext.util.Region',
+                prevBox.y + (prevCmp.minHeight || defaultMin),
+                prevBox.right,
+                
+                
+                (prevCmp.maxHeight ? prevBox.y + prevCmp.maxHeight : nextBox.bottom - (nextCmp.minHeight || defaultMin)) + splitWidth,
+                prevBox.x
             );
-        }
-
-        if(!ts.header){
-            ts.header = new Ext.Template(
-                '<table border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
-                '<thead><tr class="x-grid3-hd-row">{cells}</tr></thead>',
-                '</table>'
+            
+            nextConstrainRegion = Ext.create('Ext.util.Region',
+                
+                
+                (nextCmp.maxHeight ? nextBox.bottom - nextCmp.maxHeight : prevBox.y + (prevCmp.minHeight || defaultMin)) - splitWidth,
+                nextBox.right,
+                nextBox.bottom - (nextCmp.minHeight || defaultMin),
+                nextBox.x
             );
         }
 
-        if(!ts.hcell){
-            ts.hcell = new Ext.Template(
-                '<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id} {css}" style="{style}"><div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}" unselectable="on" style="{istyle}">', this.grid.enableHdMenu ? '<a class="x-grid3-hd-btn" href="#"></a>' : '',
-                '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',
-                '</div></td>'
-            );
-        }
+        
+        return prevConstrainRegion.intersect(nextConstrainRegion);
+    },
 
-        if(!ts.body){
-            ts.body = new Ext.Template('{rows}');
-        }
+    
+    performResize: function(e) {
+        var me       = this,
+            offset   = me.getOffset('dragTarget'),
+            splitter = me.getSplitter(),
+            orient   = splitter.orientation,
+            prevCmp  = me.getPrevCmp(),
+            nextCmp  = me.getNextCmp(),
+            owner    = splitter.ownerCt,
+            layout   = owner.getLayout();
 
-        if(!ts.row){
-            ts.row = new Ext.Template(
-                '<div class="x-grid3-row {alt}" style="{tstyle}"><table class="x-grid3-row-table" border="0" cellspacing="0" cellpadding="0" style="{tstyle}">',
-                '<tbody><tr>{cells}</tr>',
-                (this.enableRowBody ? '<tr class="x-grid3-row-body-tr" style="{bodyStyle}"><td colspan="{cols}" class="x-grid3-body-cell" tabIndex="0" hidefocus="on"><div class="x-grid3-row-body">{body}</div></td></tr>' : ''),
-                '</tbody></table></div>'
-            );
-        }
+        
+        owner.suspendLayout = true;
 
-        if(!ts.cell){
-            ts.cell = new Ext.Template(
-                    '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
-                    '<div class="x-grid3-cell-inner x-grid3-col-{id}" unselectable="on" {attr}>{value}</div>',
-                    '</td>'
-                    );
+        if (orient === 'vertical') {
+            if (prevCmp) {
+                if (!prevCmp.maintainFlex) {
+                    delete prevCmp.flex;
+                    prevCmp.setSize(me.prevBox.width + offset[0], prevCmp.getHeight());
+                }
+            }
+            if (nextCmp) {
+                if (!nextCmp.maintainFlex) {
+                    delete nextCmp.flex;
+                    nextCmp.setSize(me.nextBox.width - offset[0], nextCmp.getHeight());
+                }
+            }
+        
+        } else {
+            if (prevCmp) {
+                if (!prevCmp.maintainFlex) {
+                    delete prevCmp.flex;
+                    prevCmp.setSize(prevCmp.getWidth(), me.prevBox.height + offset[1]);
+                }
+            }
+            if (nextCmp) {
+                if (!nextCmp.maintainFlex) {
+                    delete nextCmp.flex;
+                    nextCmp.setSize(prevCmp.getWidth(), me.nextBox.height - offset[1]);
+                }
+            }
         }
+        delete owner.suspendLayout;
+        layout.onLayout();
+    },
 
-        for(var k in ts){
-            var t = ts[k];
-            if(t && Ext.isFunction(t.compile) && !t.compiled){
-                t.disableFormats = true;
-                t.compile();
-            }
+    
+    
+    
+    endDrag: function () {
+        var me = this;
+
+        if (me.overlay) {
+             me.overlay.remove();
+             delete me.overlay;
         }
 
-        this.templates = ts;
-        this.colRe = new RegExp('x-grid3-td-([^\\s]+)', '');
+        me.callParent(arguments); 
     },
 
     
-    fly : function(el){
-        if(!this._flyweight){
-            this._flyweight = new Ext.Element.Flyweight(document.body);
-        }
-        this._flyweight.dom = el;
-        return this._flyweight;
+    onEnd: function(e) {
+        var me = this,
+            splitter = me.getSplitter();
+            
+        splitter.removeCls(splitter.baseCls + '-active');
+        me.performResize();
     },
 
     
-    getEditorParent : function(){
-        return this.scroller.dom;
+    
+    onDrag: function(e) {
+        var me        = this,
+            offset    = me.getOffset('dragTarget'),
+            splitter  = me.getSplitter(),
+            splitEl   = splitter.getEl(),
+            orient    = splitter.orientation;
+
+        if (orient === "vertical") {
+            splitEl.setX(me.startRegion.left + offset[0]);
+        } else {
+            splitEl.setY(me.startRegion.top + offset[1]);
+        }
     },
 
+    getSplitter: function() {
+        return Ext.getCmp(this.getDragCt().id);
+    }
+});
+
+Ext.define('Ext.selection.CellModel', {
+    extend: 'Ext.selection.Model',
+    alias: 'selection.cellmodel',
+    requires: ['Ext.util.KeyNav'],
+
+    
+    enableKeyNav: true,
+
     
-    initElements : function(){
-        var E = Ext.Element;
+    preventWrap: false,
 
-        var el = this.grid.getGridEl().dom.firstChild;
-        var cs = el.childNodes;
+    constructor: function(){
+        this.addEvents(
+            
+            'deselect',
 
-        this.el = new E(el);
+            
+            'select'
+        );
+        this.callParent(arguments);
+    },
 
-        this.mainWrap = new E(cs[0]);
-        this.mainHd = new E(this.mainWrap.dom.firstChild);
+    bindComponent: function(view) {
+        var me = this;
+        me.primaryView = view;
+        me.views = me.views || [];
+        me.views.push(view);
+        me.bind(view.getStore(), true);
+
+        view.on({
+            cellmousedown: me.onMouseDown,
+            refresh: me.onViewRefresh,
+            scope: me
+        });
 
-        if(this.grid.hideHeaders){
-            this.mainHd.setDisplayed(false);
+        if (me.enableKeyNav) {
+            me.initKeyNav(view);
         }
+    },
+
+    initKeyNav: function(view) {
+        var me = this;
 
-        this.innerHd = this.mainHd.dom.firstChild;
-        this.scroller = new E(this.mainWrap.dom.childNodes[1]);
-        if(this.forceFit){
-            this.scroller.setStyle('overflow-x', 'hidden');
+        if (!view.rendered) {
+            view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
+            return;
         }
+
+        view.el.set({
+            tabIndex: -1
+        });
+
+        
         
-        this.mainBody = new E(this.scroller.dom.firstChild);
+        me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
+            up: me.onKeyUp,
+            down: me.onKeyDown,
+            right: me.onKeyRight,
+            left: me.onKeyLeft,
+            tab: me.onKeyTab,
+            scope: me
+        });
+    },
 
-        this.focusEl = new E(this.scroller.dom.childNodes[1]);
-        this.focusEl.swallowEvent('click', true);
+    getHeaderCt: function() {
+        return this.primaryView.headerCt;
+    },
 
-        this.resizeMarker = new E(cs[1]);
-        this.resizeProxy = new E(cs[2]);
+    onKeyUp: function(e, t) {
+        this.move('up', e);
     },
 
-    
-    getRows : function(){
-        return this.hasRows() ? this.mainBody.dom.childNodes : [];
+    onKeyDown: function(e, t) {
+        this.move('down', e);
     },
 
-    
+    onKeyLeft: function(e, t) {
+        this.move('left', e);
+    },
 
-    
-    findCell : function(el){
-        if(!el){
-            return false;
-        }
-        return this.fly(el).findParent(this.cellSelector, this.cellSelectorDepth);
+    onKeyRight: function(e, t) {
+        this.move('right', e);
     },
 
-    
-    findCellIndex : function(el, requiredCls){
-        var cell = this.findCell(el);
-        if(cell && (!requiredCls || this.fly(cell).hasClass(requiredCls))){
-            return this.getCellIndex(cell);
+    move: function(dir, e) {
+        var me = this,
+            pos = me.primaryView.walkCells(me.getCurrentPosition(), dir, e, me.preventWrap);
+        if (pos) {
+            me.setCurrentPosition(pos);
         }
-        return false;
+        return pos;
     },
 
     
-    getCellIndex : function(el){
-        if(el){
-            var m = el.className.match(this.colRe);
-            if(m && m[1]){
-                return this.cm.getIndexById(m[1]);
-            }
-        }
-        return false;
+    getCurrentPosition: function() {
+        return this.position;
     },
 
     
-    findHeaderCell : function(el){
-        var cell = this.findCell(el);
-        return cell && this.fly(cell).hasClass(this.hdCls) ? cell : null;
+    setCurrentPosition: function(pos) {
+        var me = this;
+
+        if (me.position) {
+            me.onCellDeselect(me.position);
+        }
+        if (pos) {
+            me.onCellSelect(pos);
+        }
+        me.position = pos;
     },
 
     
-    findHeaderIndex : function(el){
-        return this.findCellIndex(el, this.hdCls);
+    onMouseDown: function(view, cell, cellIndex, record, row, rowIndex, e) {
+        this.setCurrentPosition({
+            row: rowIndex,
+            column: cellIndex
+        });
     },
 
     
-    findRow : function(el){
-        if(!el){
-            return false;
-        }
-        return this.fly(el).findParent(this.rowSelector, this.rowSelectorDepth);
+    
+    onCellSelect: function(position) {
+        var me = this,
+            store = me.view.getStore(),
+            record = store.getAt(position.row);
+
+        me.doSelect(record);
+        me.primaryView.onCellSelect(position);
+        
+        me.primaryView.onCellFocus(position);
+        me.fireEvent('select', me, record, position.row, position.column);
     },
 
     
-    findRowIndex : function(el){
-        var r = this.findRow(el);
-        return r ? r.rowIndex : false;
+    
+    onCellDeselect: function(position) {
+        var me = this,
+            store = me.view.getStore(),
+            record = store.getAt(position.row);
+
+        me.doDeselect(record);
+        me.primaryView.onCellDeselect(position);
+        me.fireEvent('deselect', me, record, position.row, position.column);
     },
 
-    
-    findRowBody : function(el){
-        if(!el){
-            return false;
+    onKeyTab: function(e, t) {
+        var me = this,
+            direction = e.shiftKey ? 'left' : 'right',
+            editingPlugin = me.view.editingPlugin,
+            position = me.move(direction, e);
+
+        if (editingPlugin && position && me.wasEditing) {
+            editingPlugin.startEditByPosition(position);
         }
-        return this.fly(el).findParent(this.rowBodySelector, this.rowBodySelectorDepth);
+        delete me.wasEditing;
     },
 
-    
+    onEditorTab: function(editingPlugin, e) {
+        var me = this,
+            direction = e.shiftKey ? 'left' : 'right',
+            position  = me.move(direction, e);
 
-    
-    getRow : function(row){
-        return this.getRows()[row];
+        if (position) {
+            editingPlugin.startEditByPosition(position);
+            me.wasEditing = true;
+        }
     },
 
-    
-    getCell : function(row, col){
-        return this.getRow(row).getElementsByTagName('td')[col];
+    refresh: function() {
+        var pos = this.getCurrentPosition();
+        if (pos) {
+            this.onCellSelect(pos);
+        }
     },
 
-    
-    getHeaderCell : function(index){
-        return this.mainHd.dom.getElementsByTagName('td')[index];
+    onViewRefresh: function() {
+        var pos = this.getCurrentPosition();
+        if (pos) {
+            this.onCellDeselect(pos);
+            this.setCurrentPosition(null);
+        }
     },
 
+    selectByPosition: function(position) {
+        this.setCurrentPosition(position);
+    }
+});
+
+Ext.define('Ext.selection.RowModel', {
+    extend: 'Ext.selection.Model',
+    alias: 'selection.rowmodel',
+    requires: ['Ext.util.KeyNav'],
+
     
+    deltaScroll: 5,
 
     
-    addRowClass : function(row, cls){
-        var r = this.getRow(row);
-        if(r){
-            this.fly(r).addClass(cls);
-        }
+    enableKeyNav: true,
+    
+    
+    ignoreRightMouseSelection: true,
+
+    constructor: function(){
+        this.addEvents(
+            
+            'beforedeselect',
+
+            
+            'beforeselect',
+
+            
+            'deselect',
+
+            
+            'select'
+        );
+        this.callParent(arguments);
     },
 
-    
-    removeRowClass : function(row, cls){
-        var r = this.getRow(row);
-        if(r){
-            this.fly(r).removeClass(cls);
+    bindComponent: function(view) {
+        var me = this;
+
+        me.views = me.views || [];
+        me.views.push(view);
+        me.bind(view.getStore(), true);
+
+        view.on({
+            itemmousedown: me.onRowMouseDown,
+            scope: me
+        });
+
+        if (me.enableKeyNav) {
+            me.initKeyNav(view);
         }
     },
 
-    
-    removeRow : function(row){
-        Ext.removeNode(this.getRow(row));
-        this.syncFocusEl(row);
+    initKeyNav: function(view) {
+        var me = this;
+
+        if (!view.rendered) {
+            view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
+            return;
+        }
+
+        view.el.set({
+            tabIndex: -1
+        });
+
+        
+        
+        me.keyNav = new Ext.util.KeyNav(view.el, {
+            up: me.onKeyUp,
+            down: me.onKeyDown,
+            right: me.onKeyRight,
+            left: me.onKeyLeft,
+            pageDown: me.onKeyPageDown,
+            pageUp: me.onKeyPageUp,
+            home: me.onKeyHome,
+            end: me.onKeyEnd,
+            scope: me
+        });
+        view.el.on(Ext.EventManager.getKeyEvent(), me.onKeyPress, me);
     },
 
     
-    removeRows : function(firstRow, lastRow){
-        var bd = this.mainBody.dom;
-        for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
-            Ext.removeNode(bd.childNodes[firstRow]);
+    
+    
+    getRowsVisible: function() {
+        var rowsVisible = false,
+            view = this.views[0],
+            row = view.getNode(0),
+            rowHeight, gridViewHeight;
+
+        if (row) {
+            rowHeight = Ext.fly(row).getHeight();
+            gridViewHeight = view.el.getHeight();
+            rowsVisible = Math.floor(gridViewHeight / rowHeight);
         }
-        this.syncFocusEl(firstRow);
+
+        return rowsVisible;
     },
 
     
+    onKeyEnd: function(e, t) {
+        var me = this,
+            last = me.store.getAt(me.store.getCount() - 1);
 
-    
-    getScrollState : function(){
-        var sb = this.scroller.dom;
-        return {left: sb.scrollLeft, top: sb.scrollTop};
+        if (last) {
+            if (e.shiftKey) {
+                me.selectRange(last, me.lastFocused || 0);
+                me.setLastFocused(last);
+            } else if (e.ctrlKey) {
+                me.setLastFocused(last);
+            } else {
+                me.doSelect(last);
+            }
+        }
     },
 
     
-    restoreScroll : function(state){
-        var sb = this.scroller.dom;
-        sb.scrollLeft = state.left;
-        sb.scrollTop = state.top;
+    onKeyHome: function(e, t) {
+        var me = this,
+            first = me.store.getAt(0);
+
+        if (first) {
+            if (e.shiftKey) {
+                me.selectRange(first, me.lastFocused || 0);
+                me.setLastFocused(first);
+            } else if (e.ctrlKey) {
+                me.setLastFocused(first);
+            } else {
+                me.doSelect(first, false);
+            }
+        }
     },
 
     
-    scrollToTop : function(){
-        this.scroller.dom.scrollTop = 0;
-        this.scroller.dom.scrollLeft = 0;
+    onKeyPageUp: function(e, t) {
+        var me = this,
+            rowsVisible = me.getRowsVisible(),
+            selIdx,
+            prevIdx,
+            prevRecord,
+            currRec;
+
+        if (rowsVisible) {
+            selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
+            prevIdx = selIdx - rowsVisible;
+            if (prevIdx < 0) {
+                prevIdx = 0;
+            }
+            prevRecord = me.store.getAt(prevIdx);
+            if (e.shiftKey) {
+                currRec = me.store.getAt(selIdx);
+                me.selectRange(prevRecord, currRec, e.ctrlKey, 'up');
+                me.setLastFocused(prevRecord);
+            } else if (e.ctrlKey) {
+                e.preventDefault();
+                me.setLastFocused(prevRecord);
+            } else {
+                me.doSelect(prevRecord);
+            }
+
+        }
     },
 
     
-    syncScroll : function(){
-        this.syncHeaderScroll();
-        var mb = this.scroller.dom;
-        this.grid.fireEvent('bodyscroll', mb.scrollLeft, mb.scrollTop);
+    onKeyPageDown: function(e, t) {
+        var me = this,
+            rowsVisible = me.getRowsVisible(),
+            selIdx,
+            nextIdx,
+            nextRecord,
+            currRec;
+
+        if (rowsVisible) {
+            selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
+            nextIdx = selIdx + rowsVisible;
+            if (nextIdx >= me.store.getCount()) {
+                nextIdx = me.store.getCount() - 1;
+            }
+            nextRecord = me.store.getAt(nextIdx);
+            if (e.shiftKey) {
+                currRec = me.store.getAt(selIdx);
+                me.selectRange(nextRecord, currRec, e.ctrlKey, 'down');
+                me.setLastFocused(nextRecord);
+            } else if (e.ctrlKey) {
+                
+                
+                e.preventDefault();
+                me.setLastFocused(nextRecord);
+            } else {
+                me.doSelect(nextRecord);
+            }
+        }
     },
 
     
-    syncHeaderScroll : function(){
-        var mb = this.scroller.dom;
-        this.innerHd.scrollLeft = mb.scrollLeft;
-        this.innerHd.scrollLeft = mb.scrollLeft; 
+    
+    onKeyPress: function(e, t) {
+        if (e.getKey() === e.SPACE) {
+            e.stopEvent();
+            var me = this,
+                record = me.lastFocused;
+
+            if (record) {
+                if (me.isSelected(record)) {
+                    me.doDeselect(record, false);
+                } else {
+                    me.doSelect(record, true);
+                }
+            }
+        }
     },
 
     
-    updateSortIcon : function(col, dir){
-        var sc = this.sortClasses;
-        var hds = this.mainHd.select('td').removeClass(sc);
-        hds.item(col).addClass(sc[dir == 'DESC' ? 1 : 0]);
+    
+    
+    onKeyUp: function(e, t) {
+        var me = this,
+            view = me.views[0],
+            idx  = me.store.indexOf(me.lastFocused),
+            record;
+
+        if (idx > 0) {
+            
+            
+            record = me.store.getAt(idx - 1);
+            if (e.shiftKey && me.lastFocused) {
+                if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
+                    me.doDeselect(me.lastFocused, true);
+                    me.setLastFocused(record);
+                } else if (!me.isSelected(me.lastFocused)) {
+                    me.doSelect(me.lastFocused, true);
+                    me.doSelect(record, true);
+                } else {
+                    me.doSelect(record, true);
+                }
+            } else if (e.ctrlKey) {
+                me.setLastFocused(record);
+            } else {
+                me.doSelect(record);
+                
+            }
+        }
+        
+        
+        
+        
+        
+        
+        
     },
 
     
-    updateAllColumnWidths : function(){
-        var tw   = this.getTotalWidth(),
-            clen = this.cm.getColumnCount(),
-            ws   = [],
-            len,
-            i;
+    
+    
+    onKeyDown: function(e, t) {
+        var me = this,
+            view = me.views[0],
+            idx  = me.store.indexOf(me.lastFocused),
+            record;
 
-        for(i = 0; i < clen; i++){
-            ws[i] = this.getColumnWidth(i);
+        
+        
+        if (idx + 1 < me.store.getCount()) {
+            record = me.store.getAt(idx + 1);
+            if (me.selected.getCount() === 0) {
+                me.doSelect(record);
+                
+            } else if (e.shiftKey && me.lastFocused) {
+                if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
+                    me.doDeselect(me.lastFocused, true);
+                    me.setLastFocused(record);
+                } else if (!me.isSelected(me.lastFocused)) {
+                    me.doSelect(me.lastFocused, true);
+                    me.doSelect(record, true);
+                } else {
+                    me.doSelect(record, true);
+                }
+            } else if (e.ctrlKey) {
+                me.setLastFocused(record);
+            } else {
+                me.doSelect(record);
+                
+            }
         }
+    },
 
-        this.innerHd.firstChild.style.width = this.getOffsetWidth();
-        this.innerHd.firstChild.firstChild.style.width = tw;
-        this.mainBody.dom.style.width = tw;
+    scrollByDeltaX: function(delta) {
+        var view    = this.views[0],
+            section = view.up(),
+            hScroll = section.horizontalScroller;
 
-        for(i = 0; i < clen; i++){
-            var hd = this.getHeaderCell(i);
-            hd.style.width = ws[i];
+        if (hScroll) {
+            hScroll.scrollByDeltaX(delta);
         }
+    },
 
-        var ns = this.getRows(), row, trow;
-        for(i = 0, len = ns.length; i < len; i++){
-            row = ns[i];
-            row.style.width = tw;
-            if(row.firstChild){
-                row.firstChild.style.width = tw;
-                trow = row.firstChild.rows[0];
-                for (var j = 0; j < clen; j++) {
-                   trow.childNodes[j].style.width = ws[j];
-                }
-            }
-        }
+    onKeyLeft: function(e, t) {
+        this.scrollByDeltaX(-this.deltaScroll);
+    },
 
-        this.onAllColumnWidthsUpdated(ws, tw);
+    onKeyRight: function(e, t) {
+        this.scrollByDeltaX(this.deltaScroll);
     },
 
     
-    updateColumnWidth : function(col, width){
-        var w = this.getColumnWidth(col);
-        var tw = this.getTotalWidth();
-        this.innerHd.firstChild.style.width = this.getOffsetWidth();
-        this.innerHd.firstChild.firstChild.style.width = tw;
-        this.mainBody.dom.style.width = tw;
-        var hd = this.getHeaderCell(col);
-        hd.style.width = w;
-
-        var ns = this.getRows(), row;
-        for(var i = 0, len = ns.length; i < len; i++){
-            row = ns[i];
-            row.style.width = tw;
-            if(row.firstChild){
-                row.firstChild.style.width = tw;
-                row.firstChild.rows[0].childNodes[col].style.width = w;
-            }
+    
+    onRowMouseDown: function(view, record, item, index, e) {
+        view.el.focus();
+        if (!this.allowRightMouseSelection(e)) {
+            return;
         }
-
-        this.onColumnWidthUpdated(col, w, tw);
+        this.selectWithEvent(record, e);
     },
-
     
-    updateColumnHidden : function(col, hidden){
-        var tw = this.getTotalWidth();
-        this.innerHd.firstChild.style.width = this.getOffsetWidth();
-        this.innerHd.firstChild.firstChild.style.width = tw;
-        this.mainBody.dom.style.width = tw;
-        var display = hidden ? 'none' : '';
-
-        var hd = this.getHeaderCell(col);
-        hd.style.display = display;
-
-        var ns = this.getRows(), row;
-        for(var i = 0, len = ns.length; i < len; i++){
-            row = ns[i];
-            row.style.width = tw;
-            if(row.firstChild){
-                row.firstChild.style.width = tw;
-                row.firstChild.rows[0].childNodes[col].style.display = display;
-            }
+    
+    allowRightMouseSelection: function(e) {
+        var disallow = this.ignoreRightMouseSelection && e.button !== 0;
+        if (disallow) {
+            disallow = this.hasSelection();
         }
-
-        this.onColumnHiddenUpdated(col, hidden, tw);
-        delete this.lastViewWidth; 
-        this.layout();
+        return !disallow;
     },
 
     
-    doRender : function(columns, records, store, startRow, colCount, stripe) {
-        var templates    = this.templates,
-            cellTemplate = templates.cell,
-            rowTemplate  = templates.row,
-            last         = colCount - 1;
-
-        var tstyle = 'width:' + this.getTotalWidth() + ';';
-
-        
-        var rowBuffer = [],
-            colBuffer = [],
-            rowParams = {tstyle: tstyle},
-            meta      = {},
-            column,
-            record;
-
-        
-        for (var j = 0, len = records.length; j < len; j++) {
-            record    = records[j];
-            colBuffer = [];
-
-            var rowIndex = j + startRow;
-
-            
-            for (var i = 0; i < colCount; i++) {
-                column = columns[i];
-
-                meta.id    = column.id;
-                meta.css   = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
-                meta.attr  = meta.cellAttr = '';
-                meta.style = column.style;
-                meta.value = column.renderer.call(column.scope, record.data[column.name], meta, record, rowIndex, i, store);
+    
+    onSelectChange: function(record, isSelected, suppressEvent, commitFn) {
+        var me      = this,
+            views   = me.views,
+            viewsLn = views.length,
+            store   = me.store,
+            rowIdx  = store.indexOf(record),
+            eventName = isSelected ? 'select' : 'deselect',
+            i = 0;
 
-                if (Ext.isEmpty(meta.value)) {
-                    meta.value = '&#160;';
-                }
+        if ((suppressEvent || me.fireEvent('before' + eventName, me, record, rowIdx)) !== false &&
+                commitFn() !== false) {
 
-                if (this.markDirty && record.dirty && Ext.isDefined(record.modified[column.name])) {
-                    meta.css += ' x-grid3-dirty-cell';
+            for (; i < viewsLn; i++) {
+                if (isSelected) {
+                    views[i].onRowSelect(rowIdx, suppressEvent);
+                } else {
+                    views[i].onRowDeselect(rowIdx, suppressEvent);
                 }
-
-                colBuffer[colBuffer.length] = cellTemplate.apply(meta);
             }
 
-            
-            var alt = [];
-
-            if (stripe && ((rowIndex + 1) % 2 === 0)) {
-                alt[0] = 'x-grid3-row-alt';
-            }
-
-            if (record.dirty) {
-                alt[1] = ' x-grid3-dirty-row';
+            if (!suppressEvent) {
+                me.fireEvent(eventName, me, record, rowIdx);
             }
-
-            rowParams.cols = colCount;
-
-            if (this.getRowClass) {
-                alt[2] = this.getRowClass(record, rowIndex, rowParams, store);
-            }
-
-            rowParams.alt   = alt.join(' ');
-            rowParams.cells = colBuffer.join('');
-
-            rowBuffer[rowBuffer.length] = rowTemplate.apply(rowParams);
         }
-
-        return rowBuffer.join('');
     },
 
     
-    processRows : function(startRow, skipStripe) {
-        if (!this.ds || this.ds.getCount() < 1) {
-            return;
-        }
-
-        var rows = this.getRows(),
-            len  = rows.length,
-            i, r;
-
-        skipStripe = skipStripe || !this.grid.stripeRows;
-        startRow   = startRow   || 0;
+    
+    onLastFocusChanged: function(oldFocused, newFocused, supressFocus) {
+        var views   = this.views,
+            viewsLn = views.length,
+            store   = this.store,
+            rowIdx,
+            i = 0;
 
-        for (i = 0; i<len; i++) {
-            r = rows[i];
-            if (r) {
-                r.rowIndex = i;
-                if (!skipStripe) {
-                    r.className = r.className.replace(this.rowClsRe, ' ');
-                    if ((i + 1) % 2 === 0){
-                        r.className += ' x-grid3-row-alt';
-                    }
+        if (oldFocused) {
+            rowIdx = store.indexOf(oldFocused);
+            if (rowIdx != -1) {
+                for (; i < viewsLn; i++) {
+                    views[i].onRowFocus(rowIdx, false);
                 }
             }
         }
 
-        
-        if (startRow === 0) {
-            Ext.fly(rows[0]).addClass(this.firstRowCls);
+        if (newFocused) {
+            rowIdx = store.indexOf(newFocused);
+            if (rowIdx != -1) {
+                for (i = 0; i < viewsLn; i++) {
+                    views[i].onRowFocus(rowIdx, true, supressFocus);
+                }
+            }
         }
-
-        Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
     },
 
-    afterRender : function(){
-        if(!this.ds || !this.cm){
-            return;
-        }
-        this.mainBody.dom.innerHTML = this.renderRows() || '&#160;';
-        this.processRows(0, true);
+    onEditorTab: function(editingPlugin, e) {
+        var me = this,
+            view = me.views[0],
+            record = editingPlugin.getActiveRecord(),
+            header = editingPlugin.getActiveColumn(),
+            position = view.getPosition(record, header),
+            direction = e.shiftKey ? 'left' : 'right',
+            newPosition  = view.walkCells(position, direction, e, this.preventWrap);
 
-        if(this.deferEmptyText !== true){
-            this.applyEmptyText();
+        if (newPosition) {
+            editingPlugin.startEditByPosition(newPosition);
         }
-        this.grid.fireEvent('viewready', this.grid);
     },
 
-    
-    renderUI : function() {
-        var templates = this.templates,
-            header    = this.renderHeaders(),
-            body      = templates.body.apply({rows:'&#160;'});
+    selectByPosition: function(position) {
+        var record = this.store.getAt(position.row);
+        this.select(record);
+    }
+});
 
-        var html = templates.master.apply({
-            body  : body,
-            header: header,
-            ostyle: 'width:' + this.getOffsetWidth() + ';',
-            bstyle: 'width:' + this.getTotalWidth()  + ';'
-        });
+Ext.define('Ext.selection.CheckboxModel', {
+    alias: 'selection.checkboxmodel',
+    extend: 'Ext.selection.RowModel',
 
-        var g = this.grid;
+    
+    mode: 'MULTI',
 
-        g.getGridEl().dom.innerHTML = html;
+    
+    injectCheckbox: 0,
 
-        this.initElements();
+    
+    checkOnly: false,
 
-        
-        Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
+    headerWidth: 24,
 
-        this.mainHd.on({
-            scope    : this,
-            mouseover: this.handleHdOver,
-            mouseout : this.handleHdOut,
-            mousemove: this.handleHdMove
-        });
+    
+    checkerOnCls: Ext.baseCSSPrefix + 'grid-hd-checker-on',
 
-        this.scroller.on('scroll', this.syncScroll,  this);
-        if (g.enableColumnResize !== false) {
-            this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
-        }
+    bindComponent: function(view) {
+        var me = this;
 
-        if (g.enableColumnMove) {
-            this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
-            this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
+        me.sortable = false;
+        me.callParent(arguments);
+        if (!me.hasLockedHeader() || view.headerCt.lockedCt) {
+            
+            view.headerCt.on('headerclick', me.onHeaderClick, me);
+            me.addCheckbox(true);
+            me.mon(view.ownerCt, 'reconfigure', me.addCheckbox, me);
         }
+    },
 
-        if (g.enableHdMenu !== false) {
-            this.hmenu = new Ext.menu.Menu({id: g.id + '-hctx'});
-            this.hmenu.add(
-                {itemId:'asc',  text: this.sortAscText,  cls: 'xg-hmenu-sort-asc'},
-                {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
-            );
-
-            if (g.enableColumnHide !== false) {
-                this.colMenu = new Ext.menu.Menu({id:g.id + '-hcols-menu'});
-                this.colMenu.on({
-                    scope     : this,
-                    beforeshow: this.beforeColMenuShow,
-                    itemclick : this.handleHdMenuClick
-                });
-                this.hmenu.add('-', {
-                    itemId:'columns',
-                    hideOnClick: false,
-                    text: this.columnsText,
-                    menu: this.colMenu,
-                    iconCls: 'x-cols-icon'
-                });
+    hasLockedHeader: function(){
+        var hasLocked = false;
+        Ext.each(this.views, function(view){
+            if (view.headerCt.lockedCt) {
+                hasLocked = true;
+                return false;
             }
+        });
+        return hasLocked;
+    },
 
-            this.hmenu.on('itemclick', this.handleHdMenuClick, this);
-        }
+    
+    addCheckbox: function(initial){
+        var me = this,
+            checkbox = me.injectCheckbox,
+            view = me.views[0],
+            headerCt = view.headerCt;
 
-        if (g.trackMouseOver) {
-            this.mainBody.on({
-                scope    : this,
-                mouseover: this.onRowOver,
-                mouseout : this.onRowOut
-            });
+        if (checkbox !== false) {
+            if (checkbox == 'first') {
+                checkbox = 0;
+            } else if (checkbox == 'last') {
+                checkbox = headerCt.getColumnCount();
+            }
+            headerCt.add(checkbox,  me.getHeaderConfig());
         }
 
-        if (g.enableDragDrop || g.enableDrag) {
-            this.dragZone = new Ext.grid.GridDragZone(g, {
-                ddGroup : g.ddGroup || 'GridDD'
-            });
+        if (initial !== true) {
+            view.refresh();
         }
-
-        this.updateHeaderSortState();
     },
 
     
-    processEvent : function(name, e) {
-        var t = e.getTarget(),
-            g = this.grid,
-            header = this.findHeaderIndex(t);
-        g.fireEvent(name, e);
-        if (header !== false) {
-            g.fireEvent('header' + name, g, header, e);
-        } else {
-            var row = this.findRowIndex(t),
-                cell,
-                body;
-            if (row !== false) {
-                g.fireEvent('row' + name, g, row, e);
-                cell = this.findCellIndex(t);
-                if (cell !== false) {
-                    g.fireEvent('cell' + name, g, row, cell, e);
-                } else {
-                    body = this.findRowBody(t);
-                    if (body) {
-                        g.fireEvent('rowbody' + name, g, row, e);
-                    }
-                }
+    toggleUiHeader: function(isChecked) {
+        var view     = this.views[0],
+            headerCt = view.headerCt,
+            checkHd  = headerCt.child('gridcolumn[isCheckerHd]');
+
+        if (checkHd) {
+            if (isChecked) {
+                checkHd.el.addCls(this.checkerOnCls);
             } else {
-                g.fireEvent('container' + name, g, e);
+                checkHd.el.removeCls(this.checkerOnCls);
             }
         }
     },
 
     
-    layout : function() {
-        if(!this.mainBody){
-            return; 
-        }
-        var g = this.grid;
-        var c = g.getGridEl();
-        var csize = c.getSize(true);
-        var vw = csize.width;
-
-        if(!g.hideHeaders && (vw < 20 || csize.height < 20)){ 
-            return;
-        }
-
-        if(g.autoHeight){
-            this.scroller.dom.style.overflow = 'visible';
-            if(Ext.isWebKit){
-                this.scroller.dom.style.position = 'static';
-            }
-        }else{
-            this.el.setSize(csize.width, csize.height);
-
-            var hdHeight = this.mainHd.getHeight();
-            var vh = csize.height - (hdHeight);
-
-            this.scroller.setSize(vw, vh);
-            if(this.innerHd){
-                this.innerHd.style.width = (vw)+'px';
-            }
-        }
-        if(this.forceFit){
-            if(this.lastViewWidth != vw){
-                this.fitColumns(false, false);
-                this.lastViewWidth = vw;
+    onHeaderClick: function(headerCt, header, e) {
+        if (header.isCheckerHd) {
+            e.stopEvent();
+            var isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on');
+            if (isChecked) {
+                
+                this.deselectAll(true);
+            } else {
+                
+                this.selectAll(true);
             }
-        }else {
-            this.autoExpand();
-            this.syncHeaderScroll();
         }
-        this.onLayout(vw, vh);
     },
 
     
-    
-    onLayout : function(vw, vh){
-        
-    },
+    getHeaderConfig: function() {
+        var me = this;
 
-    onColumnWidthUpdated : function(col, w, tw){
-        
+        return {
+            isCheckerHd: true,
+            text : '&#160;',
+            width: me.headerWidth,
+            sortable: false,
+            draggable: false,
+            resizable: false,
+            hideable: false,
+            menuDisabled: true,
+            dataIndex: '',
+            cls: Ext.baseCSSPrefix + 'column-header-checkbox ',
+            renderer: Ext.Function.bind(me.renderer, me),
+            locked: me.hasLockedHeader()
+        };
     },
 
-    onAllColumnWidthsUpdated : function(ws, tw){
-        
+    
+    renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
+        metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
+        return '<div class="' + Ext.baseCSSPrefix + 'grid-row-checker">&#160;</div>';
     },
 
-    onColumnHiddenUpdated : function(col, hidden, tw){
-        
-    },
+    
+    onRowMouseDown: function(view, record, item, index, e) {
+        view.el.focus();
+        var me = this,
+            checker = e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-checker');
+            
+        if (!me.allowRightMouseSelection(e)) {
+            return;
+        }
 
-    updateColumnText : function(col, text){
         
-    },
+        if (me.checkOnly && !checker) {
+            return;
+        }
 
-    afterMove : function(colIndex){
-        
+        if (checker) {
+            var mode = me.getSelectionMode();
+            
+            
+            if (mode !== 'SINGLE') {
+                me.setSelectionMode('SIMPLE');
+            }
+            me.selectWithEvent(record, e);
+            me.setSelectionMode(mode);
+        } else {
+            me.selectWithEvent(record, e);
+        }
     },
 
     
-    
-    init : function(grid){
-        this.grid = grid;
+    onSelectChange: function() {
+        this.callParent(arguments);
 
-        this.initTemplates();
-        this.initData(grid.store, grid.colModel);
-        this.initUI(grid);
-    },
+        
+        var hdSelectStatus = this.selected.getCount() === this.store.getCount();
+        this.toggleUiHeader(hdSelectStatus);
+    }
+});
 
-    
-    getColumnId : function(index){
-      return this.cm.getColumnId(index);
-    },
 
+Ext.define('Ext.selection.TreeModel', {
+    extend: 'Ext.selection.RowModel',
+    alias: 'selection.treemodel',
     
-    getOffsetWidth : function() {
-        return (this.cm.getTotalWidth() + this.getScrollOffset()) + 'px';
-    },
-
-    getScrollOffset: function(){
-        return Ext.num(this.scrollOffset, Ext.getScrollBarWidth());
+    
+    
+    
+    pruneRemoved: false,
+    
+    onKeyRight: function(e, t) {
+        var focused = this.getLastFocused(),
+            view    = this.view;
+            
+        if (focused) {
+            
+            
+            
+            if (focused.isExpanded()) {
+                this.onKeyDown(e, t);
+            
+            } else if (!focused.isLeaf()) {
+                view.expand(focused);
+            }
+        }
     },
-
     
-    renderHeaders : function() {
-        var cm   = this.cm,
-            ts   = this.templates,
-            ct   = ts.hcell,
-            cb   = [],
-            p    = {},
-            len  = cm.getColumnCount(),
-            last = len - 1;
-
-        for (var i = 0; i < len; i++) {
-            p.id = cm.getColumnId(i);
-            p.value = cm.getColumnHeader(i) || '';
-            p.style = this.getColumnStyle(i, true);
-            p.tooltip = this.getColumnTooltip(i);
-            p.css = i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
+    onKeyLeft: function(e, t) {
+        var focused = this.getLastFocused(),
+            view    = this.view,
+            viewSm  = view.getSelectionModel(),
+            parentNode, parentRecord;
 
-            if (cm.config[i].align == 'right') {
-                p.istyle = 'padding-right:16px';
-            } else {
-                delete p.istyle;
+        if (focused) {
+            parentNode = focused.parentNode;
+            
+            if (focused.isExpanded()) {
+                view.collapse(focused);
+            
+            
+            } else if (parentNode && !parentNode.isRoot()) {
+                
+                if (e.shiftKey) {
+                    viewSm.selectRange(parentNode, focused, e.ctrlKey, 'up');
+                    viewSm.setLastFocused(parentNode);
+                
+                } else if (e.ctrlKey) {
+                    viewSm.setLastFocused(parentNode);
+                
+                } else {
+                    viewSm.select(parentNode);
+                }
             }
-            cb[cb.length] = ct.apply(p);
         }
-        return ts.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'});
     },
-
     
-    getColumnTooltip : function(i){
-        var tt = this.cm.getColumnTooltip(i);
-        if(tt){
-            if(Ext.QuickTips.isEnabled()){
-                return 'ext:qtip="'+tt+'"';
-            }else{
-                return 'title="'+tt+'"';
+    onKeyPress: function(e, t) {
+        var key = e.getKey(),
+            selected, 
+            checked;
+        
+        if (key === e.SPACE || key === e.ENTER) {
+            e.stopEvent();
+            selected = this.getLastSelected();
+            if (selected) {
+                this.view.onCheckChange(selected);
             }
+        } else {
+            this.callParent(arguments);
         }
-        return '';
-    },
+    }
+});
 
-    
-    beforeUpdate : function(){
-        this.grid.stopEditing(true);
-    },
 
+Ext.define('Ext.slider.Thumb', {
+    requires: ['Ext.dd.DragTracker', 'Ext.util.Format'],
     
-    updateHeaders : function(){
-        this.innerHd.firstChild.innerHTML = this.renderHeaders();
-        this.innerHd.firstChild.style.width = this.getOffsetWidth();
-        this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
-    },
+    topZIndex: 10000,
 
     
-    focusRow : function(row){
-        this.focusCell(row, 0, false);
-    },
 
     
-    focusCell : function(row, col, hscroll){
-        this.syncFocusEl(this.ensureVisible(row, col, hscroll));
-        if(Ext.isGecko){
-            this.focusEl.focus();
-        }else{
-            this.focusEl.focus.defer(1, this.focusEl);
+    constructor: function(config) {
+        var me = this;
+
+        
+        Ext.apply(me, config || {}, {
+            cls: Ext.baseCSSPrefix + 'slider-thumb',
+
+            
+            constrain: false
+        });
+        me.callParent([config]);
+
+        if (me.slider.vertical) {
+            Ext.apply(me, Ext.slider.Thumb.Vertical);
         }
     },
 
-    resolveCell : function(row, col, hscroll){
-        if(!Ext.isNumber(row)){
-            row = row.rowIndex;
-        }
-        if(!this.ds){
-            return null;
-        }
-        if(row < 0 || row >= this.ds.getCount()){
-            return null;
-        }
-        col = (col !== undefined ? col : 0);
+    
+    render: function() {
+        var me = this;
 
-        var rowEl = this.getRow(row),
-            cm = this.cm,
-            colCount = cm.getColumnCount(),
-            cellEl;
-        if(!(hscroll === false && col === 0)){
-            while(col < colCount && cm.isHidden(col)){
-                col++;
-            }
-            cellEl = this.getCell(row, col);
+        me.el = me.slider.innerEl.insertFirst({cls: me.cls});
+        if (me.disabled) {
+            me.disable();
         }
-
-        return {row: rowEl, cell: cellEl};
+        me.initEvents();
     },
 
-    getResolvedXY : function(resolved){
-        if(!resolved){
-            return null;
+    
+    move: function(v, animate){
+        if(!animate){
+            this.el.setLeft(v);
+        }else{
+            Ext.create('Ext.fx.Anim', {
+                target: this.el,
+                duration: 350,
+                to: {
+                    left: v
+                }
+            });
         }
-        var s = this.scroller.dom, c = resolved.cell, r = resolved.row;
-        return c ? Ext.fly(c).getXY() : [this.el.getX(), Ext.fly(r).getY()];
     },
 
-    syncFocusEl : function(row, col, hscroll){
-        var xy = row;
-        if(!Ext.isArray(xy)){
-            row = Math.min(row, Math.max(0, this.getRows().length-1));
-            if (isNaN(row)) {
-                return;
-            }
-            xy = this.getResolvedXY(this.resolveCell(row, col, hscroll));
-        }
-        this.focusEl.setXY(xy||this.scroller.getXY());
+    
+    bringToFront: function() {
+        this.el.setStyle('zIndex', this.topZIndex);
     },
 
-    ensureVisible : function(row, col, hscroll){
-        var resolved = this.resolveCell(row, col, hscroll);
-        if(!resolved || !resolved.row){
-            return;
-        }
+    
+    sendToBack: function() {
+        this.el.setStyle('zIndex', '');
+    },
 
-        var rowEl = resolved.row,
-            cellEl = resolved.cell,
-            c = this.scroller.dom,
-            ctop = 0,
-            p = rowEl,
-            stop = this.el.dom;
+    
+    enable: function() {
+        var me = this;
 
-        while(p && p != stop){
-            ctop += p.offsetTop;
-            p = p.offsetParent;
+        me.disabled = false;
+        if (me.el) {
+            me.el.removeCls(me.slider.disabledCls);
         }
+    },
 
-        ctop -= this.mainHd.dom.offsetHeight;
-        stop = parseInt(c.scrollTop, 10);
-
-        var cbot = ctop + rowEl.offsetHeight,
-            ch = c.clientHeight,
-            sbot = stop + ch;
-
+    
+    disable: function() {
+        var me = this;
 
-        if(ctop < stop){
-          c.scrollTop = ctop;
-        }else if(cbot > sbot){
-            c.scrollTop = cbot-ch;
+        me.disabled = true;
+        if (me.el) {
+            me.el.addCls(me.slider.disabledCls);
         }
+    },
+
+    
+    initEvents: function() {
+        var me = this,
+            el = me.el;
 
-        if(hscroll !== false){
-            var cleft = parseInt(cellEl.offsetLeft, 10);
-            var cright = cleft + cellEl.offsetWidth;
+        me.tracker = Ext.create('Ext.dd.DragTracker', {
+            onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me),
+            onStart      : Ext.Function.bind(me.onDragStart, me),
+            onDrag       : Ext.Function.bind(me.onDrag, me),
+            onEnd        : Ext.Function.bind(me.onDragEnd, me),
+            tolerance    : 3,
+            autoStart    : 300,
+            overCls      : Ext.baseCSSPrefix + 'slider-thumb-over'
+        });
 
-            var sleft = parseInt(c.scrollLeft, 10);
-            var sright = sleft + c.clientWidth;
-            if(cleft < sleft){
-                c.scrollLeft = cleft;
-            }else if(cright > sright){
-                c.scrollLeft = cright-c.clientWidth;
-            }
-        }
-        return this.getResolvedXY(resolved);
+        me.tracker.initEl(el);
     },
 
     
-    insertRows : function(dm, firstRow, lastRow, isUpdate) {
-        var last = dm.getCount() - 1;
-        if( !isUpdate && firstRow === 0 && lastRow >= last) {
-            this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
-                this.refresh();
-            this.fireEvent('rowsinserted', this, firstRow, lastRow);
+    onBeforeDragStart : function(e) {
+        if (this.disabled) {
+            return false;
         } else {
-            if (!isUpdate) {
-                this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
-            }
-            var html = this.renderRows(firstRow, lastRow),
-                before = this.getRow(firstRow);
-            if (before) {
-                if(firstRow === 0){
-                    Ext.fly(this.getRow(0)).removeClass(this.firstRowCls);
-                }
-                Ext.DomHelper.insertHtml('beforeBegin', before, html);
-            } else {
-                var r = this.getRow(last - 1);
-                if(r){
-                    Ext.fly(r).removeClass(this.lastRowCls);
-                }
-                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
-            }
-            if (!isUpdate) {
-                this.fireEvent('rowsinserted', this, firstRow, lastRow);
-                this.processRows(firstRow);
-            } else if (firstRow === 0 || firstRow >= last) {
-                
-                Ext.fly(this.getRow(firstRow)).addClass(firstRow === 0 ? this.firstRowCls : this.lastRowCls);
-            }
+            this.slider.promoteThumb(this);
+            return true;
         }
-        this.syncFocusEl(firstRow);
     },
 
     
-    deleteRows : function(dm, firstRow, lastRow){
-        if(dm.getRowCount()<1){
-            this.refresh();
-        }else{
-            this.fireEvent('beforerowsdeleted', this, firstRow, lastRow);
+    onDragStart: function(e){
+        var me = this;
 
-            this.removeRows(firstRow, lastRow);
+        me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
+        me.dragging = true;
+        me.dragStartValue = me.value;
 
-            this.processRows(firstRow);
-            this.fireEvent('rowsdeleted', this, firstRow, lastRow);
-        }
+        me.slider.fireEvent('dragstart', me.slider, e, me);
     },
 
     
-    getColumnStyle : function(col, isHeader){
-        var style = !isHeader ? (this.cm.config[col].css || '') : '';
-        style += 'width:'+this.getColumnWidth(col)+';';
-        if(this.cm.isHidden(col)){
-            style += 'display:none;';
-        }
-        var align = this.cm.config[col].align;
-        if(align){
-            style += 'text-align:'+align+';';
-        }
-        return style;
-    },
+    onDrag: function(e) {
+        var me       = this,
+            slider   = me.slider,
+            index    = me.index,
+            newValue = me.getNewValue(),
+            above,
+            below;
 
-    
-    getColumnWidth : function(col){
-        var w = this.cm.getColumnWidth(col);
-        if(Ext.isNumber(w)){
-            return (Ext.isBorderBox || (Ext.isWebKit && !Ext.isSafari2) ? w : (w - this.borderWidth > 0 ? w - this.borderWidth : 0)) + 'px';
+        if (me.constrain) {
+            above = slider.thumbs[index + 1];
+            below = slider.thumbs[index - 1];
+
+            if (below !== undefined && newValue <= below.value) {
+                newValue = below.value;
+            }
+
+            if (above !== undefined && newValue >= above.value) {
+                newValue = above.value;
+            }
         }
-        return w;
+
+        slider.setValue(index, newValue, false);
+        slider.fireEvent('drag', slider, e, me);
     },
 
-    
-    getTotalWidth : function(){
-        return this.cm.getTotalWidth()+'px';
+    getNewValue: function() {
+        var slider = this.slider,
+            pos = slider.innerEl.translatePoints(this.tracker.getXY());
+
+        return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
     },
 
     
-    fitColumns : function(preventRefresh, onlyExpand, omitColumn){
-        var cm = this.cm, i;
-        var tw = cm.getTotalWidth(false);
-        var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
+    onDragEnd: function(e) {
+        var me     = this,
+            slider = me.slider,
+            value  = me.value;
 
-        if(aw < 20){ 
-            return;
-        }
-        var extra = aw - tw;
+        me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
 
-        if(extra === 0){
-            return false;
-        }
+        me.dragging = false;
+        slider.fireEvent('dragend', slider, e);
 
-        var vc = cm.getColumnCount(true);
-        var ac = vc-(Ext.isNumber(omitColumn) ? 1 : 0);
-        if(ac === 0){
-            ac = 1;
-            omitColumn = undefined;
+        if (me.dragStartValue != value) {
+            slider.fireEvent('changecomplete', slider, value, me);
         }
-        var colCount = cm.getColumnCount();
-        var cols = [];
-        var extraCol = 0;
-        var width = 0;
-        var w;
-        for (i = 0; i < colCount; i++){
-            if(!cm.isFixed(i) && i !== omitColumn){
-                w = cm.getColumnWidth(i);
-                cols.push(i, w);
-                if(!cm.isHidden(i)){
-                    extraCol = i;
-                    width += w;
+    },
+
+    destroy: function() {
+        Ext.destroy(this.tracker);
+    },
+    statics: {
+        
+        Vertical: {
+            getNewValue: function() {
+                var slider   = this.slider,
+                    innerEl  = slider.innerEl,
+                    pos      = innerEl.translatePoints(this.tracker.getXY()),
+                    bottom   = innerEl.getHeight() - pos.top;
+
+                return Ext.util.Format.round(slider.reverseValue(bottom), slider.decimalPrecision);
+            },
+            move: function(v, animate) {
+                if (!animate) {
+                    this.el.setBottom(v);
+                } else {
+                    Ext.create('Ext.fx.Anim', {
+                        target: this.el,
+                        duration: 350,
+                        to: {
+                            bottom: v
+                        }
+                    });
                 }
             }
         }
-        var frac = (aw - cm.getTotalWidth())/width;
-        while (cols.length){
-            w = cols.pop();
-            i = cols.pop();
-            cm.setColumnWidth(i, Math.max(this.grid.minColumnWidth, Math.floor(w + w*frac)), true);
-        }
+    }
+});
 
-        if((tw = cm.getTotalWidth(false)) > aw){
-            var adjustCol = ac != vc ? omitColumn : extraCol;
-             cm.setColumnWidth(adjustCol, Math.max(1,
-                     cm.getColumnWidth(adjustCol)- (tw-aw)), true);
-        }
 
-        if(preventRefresh !== true){
-            this.updateAllColumnWidths();
-        }
+Ext.define('Ext.slider.Tip', {
+    extend: 'Ext.tip.Tip',
+    minWidth: 10,
+    alias: 'widget.slidertip',
+    offsets : [0, -10],
 
+    isSliderTip: true,
 
-        return true;
-    },
+    init: function(slider) {
+        var me = this;
 
+        slider.on({
+            scope    : me,
+            dragstart: me.onSlide,
+            drag     : me.onSlide,
+            dragend  : me.hide,
+            destroy  : me.destroy
+        });
+    },
     
-    autoExpand : function(preventUpdate){
-        var g = this.grid, cm = this.cm;
-        if(!this.userResized && g.autoExpandColumn){
-            var tw = cm.getTotalWidth(false);
-            var aw = this.grid.getGridEl().getWidth(true)-this.getScrollOffset();
-            if(tw != aw){
-                var ci = cm.getIndexById(g.autoExpandColumn);
-                var currentWidth = cm.getColumnWidth(ci);
-                var cw = Math.min(Math.max(((aw-tw)+currentWidth), g.autoExpandMin), g.autoExpandMax);
-                if(cw != currentWidth){
-                    cm.setColumnWidth(ci, cw, true);
-                    if(preventUpdate !== true){
-                        this.updateColumnWidth(ci, cw);
-                    }
-                }
-            }
-        }
+    onSlide : function(slider, e, thumb) {
+        var me = this;
+        me.show();
+        me.update(me.getText(thumb));
+        me.doComponentLayout();
+        me.el.alignTo(thumb.el, 'b-t?', me.offsets);
     },
 
     
-    getColumnData : function(){
-        
-        var cs       = [],
-            cm       = this.cm,
-            colCount = cm.getColumnCount();
+    getText : function(thumb) {
+        return String(thumb.value);
+    }
+});
 
-        for (var i = 0; i < colCount; i++) {
-            var name = cm.getDataIndex(i);
+Ext.define('Ext.slider.Multi', {
+    extend: 'Ext.form.field.Base',
+    alias: 'widget.multislider',
+    alternateClassName: 'Ext.slider.MultiSlider',
+
+    requires: [
+        'Ext.slider.Thumb',
+        'Ext.slider.Tip',
+        'Ext.Number',
+        'Ext.util.Format',
+        'Ext.Template',
+        'Ext.layout.component.field.Slider'
+    ],
 
-            cs[i] = {
-                name    : (!Ext.isDefined(name) ? this.ds.fields.get(i).name : name),
-                renderer: cm.getRenderer(i),
-                scope   : cm.getRendererScope(i),
-                id      : cm.getColumnId(i),
-                style   : this.getColumnStyle(i)
-            };
+    
+    fieldSubTpl: [
+        '<div id="{id}" class="' + Ext.baseCSSPrefix + 'slider {fieldCls} {vertical}" aria-valuemin="{minValue}" aria-valuemax="{maxValue}" aria-valuenow="{value}" aria-valuetext="{value}">',
+            '<div id="{cmpId}-endEl" class="' + Ext.baseCSSPrefix + 'slider-end" role="presentation">',
+                '<div id="{cmpId}-innerEl" class="' + Ext.baseCSSPrefix + 'slider-inner" role="presentation">',
+                    '<a id="{cmpId}-focusEl" class="' + Ext.baseCSSPrefix + 'slider-focus" href="#" tabIndex="-1" hidefocus="on" role="presentation"></a>',
+                '</div>',
+            '</div>',
+        '</div>',
+        {
+            disableFormats: true,
+            compiled: true
         }
+    ],
 
-        return cs;
-    },
+    
 
     
-    renderRows : function(startRow, endRow){
-        
-        var g = this.grid, cm = g.colModel, ds = g.store, stripe = g.stripeRows;
-        var colCount = cm.getColumnCount();
 
-        if(ds.getCount() < 1){
-            return '';
-        }
+    
+    vertical: false,
 
-        var cs = this.getColumnData();
+    
+    minValue: 0,
 
-        startRow = startRow || 0;
-        endRow = !Ext.isDefined(endRow) ? ds.getCount()-1 : endRow;
+    
+    maxValue: 100,
 
-        
-        var rs = ds.getRange(startRow, endRow);
+    
+    decimalPrecision: 0,
 
-        return this.doRender(cs, rs, ds, startRow, colCount, stripe);
-    },
+    
+    keyIncrement: 1,
 
     
-    renderBody : function(){
-        var markup = this.renderRows() || '&#160;';
-        return this.templates.body.apply({rows: markup});
-    },
+    increment: 0,
 
     
-    refreshRow : function(record){
-        var ds = this.ds, index;
-        if(Ext.isNumber(record)){
-            index = record;
-            record = ds.getAt(index);
-            if(!record){
-                return;
-            }
-        }else{
-            index = ds.indexOf(record);
-            if(index < 0){
-                return;
-            }
-        }
-        this.insertRows(ds, index, index, true);
-        this.getRow(index).rowIndex = index;
-        this.onRemove(ds, record, index+1, true);
-        this.fireEvent('rowupdated', this, index, record);
-    },
+    clickRange: [5,15],
 
     
-    refresh : function(headersToo){
-        this.fireEvent('beforerefresh', this);
-        this.grid.stopEditing(true);
+    clickToChange : true,
 
-        var result = this.renderBody();
-        this.mainBody.update(result).setWidth(this.getTotalWidth());
-        if(headersToo === true){
-            this.updateHeaders();
-            this.updateHeaderSortState();
-        }
-        this.processRows(0, true);
-        this.layout();
-        this.applyEmptyText();
-        this.fireEvent('refresh', this);
-    },
+    
+    animate: true,
 
     
-    applyEmptyText : function(){
-        if(this.emptyText && !this.hasRows()){
-            this.mainBody.update('<div class="x-grid-empty">' + this.emptyText + '</div>');
-        }
-    },
+    dragging: false,
 
     
-    updateHeaderSortState : function(){
-        var state = this.ds.getSortState();
-        if (!state) {
-            return;
-        }
+    constrainThumbs: true,
 
-        if (!this.sortState || (this.sortState.field != state.field || this.sortState.direction != state.direction)) {
-            this.grid.fireEvent('sortchange', this.grid, state);
-        }
+    componentLayout: 'sliderfield',
+
+    
+    useTips : true,
 
-        this.sortState = state;
+    
+    tipText : null,
 
-        var sortColumn = this.cm.findColumnIndex(state.field);
-        if (sortColumn != -1){
-            var sortDir = state.direction;
-            this.updateSortIcon(sortColumn, sortDir);
-        }
-    },
+    ariaRole: 'slider',
 
     
-    clearHeaderSortState : function(){
-        if (!this.sortState) {
-            return;
+    initValue: function() {
+        var me = this,
+            extValue = Ext.value,
+            
+            values = extValue(me.values, [extValue(me.value, extValue(me.minValue, 0))]),
+            i = 0,
+            len = values.length;
+
+        
+        me.originalValue = values;
+
+        
+        for (; i < len; i++) {
+            me.addThumb(values[i]);
         }
-        this.grid.fireEvent('sortchange', this.grid, null);
-        this.mainHd.select('td').removeClass(this.sortClasses);
-        delete this.sortState;
     },
 
     
-    destroy : function(){
-        if (this.scrollToTopTask && this.scrollToTopTask.cancel){
-            this.scrollToTopTask.cancel();
-        }
-        if(this.colMenu){
-            Ext.menu.MenuMgr.unregister(this.colMenu);
-            this.colMenu.destroy();
-            delete this.colMenu;
-        }
-        if(this.hmenu){
-            Ext.menu.MenuMgr.unregister(this.hmenu);
-            this.hmenu.destroy();
-            delete this.hmenu;
-        }
+    initComponent : function() {
+        var me = this,
+            tipPlug,
+            hasTip;
 
-        this.initData(null, null);
-        this.purgeListeners();
-        Ext.fly(this.innerHd).un("click", this.handleHdDown, this);
+        
+        me.thumbs = [];
 
-        if(this.grid.enableColumnMove){
-            Ext.destroy(
-                this.columnDrag.el,
-                this.columnDrag.proxy.ghost,
-                this.columnDrag.proxy.el,
-                this.columnDrop.el,
-                this.columnDrop.proxyTop,
-                this.columnDrop.proxyBottom,
-                this.columnDrag.dragData.ddel,
-                this.columnDrag.dragData.header
-            );
-            if (this.columnDrag.proxy.anim) {
-                Ext.destroy(this.columnDrag.proxy.anim);
-            }
-            delete this.columnDrag.proxy.ghost;
-            delete this.columnDrag.dragData.ddel;
-            delete this.columnDrag.dragData.header;
-            this.columnDrag.destroy();
-            delete Ext.dd.DDM.locationCache[this.columnDrag.id];
-            delete this.columnDrag._domRef;
+        me.keyIncrement = Math.max(me.increment, me.keyIncrement);
 
-            delete this.columnDrop.proxyTop;
-            delete this.columnDrop.proxyBottom;
-            this.columnDrop.destroy();
-            delete Ext.dd.DDM.locationCache["gridHeader" + this.grid.getGridEl().id];
-            delete this.columnDrop._domRef;
-            delete Ext.dd.DDM.ids[this.columnDrop.ddGroup];
-        }
+        me.addEvents(
+            
+            'beforechange',
 
-        if (this.splitZone){ 
-            this.splitZone.destroy();
-            delete this.splitZone._domRef;
-            delete Ext.dd.DDM.ids["gridSplitters" + this.grid.getGridEl().id];
-        }
+            
+            'change',
 
-        Ext.fly(this.innerHd).removeAllListeners();
-        Ext.removeNode(this.innerHd);
-        delete this.innerHd;
+            
+            'changecomplete',
 
-        Ext.destroy(
-            this.el,
-            this.mainWrap,
-            this.mainHd,
-            this.scroller,
-            this.mainBody,
-            this.focusEl,
-            this.resizeMarker,
-            this.resizeProxy,
-            this.activeHdBtn,
-            this.dragZone,
-            this.splitZone,
-            this._flyweight
-        );
+            
+            'dragstart',
+
+            
+            'drag',
 
-        delete this.grid.container;
+            
+            'dragend'
+        );
 
-        if(this.dragZone){
-            this.dragZone.destroy();
+        if (me.vertical) {
+            Ext.apply(me, Ext.slider.Multi.Vertical);
         }
 
-        Ext.dd.DDM.currentTarget = null;
-        delete Ext.dd.DDM.locationCache[this.grid.getGridEl().id];
+        me.callParent();
 
-        Ext.EventManager.removeResizeListener(this.onWindowResize, this);
+        
+        if (me.useTips) {
+            tipPlug = me.tipText ? {getText: me.tipText} : {};
+            me.plugins = me.plugins || [];
+            Ext.each(me.plugins, function(plug){
+                if (plug.isSliderTip) {
+                    hasTip = true;
+                    return false;
+                }
+            });
+            if (!hasTip) {
+                me.plugins.push(Ext.create('Ext.slider.Tip', tipPlug));
+            }
+        }
     },
 
     
-    onDenyColumnHide : function(){
+    addThumb: function(value) {
+        var me = this,
+            thumb = Ext.create('Ext.slider.Thumb', {
+            value    : value,
+            slider   : me,
+            index    : me.thumbs.length,
+            constrain: me.constrainThumbs
+        });
+        me.thumbs.push(thumb);
+
+        
+        if (me.rendered) {
+            thumb.render();
+        }
 
+        return thumb;
     },
 
     
-    render : function(){
-        if(this.autoFill){
-            var ct = this.grid.ownerCt;
-            if (ct && ct.getLayout()){
-                ct.on('afterlayout', function(){
-                    this.fitColumns(true, true);
-                    this.updateHeaders();
-                }, this, {single: true});
-            }else{
-                this.fitColumns(true, true);
+    promoteThumb: function(topThumb) {
+        var thumbs = this.thumbs,
+            ln = thumbs.length,
+            zIndex, thumb, i;
+
+        for (i = 0; i < ln; i++) {
+            thumb = thumbs[i];
+
+            if (thumb == topThumb) {
+                thumb.bringToFront();
+            } else {
+                thumb.sendToBack();
             }
-        }else if(this.forceFit){
-            this.fitColumns(true, false);
-        }else if(this.grid.autoExpandColumn){
-            this.autoExpand(true);
         }
-
-        this.renderUI();
     },
 
     
-    
-    initData : function(ds, cm){
-        if(this.ds){
-            this.ds.un('load', this.onLoad, this);
-            this.ds.un('datachanged', this.onDataChange, this);
-            this.ds.un('add', this.onAdd, this);
-            this.ds.un('remove', this.onRemove, this);
-            this.ds.un('update', this.onUpdate, this);
-            this.ds.un('clear', this.onClear, this);
-            if(this.ds !== ds && this.ds.autoDestroy){
-                this.ds.destroy();
-            }
-        }
-        if(ds){
-            ds.on({
-                scope: this,
-                load: this.onLoad,
-                datachanged: this.onDataChange,
-                add: this.onAdd,
-                remove: this.onRemove,
-                update: this.onUpdate,
-                clear: this.onClear
-            });
-        }
-        this.ds = ds;
+    onRender : function() {
+        var me = this,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            thumb;
 
-        if(this.cm){
-            this.cm.un('configchange', this.onColConfigChange, this);
-            this.cm.un('widthchange', this.onColWidthChange, this);
-            this.cm.un('headerchange', this.onHeaderChange, this);
-            this.cm.un('hiddenchange', this.onHiddenChange, this);
-            this.cm.un('columnmoved', this.onColumnMove, this);
-        }
-        if(cm){
-            delete this.lastViewWidth;
-            cm.on({
-                scope: this,
-                configchange: this.onColConfigChange,
-                widthchange: this.onColWidthChange,
-                headerchange: this.onHeaderChange,
-                hiddenchange: this.onHiddenChange,
-                columnmoved: this.onColumnMove
-            });
+        Ext.applyIf(me.subTplData, {
+            vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz',
+            minValue: me.minValue,
+            maxValue: me.maxValue,
+            value: me.value
+        });
+
+        me.addChildEls('endEl', 'innerEl', 'focusEl');
+
+        me.callParent(arguments);
+
+        
+        for (; i < len; i++) {
+            thumbs[i].render();
         }
-        this.cm = cm;
-    },
 
-    
-    onDataChange : function(){
-        this.refresh();
-        this.updateHeaderSortState();
-        this.syncFocusEl(0);
-    },
+        
+        thumb = me.innerEl.down('.' + Ext.baseCSSPrefix + 'slider-thumb');
+        me.halfThumb = (me.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
 
-    
-    onClear : function(){
-        this.refresh();
-        this.syncFocusEl(0);
     },
 
     
-    onUpdate : function(ds, record){
-        this.refreshRow(record);
+    onChange : function(slider, v) {
+        this.setValue(v, undefined, true);
     },
 
     
-    onAdd : function(ds, records, index){
-        this.insertRows(ds, index, index + (records.length-1));
+    initEvents : function() {
+        var me = this;
+
+        me.mon(me.el, {
+            scope    : me,
+            mousedown: me.onMouseDown,
+            keydown  : me.onKeyDown,
+            change : me.onChange
+        });
+
+        me.focusEl.swallowEvent("click", true);
     },
 
     
-    onRemove : function(ds, record, index, isUpdate){
-        if(isUpdate !== true){
-            this.fireEvent('beforerowremoved', this, index, record);
-        }
-        this.removeRow(index);
-        if(isUpdate !== true){
-            this.processRows(index);
-            this.applyEmptyText();
-            this.fireEvent('rowremoved', this, index, record);
+    onMouseDown : function(e) {
+        var me = this,
+            thumbClicked = false,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            local;
+
+        if (me.disabled) {
+            return;
         }
-    },
 
-    
-    onLoad : function(){
-        if (Ext.isGecko){
-            if (!this.scrollToTopTask) {
-                this.scrollToTopTask = new Ext.util.DelayedTask(this.scrollToTop, this);
-            }
-            this.scrollToTopTask.delay(1);
-        }else{
-            this.scrollToTop();
+        
+        for (; i < len; i++) {
+            thumbClicked = thumbClicked || e.target == thumbs[i].el.dom;
         }
-    },
 
-    
-    onColWidthChange : function(cm, col, width){
-        this.updateColumnWidth(col, width);
+        if (me.clickToChange && !thumbClicked) {
+            local = me.innerEl.translatePoints(e.getXY());
+            me.onClickChange(local);
+        }
+        me.focus();
     },
 
     
-    onHeaderChange : function(cm, col, text){
-        this.updateHeaders();
-    },
+    onClickChange : function(local) {
+        var me = this,
+            thumb, index;
 
-    
-    onHiddenChange : function(cm, col, hidden){
-        this.updateColumnHidden(col, hidden);
+        if (local.top > me.clickRange[0] && local.top < me.clickRange[1]) {
+            
+            thumb = me.getNearest(local, 'left');
+            if (!thumb.disabled) {
+                index = thumb.index;
+                me.setValue(index, Ext.util.Format.round(me.reverseValue(local.left), me.decimalPrecision), undefined, true);
+            }
+        }
     },
 
     
-    onColumnMove : function(cm, oldIndex, newIndex){
-        this.indexMap = null;
-        var s = this.getScrollState();
-        this.refresh(true);
-        this.restoreScroll(s);
-        this.afterMove(newIndex);
-        this.grid.fireEvent('columnmove', oldIndex, newIndex);
-    },
+    getNearest: function(local, prop) {
+        var me = this,
+            localValue = prop == 'top' ? me.innerEl.getHeight() - local[prop] : local[prop],
+            clickValue = me.reverseValue(localValue),
+            nearestDistance = (me.maxValue - me.minValue) + 5, 
+            index = 0,
+            nearest = null,
+            thumbs = me.thumbs,
+            i = 0,
+            len = thumbs.length,
+            thumb,
+            value,
+            dist;
 
-    
-    onColConfigChange : function(){
-        delete this.lastViewWidth;
-        this.indexMap = null;
-        this.refresh(true);
-    },
+        for (; i < len; i++) {
+            thumb = me.thumbs[i];
+            value = thumb.value;
+            dist  = Math.abs(value - clickValue);
 
-    
-    
-    initUI : function(grid){
-        grid.on('headerclick', this.onHeaderClick, this);
+            if (Math.abs(dist <= nearestDistance)) {
+                nearest = thumb;
+                index = i;
+                nearestDistance = dist;
+            }
+        }
+        return nearest;
     },
 
     
-    initEvents : function(){
-    },
+    onKeyDown : function(e) {
+        
+        var me = this,
+            k,
+            val;
 
-    
-    onHeaderClick : function(g, index){
-        if(this.headersDisabled || !this.cm.isSortable(index)){
+        if(me.disabled || me.thumbs.length !== 1) {
+            e.preventDefault();
             return;
         }
-        g.stopEditing(true);
-        g.store.sort(this.cm.getDataIndex(index));
+        k = e.getKey();
+
+        switch(k) {
+            case e.UP:
+            case e.RIGHT:
+                e.stopEvent();
+                val = e.ctrlKey ? me.maxValue : me.getValue(0) + me.keyIncrement;
+                me.setValue(0, val, undefined, true);
+            break;
+            case e.DOWN:
+            case e.LEFT:
+                e.stopEvent();
+                val = e.ctrlKey ? me.minValue : me.getValue(0) - me.keyIncrement;
+                me.setValue(0, val, undefined, true);
+            break;
+            default:
+                e.preventDefault();
+        }
     },
 
     
-    onRowOver : function(e, t){
-        var row;
-        if((row = this.findRowIndex(t)) !== false){
-            this.addRowClass(row, 'x-grid3-row-over');
+    afterRender : function() {
+        var me = this,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            thumb,
+            v;
+
+        me.callParent(arguments);
+
+        for (; i < len; i++) {
+            thumb = thumbs[i];
+
+            if (thumb.value !== undefined) {
+                v = me.normalizeValue(thumb.value);
+                if (v !== thumb.value) {
+                    
+                    me.setValue(i, v, false);
+                } else {
+                    thumb.move(me.translateValue(v), false);
+                }
+            }
         }
     },
 
     
-    onRowOut : function(e, t){
-        var row;
-        if((row = this.findRowIndex(t)) !== false && !e.within(this.getRow(row), true)){
-            this.removeRowClass(row, 'x-grid3-row-over');
-        }
+    getRatio : function() {
+        var w = this.innerEl.getWidth(),
+            v = this.maxValue - this.minValue;
+        return v === 0 ? w : (w/v);
     },
 
     
-    handleWheel : function(e){
-        e.stopPropagation();
-    },
+    normalizeValue : function(v) {
+        var me = this;
 
-    
-    onRowSelect : function(row){
-        this.addRowClass(row, this.selectedRowClass);
+        v = Ext.Number.snap(v, this.increment, this.minValue, this.maxValue);
+        v = Ext.util.Format.round(v, me.decimalPrecision);
+        v = Ext.Number.constrain(v, me.minValue, me.maxValue);
+        return v;
     },
 
     
-    onRowDeselect : function(row){
-        this.removeRowClass(row, this.selectedRowClass);
-    },
+    setMinValue : function(val) {
+        var me = this,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            t;
 
-    
-    onCellSelect : function(row, col){
-        var cell = this.getCell(row, col);
-        if(cell){
-            this.fly(cell).addClass('x-grid3-cell-selected');
+        me.minValue = val;
+        if (me.rendered) {
+            me.inputEl.dom.setAttribute('aria-valuemin', val);
         }
-    },
 
-    
-    onCellDeselect : function(row, col){
-        var cell = this.getCell(row, col);
-        if(cell){
-            this.fly(cell).removeClass('x-grid3-cell-selected');
+        for (; i < len; ++i) {
+            t = thumbs[i];
+            t.value = t.value < val ? val : t.value;
         }
+        me.syncThumbs();
     },
 
     
-    onColumnSplitterMoved : function(i, w){
-        this.userResized = true;
-        var cm = this.grid.colModel;
-        cm.setColumnWidth(i, w, true);
+    setMaxValue : function(val) {
+        var me = this,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            t;
 
-        if(this.forceFit){
-            this.fitColumns(true, false, i);
-            this.updateAllColumnWidths();
-        }else{
-            this.updateColumnWidth(i, w);
-            this.syncHeaderScroll();
+        me.maxValue = val;
+        if (me.rendered) {
+            me.inputEl.dom.setAttribute('aria-valuemax', val);
         }
 
-        this.grid.fireEvent('columnresize', i, w);
+        for (; i < len; ++i) {
+            t = thumbs[i];
+            t.value = t.value > val ? val : t.value;
+        }
+        me.syncThumbs();
     },
 
     
-    handleHdMenuClick : function(item){
-        var index = this.hdCtxIndex,
-            cm = this.cm,
-            ds = this.ds,
-            id = item.getItemId();
-        switch(id){
-            case 'asc':
-                ds.sort(cm.getDataIndex(index), 'ASC');
-                break;
-            case 'desc':
-                ds.sort(cm.getDataIndex(index), 'DESC');
-                break;
-            default:
-                index = cm.getIndexById(id.substr(4));
-                if(index != -1){
-                    if(item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1){
-                        this.onDenyColumnHide();
-                        return false;
-                    }
-                    cm.setHidden(index, item.checked);
+    setValue : function(index, value, animate, changeComplete) {
+        var me = this,
+            thumb = me.thumbs[index];
+
+        
+        value = me.normalizeValue(value);
+
+        if (value !== thumb.value && me.fireEvent('beforechange', me, value, thumb.value, thumb) !== false) {
+            thumb.value = value;
+            if (me.rendered) {
+                
+                
+                me.inputEl.set({
+                    'aria-valuenow': value,
+                    'aria-valuetext': value
+                });
+
+                thumb.move(me.translateValue(value), Ext.isDefined(animate) ? animate !== false : me.animate);
+
+                me.fireEvent('change', me, value, thumb);
+                if (changeComplete) {
+                    me.fireEvent('changecomplete', me, value, thumb);
                 }
+            }
         }
-        return true;
     },
 
     
-    isHideableColumn : function(c){
-        return !c.hidden;
+    translateValue : function(v) {
+        var ratio = this.getRatio();
+        return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
     },
 
     
-    beforeColMenuShow : function(){
-        var cm = this.cm,  colCount = cm.getColumnCount();
-        this.colMenu.removeAll();
-        for(var i = 0; i < colCount; i++){
-            if(cm.config[i].hideable !== false){
-                this.colMenu.add(new Ext.menu.CheckItem({
-                    itemId: 'col-'+cm.getColumnId(i),
-                    text: cm.getColumnHeader(i),
-                    checked: !cm.isHidden(i),
-                    hideOnClick:false,
-                    disabled: cm.config[i].hideable === false
-                }));
-            }
-        }
+    reverseValue : function(pos) {
+        var ratio = this.getRatio();
+        return (pos + (this.minValue * ratio)) / ratio;
     },
 
     
-    handleHdDown : function(e, t){
-        if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
-            e.stopEvent();
-            var hd = this.findHeaderCell(t);
-            Ext.fly(hd).addClass('x-grid3-hd-menu-open');
-            var index = this.getCellIndex(hd);
-            this.hdCtxIndex = index;
-            var ms = this.hmenu.items, cm = this.cm;
-            ms.get('asc').setDisabled(!cm.isSortable(index));
-            ms.get('desc').setDisabled(!cm.isSortable(index));
-            this.hmenu.on('hide', function(){
-                Ext.fly(hd).removeClass('x-grid3-hd-menu-open');
-            }, this, {single:true});
-            this.hmenu.show(t, 'tl-bl?');
-        }
+    focus : function() {
+        this.focusEl.focus(10);
     },
 
     
-    handleHdOver : function(e, t){
-        var hd = this.findHeaderCell(t);
-        if(hd && !this.headersDisabled){
-            this.activeHdRef = t;
-            this.activeHdIndex = this.getCellIndex(hd);
-            var fly = this.fly(hd);
-            this.activeHdRegion = fly.getRegion();
-            if(!this.cm.isMenuDisabled(this.activeHdIndex)){
-                fly.addClass('x-grid3-hd-over');
-                this.activeHdBtn = fly.child('.x-grid3-hd-btn');
-                if(this.activeHdBtn){
-                    this.activeHdBtn.dom.style.height = (hd.firstChild.offsetHeight-1)+'px';
+    onDisable: function() {
+        var me = this,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            thumb,
+            el,
+            xy;
+
+        me.callParent();
+
+        for (; i < len; i++) {
+            thumb = thumbs[i];
+            el = thumb.el;
+
+            thumb.disable();
+
+            if(Ext.isIE) {
+                
+                
+                xy = el.getXY();
+                el.hide();
+
+                me.innerEl.addCls(me.disabledCls).dom.disabled = true;
+
+                if (!me.thumbHolder) {
+                    me.thumbHolder = me.endEl.createChild({cls: Ext.baseCSSPrefix + 'slider-thumb ' + me.disabledCls});
                 }
+
+                me.thumbHolder.show().setXY(xy);
             }
         }
     },
 
     
-    handleHdMove : function(e, t){
-        var hd = this.findHeaderCell(this.activeHdRef);
-        if(hd && !this.headersDisabled){
-            var hw = this.splitHandleWidth || 5,
-                r = this.activeHdRegion,
-                x = e.getPageX(),
-                ss = hd.style,
-                cur = '';
-            if(this.grid.enableColumnResize !== false){
-                if(x - r.left <= hw && this.cm.isResizable(this.activeHdIndex-1)){
-                    cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'e-resize' : 'col-resize'; 
-                }else if(r.right - x <= (!this.activeHdBtn ? hw : 2) && this.cm.isResizable(this.activeHdIndex)){
-                    cur = Ext.isAir ? 'move' : Ext.isWebKit ? 'w-resize' : 'col-resize';
+    onEnable: function() {
+        var me = this,
+            i = 0,
+            thumbs = me.thumbs,
+            len = thumbs.length,
+            thumb,
+            el;
+
+        this.callParent();
+
+        for (; i < len; i++) {
+            thumb = thumbs[i];
+            el = thumb.el;
+
+            thumb.enable();
+
+            if (Ext.isIE) {
+                me.innerEl.removeCls(me.disabledCls).dom.disabled = false;
+
+                if (me.thumbHolder) {
+                    me.thumbHolder.hide();
                 }
+
+                el.show();
+                me.syncThumbs();
             }
-            ss.cursor = cur;
         }
     },
 
     
-    handleHdOut : function(e, t){
-        var hd = this.findHeaderCell(t);
-        if(hd && (!Ext.isIE || !e.within(hd, true))){
-            this.activeHdRef = null;
-            this.fly(hd).removeClass('x-grid3-hd-over');
-            hd.style.cursor = '';
+    syncThumbs : function() {
+        if (this.rendered) {
+            var thumbs = this.thumbs,
+                length = thumbs.length,
+                i = 0;
+
+            for (; i < length; i++) {
+                thumbs[i].move(this.translateValue(thumbs[i].value));
+            }
         }
     },
 
     
-    hasRows : function(){
-        var fc = this.mainBody.dom.firstChild;
-        return fc && fc.nodeType == 1 && fc.className != 'x-grid-empty';
+    getValue : function(index) {
+        return Ext.isNumber(index) ? this.thumbs[index].value : this.getValues();
     },
 
     
-    bind : function(d, c){
-        this.initData(d, c);
-    }
-});
+    getValues: function() {
+        var values = [],
+            i = 0,
+            thumbs = this.thumbs,
+            len = thumbs.length;
 
+        for (; i < len; i++) {
+            values.push(thumbs[i].value);
+        }
 
+        return values;
+    },
 
+    getSubmitValue: function() {
+        var me = this;
+        return (me.disabled || !me.submitValue) ? null : me.getValue();
+    },
 
-Ext.grid.GridView.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
-    
-    constructor: function(grid, hd){
-        this.grid = grid;
-        this.view = grid.getView();
-        this.marker = this.view.resizeMarker;
-        this.proxy = this.view.resizeProxy;
-        Ext.grid.GridView.SplitDragZone.superclass.constructor.call(this, hd,
-            'gridSplitters' + this.grid.getGridEl().id, {
-            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
+    reset: function() {
+        var me = this,
+            Array = Ext.Array;
+        Array.forEach(Array.from(me.originalValue), function(val, i) {
+            me.setValue(i, val);
         });
-        this.scroll = false;
-        this.hw = this.view.splitHandleWidth || 5;
+        me.clearInvalid();
+        
+        delete me.wasValid;
     },
 
-    b4StartDrag : function(x, y){
-        this.dragHeadersDisabled = this.view.headersDisabled;
-        this.view.headersDisabled = true;
-        var h = this.view.mainWrap.getHeight();
-        this.marker.setHeight(h);
-        this.marker.show();
-        this.marker.alignTo(this.view.getHeaderCell(this.cellIndex), 'tl-tl', [-2, 0]);
-        this.proxy.setHeight(h);
-        var w = this.cm.getColumnWidth(this.cellIndex),
-            minw = Math.max(w-this.grid.minColumnWidth, 0);
-        this.resetConstraints();
-        this.setXConstraint(minw, 1000);
-        this.setYConstraint(0, 0);
-        this.minX = x - minw;
-        this.maxX = x + 1000;
-        this.startPos = x;
-        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
-    },
+    
+    beforeDestroy : function() {
+        var me = this;
 
-    allowHeaderDrag : function(e){
-        return true;
+        Ext.destroy(me.innerEl, me.endEl, me.focusEl);
+        Ext.each(me.thumbs, function(thumb) {
+            Ext.destroy(thumb);
+        }, me);
+
+        me.callParent();
     },
 
-    handleMouseDown : function(e){
-        var t = this.view.findHeaderCell(e.getTarget());
-        if(t && this.allowHeaderDrag(e)){
-            var xy = this.view.fly(t).getXY(), 
-                x = xy[0], 
-                y = xy[1],
-                exy = e.getXY(), ex = exy[0],
-                w = t.offsetWidth, adjust = false;
-                
-            if((ex - x) <= this.hw){
-                adjust = -1;
-            }else if((x+w) - ex <= this.hw){
-                adjust = 0;
-            }
-            if(adjust !== false){
-                this.cm = this.grid.colModel;
-                var ci = this.view.getCellIndex(t);
-                if(adjust == -1){
-                  if (ci + adjust < 0) {
-                    return;
-                  }
-                    while(this.cm.isHidden(ci+adjust)){
-                        --adjust;
-                        if(ci+adjust < 0){
-                            return;
-                        }
+    statics: {
+        
+        Vertical: {
+            getRatio : function() {
+                var h = this.innerEl.getHeight(),
+                    v = this.maxValue - this.minValue;
+                return h/v;
+            },
+
+            onClickChange : function(local) {
+                var me = this,
+                    thumb, index, bottom;
+
+                if (local.left > me.clickRange[0] && local.left < me.clickRange[1]) {
+                    thumb = me.getNearest(local, 'top');
+                    if (!thumb.disabled) {
+                        index = thumb.index;
+                        bottom =  me.reverseValue(me.innerEl.getHeight() - local.top);
+
+                        me.setValue(index, Ext.util.Format.round(me.minValue + bottom, me.decimalPrecision), undefined, true);
                     }
                 }
-                this.cellIndex = ci+adjust;
-                this.split = t.dom;
-                if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
-                    Ext.grid.GridView.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
-                }
-            }else if(this.view.columnDrag){
-                this.view.columnDrag.callHandleMouseDown(e);
             }
         }
-    },
-
-    endDrag : function(e){
-        this.marker.hide();
-        var v = this.view,
-            endX = Math.max(this.minX, e.getPageX()),
-            diff = endX - this.startPos,
-            disabled = this.dragHeadersDisabled;
-            
-        v.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
-        setTimeout(function(){
-            v.headersDisabled = disabled;
-        }, 50);
-    },
-
-    autoOffset : function(){
-        this.setDelta(0,0);
     }
 });
 
 
-Ext.grid.HeaderDragZone = Ext.extend(Ext.dd.DragZone, {
-    maxDragWidth: 120,
+Ext.define('Ext.slider.Single', {
+    extend: 'Ext.slider.Multi',
+    alias: ['widget.slider', 'widget.sliderfield'],
+    alternateClassName: ['Ext.Slider', 'Ext.form.SliderField', 'Ext.slider.SingleSlider', 'Ext.slider.Slider'],
+
     
-    constructor : function(grid, hd, hd2){
-        this.grid = grid;
-        this.view = grid.getView();
-        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
-        Ext.grid.HeaderDragZone.superclass.constructor.call(this, hd);
-        if(hd2){
-            this.setHandleElId(Ext.id(hd));
-            this.setOuterHandleElId(Ext.id(hd2));
-        }
-        this.scroll = false;
+    getValue: function() {
+        
+        return this.callParent([0]);
     },
+
     
-    getDragData : function(e){
-        var t = Ext.lib.Event.getTarget(e),
-            h = this.view.findHeaderCell(t);
-        if(h){
-            return {ddel: h.firstChild, header:h};
-        }
-        return false;
-    },
+    setValue: function(value, animate) {
+        var args = Ext.toArray(arguments),
+            len  = args.length;
 
-    onInitDrag : function(e){
         
-        this.dragHeadersDisabled = this.view.headersDisabled;
-        this.view.headersDisabled = true;
-        var clone = this.dragData.ddel.cloneNode(true);
-        clone.id = Ext.id();
-        clone.style.width = Math.min(this.dragData.header.offsetWidth,this.maxDragWidth) + "px";
-        this.proxy.update(clone);
-        return true;
-    },
+        
+        
+        if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
+            args.unshift(0);
+        }
 
-    afterValidDrop : function(){
-        this.completeDrop();
+        return this.callParent(args);
     },
 
-    afterInvalidDrop : function(){
-        this.completeDrop();
-    },
     
-    completeDrop: function(){
-        var v = this.view,
-            disabled = this.dragHeadersDisabled;
-        setTimeout(function(){
-            v.headersDisabled = disabled;
-        }, 50);
+    getNearest : function(){
+        
+        return this.thumbs[0];
     }
 });
 
 
+Ext.define('Ext.tab.Tab', {
+    extend: 'Ext.button.Button',
+    alias: 'widget.tab',
 
-Ext.grid.HeaderDropZone = Ext.extend(Ext.dd.DropZone, {
-    proxyOffsets : [-4, -9],
-    fly: Ext.Element.fly,
-    
-    constructor : function(grid, hd, hd2){
-        this.grid = grid;
-        this.view = grid.getView();
-        
-        this.proxyTop = Ext.DomHelper.append(document.body, {
-            cls:"col-move-top", html:"&#160;"
-        }, true);
-        this.proxyBottom = Ext.DomHelper.append(document.body, {
-            cls:"col-move-bottom", html:"&#160;"
-        }, true);
-        this.proxyTop.hide = this.proxyBottom.hide = function(){
-            this.setLeftTop(-100,-100);
-            this.setStyle("visibility", "hidden");
-        };
-        this.ddGroup = "gridHeader" + this.grid.getGridEl().id;
-        
-        
-        Ext.grid.HeaderDropZone.superclass.constructor.call(this, grid.getGridEl().dom);
-    },
-
-    getTargetFromEvent : function(e){
-        var t = Ext.lib.Event.getTarget(e),
-            cindex = this.view.findCellIndex(t);
-        if(cindex !== false){
-            return this.view.getHeaderCell(cindex);
-        }
-    },
-
-    nextVisible : function(h){
-        var v = this.view, cm = this.grid.colModel;
-        h = h.nextSibling;
-        while(h){
-            if(!cm.isHidden(v.getCellIndex(h))){
-                return h;
-            }
-            h = h.nextSibling;
-        }
-        return null;
-    },
+    requires: [
+        'Ext.layout.component.Tab',
+        'Ext.util.KeyNav'
+    ],
 
-    prevVisible : function(h){
-        var v = this.view, cm = this.grid.colModel;
-        h = h.prevSibling;
-        while(h){
-            if(!cm.isHidden(v.getCellIndex(h))){
-                return h;
-            }
-            h = h.prevSibling;
-        }
-        return null;
-    },
+    componentLayout: 'tab',
 
-    positionIndicator : function(h, n, e){
-        var x = Ext.lib.Event.getPageX(e),
-            r = Ext.lib.Dom.getRegion(n.firstChild),
-            px, 
-            pt, 
-            py = r.top + this.proxyOffsets[1];
-        if((r.right - x) <= (r.right-r.left)/2){
-            px = r.right+this.view.borderWidth;
-            pt = "after";
-        }else{
-            px = r.left;
-            pt = "before";
-        }
+    isTab: true,
 
-        if(this.grid.colModel.isFixed(this.view.getCellIndex(n))){
-            return false;
-        }
+    baseCls: Ext.baseCSSPrefix + 'tab',
 
-        px +=  this.proxyOffsets[0];
-        this.proxyTop.setLeftTop(px, py);
-        this.proxyTop.show();
-        if(!this.bottomOffset){
-            this.bottomOffset = this.view.mainHd.getHeight();
-        }
-        this.proxyBottom.setLeftTop(px, py+this.proxyTop.dom.offsetHeight+this.bottomOffset);
-        this.proxyBottom.show();
-        return pt;
-    },
+    
+    activeCls: 'active',
 
-    onNodeEnter : function(n, dd, e, data){
-        if(data.header != n){
-            this.positionIndicator(data.header, n, e);
-        }
-    },
+    
 
-    onNodeOver : function(n, dd, e, data){
-        var result = false;
-        if(data.header != n){
-            result = this.positionIndicator(data.header, n, e);
-        }
-        if(!result){
-            this.proxyTop.hide();
-            this.proxyBottom.hide();
-        }
-        return result ? this.dropAllowed : this.dropNotAllowed;
-    },
+    
+    closableCls: 'closable',
 
-    onNodeOut : function(n, dd, e, data){
-        this.proxyTop.hide();
-        this.proxyBottom.hide();
-    },
+    
+    closable: true,
 
-    onNodeDrop : function(n, dd, e, data){
-        var h = data.header;
-        if(h != n){
-            var cm = this.grid.colModel,
-                x = Ext.lib.Event.getPageX(e),
-                r = Ext.lib.Dom.getRegion(n.firstChild),
-                pt = (r.right - x) <= ((r.right-r.left)/2) ? "after" : "before",
-                oldIndex = this.view.getCellIndex(h),
-                newIndex = this.view.getCellIndex(n);
-            if(pt == "after"){
-                newIndex++;
-            }
-            if(oldIndex < newIndex){
-                newIndex--;
-            }
-            cm.moveColumn(oldIndex, newIndex);
-            return true;
-        }
-        return false;
-    }
-});
+    
+    closeText: 'Close Tab',
 
-Ext.grid.GridView.ColumnDragZone = Ext.extend(Ext.grid.HeaderDragZone, {
     
-    constructor : function(grid, hd){
-        Ext.grid.GridView.ColumnDragZone.superclass.constructor.call(this, grid, hd, null);
-        this.proxy.el.addClass('x-grid3-col-dd');
-    },
+    active: false,
+
     
-    handleMouseDown : function(e){
-    },
 
-    callHandleMouseDown : function(e){
-        Ext.grid.GridView.ColumnDragZone.superclass.handleMouseDown.call(this, e);
-    }
-});
+    scale: false,
 
-Ext.grid.SplitDragZone = Ext.extend(Ext.dd.DDProxy, {
-    fly: Ext.Element.fly,
-    
-    constructor : function(grid, hd, hd2){
-        this.grid = grid;
-        this.view = grid.getView();
-        this.proxy = this.view.resizeProxy;
-        Ext.grid.SplitDragZone.superclass.constructor.call(this, hd,
-            "gridSplitters" + this.grid.getGridEl().id, {
-            dragElId : Ext.id(this.proxy.dom), resizeFrame:false
-        });
-        this.setHandleElId(Ext.id(hd));
-        this.setOuterHandleElId(Ext.id(hd2));
-        this.scroll = false;
-    },
+    position: 'top',
 
-    b4StartDrag : function(x, y){
-        this.view.headersDisabled = true;
-        this.proxy.setHeight(this.view.mainWrap.getHeight());
-        var w = this.cm.getColumnWidth(this.cellIndex);
-        var minw = Math.max(w-this.grid.minColumnWidth, 0);
-        this.resetConstraints();
-        this.setXConstraint(minw, 1000);
-        this.setYConstraint(0, 0);
-        this.minX = x - minw;
-        this.maxX = x + 1000;
-        this.startPos = x;
-        Ext.dd.DDProxy.prototype.b4StartDrag.call(this, x, y);
-    },
+    initComponent: function() {
+        var me = this;
 
+        me.addEvents(
+            
+            'activate',
 
-    handleMouseDown : function(e){
-        var ev = Ext.EventObject.setEvent(e);
-        var t = this.fly(ev.getTarget());
-        if(t.hasClass("x-grid-split")){
-            this.cellIndex = this.view.getCellIndex(t.dom);
-            this.split = t.dom;
-            this.cm = this.grid.colModel;
-            if(this.cm.isResizable(this.cellIndex) && !this.cm.isFixed(this.cellIndex)){
-                Ext.grid.SplitDragZone.superclass.handleMouseDown.apply(this, arguments);
-            }
-        }
-    },
+            
+            'deactivate',
 
-    endDrag : function(e){
-        this.view.headersDisabled = false;
-        var endX = Math.max(this.minX, Ext.lib.Event.getPageX(e));
-        var diff = endX - this.startPos;
-        this.view.onColumnSplitterMoved(this.cellIndex, this.cm.getColumnWidth(this.cellIndex)+diff);
-    },
+            
+            'beforeclose',
 
-    autoOffset : function(){
-        this.setDelta(0,0);
-    }
-});
-Ext.grid.GridDragZone = function(grid, config){
-    this.view = grid.getView();
-    Ext.grid.GridDragZone.superclass.constructor.call(this, this.view.mainBody.dom, config);
-    this.scroll = false;
-    this.grid = grid;
-    this.ddel = document.createElement('div');
-    this.ddel.className = 'x-grid-dd-wrap';
-};
+            
+            'close'
+        );
 
-Ext.extend(Ext.grid.GridDragZone, Ext.dd.DragZone, {
-    ddGroup : "GridDD",
+        me.callParent(arguments);
 
-    
-    getDragData : function(e){
-        var t = Ext.lib.Event.getTarget(e);
-        var rowIndex = this.view.findRowIndex(t);
-        if(rowIndex !== false){
-            var sm = this.grid.selModel;
-            if(!sm.isSelected(rowIndex) || e.hasModifier()){
-                sm.handleMouseDown(this.grid, rowIndex, e);
-            }
-            return {grid: this.grid, ddel: this.ddel, rowIndex: rowIndex, selections:sm.getSelections()};
+        if (me.card) {
+            me.setCard(me.card);
         }
-        return false;
     },
 
     
-    onInitDrag : function(e){
-        var data = this.dragData;
-        this.ddel.innerHTML = this.grid.getDragDropText();
-        this.proxy.update(this.ddel);
+    onRender: function() {
+        var me = this,
+            tabBar = me.up('tabbar'),
+            tabPanel = me.up('tabpanel');
+
+        me.addClsWithUI(me.position);
+
+        
         
-    },
 
-    
-    afterRepair : function(){
-        this.dragging = false;
+        me.syncClosableUI();
+
+        
+        if (!me.minWidth) {
+            me.minWidth = (tabBar) ? tabBar.minTabWidth : me.minWidth;
+            if (!me.minWidth && tabPanel) {
+                me.minWidth = tabPanel.minTabWidth;
+            }
+            if (me.minWidth && me.iconCls) {
+                me.minWidth += 25;
+            }
+        }
+        if (!me.maxWidth) {
+            me.maxWidth = (tabBar) ? tabBar.maxTabWidth : me.maxWidth;
+            if (!me.maxWidth && tabPanel) {
+                me.maxWidth = tabPanel.maxTabWidth;
+            }
+        }
+
+        me.callParent(arguments);
+
+        if (me.active) {
+            me.activate(true);
+        }
+
+        me.syncClosableElements();
+
+        me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
+            enter: me.onEnterKey,
+            del: me.onDeleteKey,
+            scope: me
+        });
     },
 
     
-    getRepairXY : function(e, data){
-        return false;
-    },
+    enable : function(silent) {
+        var me = this;
 
-    onEndDrag : function(data, e){
-        
-    },
+        me.callParent(arguments);
 
-    onValidDrop : function(dd, e, id){
-        
-        this.hideProxy();
+        me.removeClsWithUI(me.position + '-disabled');
+
+        return me;
     },
 
-    beforeInvalidDrop : function(e, id){
+    
+    disable : function(silent) {
+        var me = this;
 
-    }
-});
+        me.callParent(arguments);
 
-Ext.grid.ColumnModel = Ext.extend(Ext.util.Observable, {
-    
-    defaultWidth: 100,
-    
-    defaultSortable: false,
-    
-    
+        me.addClsWithUI(me.position + '-disabled');
 
-    constructor : function(config){
-        
-           if(config.columns){
-               Ext.apply(this, config);
-               this.setConfig(config.columns, true);
-           }else{
-               this.setConfig(config, true);
-           }
-           this.addEvents(
-               
-               "widthchange",
-               
-               "headerchange",
-               
-               "hiddenchange",
-               
-               "columnmoved",
-               
-               "configchange"
-           );
-           Ext.grid.ColumnModel.superclass.constructor.call(this);
+        return me;
     },
 
     
-    getColumnId : function(index){
-        return this.config[index].id;
-    },
+    onDestroy: function() {
+        var me = this;
+
+        if (me.closeEl) {
+            me.closeEl.un('click', Ext.EventManager.preventDefault);
+            me.closeEl = null;
+        }
+
+        Ext.destroy(me.keyNav);
+        delete me.keyNav;
 
-    getColumnAt : function(index){
-        return this.config[index];
+        me.callParent(arguments);
     },
 
     
-    setConfig : function(config, initial){
-        var i, c, len;
-        if(!initial){ 
-            delete this.totalWidth;
-            for(i = 0, len = this.config.length; i < len; i++){
-                c = this.config[i];
-                if(c.setEditor){
-                    
-                    c.setEditor(null);
-                }
-            }
-        }
+    setClosable: function(closable) {
+        var me = this;
 
         
-        this.defaults = Ext.apply({
-            width: this.defaultWidth,
-            sortable: this.defaultSortable
-        }, this.defaults);
+        closable = (!arguments.length || !!closable);
 
-        this.config = config;
-        this.lookup = {};
+        if (me.closable != closable) {
+            me.closable = closable;
 
-        for(i = 0, len = config.length; i < len; i++){
-            c = Ext.applyIf(config[i], this.defaults);
             
-            if(Ext.isEmpty(c.id)){
-                c.id = i;
+            if (me.card) {
+                me.card.closable = closable;
             }
-            if(!c.isColumn){
-                var Cls = Ext.grid.Column.types[c.xtype || 'gridcolumn'];
-                c = new Cls(c);
-                config[i] = c;
+
+            me.syncClosableUI();
+
+            if (me.rendered) {
+                me.syncClosableElements();
+
+                
+                me.doComponentLayout();
+                if (me.ownerCt) {
+                    me.ownerCt.doLayout();
+                }
             }
-            this.lookup[c.id] = c;
-        }
-        if(!initial){
-            this.fireEvent('configchange', this);
         }
     },
 
     
-    getColumnById : function(id){
-        return this.lookup[id];
+    syncClosableElements: function () {
+        var me = this;
+
+        if (me.closable) {
+            if (!me.closeEl) {
+                me.closeEl = me.el.createChild({
+                    tag: 'a',
+                    cls: me.baseCls + '-close-btn',
+                    href: '#',
+                    
+                    title: me.closeText
+                }).on('click', Ext.EventManager.preventDefault);  
+            }
+        } else {
+            var closeEl = me.closeEl;
+            if (closeEl) {
+                closeEl.un('click', Ext.EventManager.preventDefault);
+                closeEl.remove();
+                me.closeEl = null;
+            }
+        }
     },
 
     
-    getIndexById : function(id){
-        for(var i = 0, len = this.config.length; i < len; i++){
-            if(this.config[i].id == id){
-                return i;
-            }
+    syncClosableUI: function () {
+        var me = this, classes = [me.closableCls, me.closableCls + '-' + me.position];
+
+        if (me.closable) {
+            me.addClsWithUI(classes);
+        } else {
+            me.removeClsWithUI(classes);
         }
-        return -1;
     },
 
     
-    moveColumn : function(oldIndex, newIndex){
-        var c = this.config[oldIndex];
-        this.config.splice(oldIndex, 1);
-        this.config.splice(newIndex, 0, c);
-        this.dataMap = null;
-        this.fireEvent("columnmoved", this, oldIndex, newIndex);
+    setCard: function(card) {
+        var me = this;
+
+        me.card = card;
+        me.setText(me.title || card.title);
+        me.setIconCls(me.iconCls || card.iconCls);
     },
 
     
-    getColumnCount : function(visibleOnly){
-        if(visibleOnly === true){
-            var c = 0;
-            for(var i = 0, len = this.config.length; i < len; i++){
-                if(!this.isHidden(i)){
-                    c++;
+    onCloseClick: function() {
+        var me = this;
+
+        if (me.fireEvent('beforeclose', me) !== false) {
+            if (me.tabBar) {
+                if (me.tabBar.closeTab(me) === false) {
+                    
+                    return;
                 }
+            } else {
+                
+                me.fireEvent('close', me);
             }
-            return c;
         }
-        return this.config.length;
     },
 
     
-    getColumnsBy : function(fn, scope){
-        var r = [];
-        for(var i = 0, len = this.config.length; i < len; i++){
-            var c = this.config[i];
-            if(fn.call(scope||this, c, i) === true){
-                r[r.length] = c;
-            }
-        }
-        return r;
+    fireClose: function(){
+        this.fireEvent('close', this);
     },
 
     
-    isSortable : function(col){
-        return !!this.config[col].sortable;
+    onEnterKey: function(e) {
+        var me = this;
+
+        if (me.tabBar) {
+            me.tabBar.onClick(e, me.el);
+        }
     },
 
-    
-    isMenuDisabled : function(col){
-        return !!this.config[col].menuDisabled;
+   
+    onDeleteKey: function(e) {
+        var me = this;
+
+        if (me.closable) {
+            me.onCloseClick();
+        }
     },
 
     
-    getRenderer : function(col){
-        if(!this.config[col].renderer){
-            return Ext.grid.ColumnModel.defaultRenderer;
+    activate : function(supressEvent) {
+        var me = this;
+
+        me.active = true;
+        me.addClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
+
+        if (supressEvent !== true) {
+            me.fireEvent('activate', me);
         }
-        return this.config[col].renderer;
     },
 
-    getRendererScope : function(col){
-        return this.config[col].scope;
-    },
+    
+    deactivate : function(supressEvent) {
+        var me = this;
 
+        me.active = false;
+        me.removeClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
+
+        if (supressEvent !== true) {
+            me.fireEvent('deactivate', me);
+        }
+    }
+});
+
+
+Ext.define('Ext.tab.Bar', {
+    extend: 'Ext.panel.Header',
+    alias: 'widget.tabbar',
+    baseCls: Ext.baseCSSPrefix + 'tab-bar',
+
+    requires: [
+        'Ext.tab.Tab',
+        'Ext.FocusManager'
+    ],
+
+    isTabBar: true,
+    
+    
+    
     
-    setRenderer : function(col, fn){
-        this.config[col].renderer = fn;
-    },
 
     
-    getColumnWidth : function(col){
-        return this.config[col].width;
-    },
+    defaultType: 'tab',
 
     
-    setColumnWidth : function(col, width, suppressEvent){
-        this.config[col].width = width;
-        this.totalWidth = null;
-        if(!suppressEvent){
-             this.fireEvent("widthchange", this, col, width);
-        }
-    },
+    plain: false,
+
+    
+    renderTpl: [
+        '<div id="{id}-body" class="{baseCls}-body <tpl if="bodyCls"> {bodyCls}</tpl> <tpl if="ui"> {baseCls}-body-{ui}<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl></tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>',
+        '<div id="{id}-strip" class="{baseCls}-strip<tpl if="ui"> {baseCls}-strip-{ui}<tpl for="uiCls"> {parent.baseCls}-strip-{parent.ui}-{.}</tpl></tpl>"></div>'
+    ],
 
     
-    getTotalWidth : function(includeHidden){
-        if(!this.totalWidth){
-            this.totalWidth = 0;
-            for(var i = 0, len = this.config.length; i < len; i++){
-                if(includeHidden || !this.isHidden(i)){
-                    this.totalWidth += this.getColumnWidth(i);
-                }
-            }
-        }
-        return this.totalWidth;
-    },
 
     
-    getColumnHeader : function(col){
-        return this.config[col].header;
-    },
 
     
-    setColumnHeader : function(col, header){
-        this.config[col].header = header;
-        this.fireEvent("headerchange", this, col, header);
+    initComponent: function() {
+        var me = this,
+            keys;
+
+        if (me.plain) {
+            me.setUI(me.ui + '-plain');
+        }
+
+        me.addClsWithUI(me.dock);
+
+        me.addEvents(
+            
+            'change'
+        );
+
+        me.addChildEls('body', 'strip');
+        me.callParent(arguments);
+
+        
+        me.layout.align = (me.orientation == 'vertical') ? 'left' : 'top';
+        me.layout.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.Scroller', me.layout);
+
+        me.remove(me.titleCmp);
+        delete me.titleCmp;
+
+        
+        keys = me.orientation == 'vertical' ? ['up', 'down'] : ['left', 'right'];
+        Ext.FocusManager.subscribe(me, {
+            keys: keys
+        });
+
+        Ext.apply(me.renderData, {
+            bodyCls: me.bodyCls
+        });
     },
 
     
-    getColumnTooltip : function(col){
-            return this.config[col].tooltip;
+    onAdd: function(tab) {
+        tab.position = this.dock;
+        this.callParent(arguments);
     },
     
-    setColumnTooltip : function(col, tooltip){
-            this.config[col].tooltip = tooltip;
+    onRemove: function(tab) {
+        var me = this;
+        
+        if (tab === me.previousTab) {
+            me.previousTab = null;
+        }
+        if (me.items.getCount() === 0) {
+            me.activeTab = null;
+        }
+        me.callParent(arguments);    
     },
 
     
-    getDataIndex : function(col){
-        return this.config[col].dataIndex;
+    afterRender: function() {
+        var me = this;
+
+        me.mon(me.el, {
+            scope: me,
+            click: me.onClick,
+            delegate: '.' + Ext.baseCSSPrefix + 'tab'
+        });
+        me.callParent(arguments);
+
     },
 
-    
-    setDataIndex : function(col, dataIndex){
-        this.config[col].dataIndex = dataIndex;
+    afterComponentLayout : function() {
+        var me = this;
+
+        me.callParent(arguments);
+        me.strip.setWidth(me.el.getWidth());
     },
 
     
-    findColumnIndex : function(dataIndex){
-        var c = this.config;
-        for(var i = 0, len = c.length; i < len; i++){
-            if(c[i].dataIndex == dataIndex){
-                return i;
+    onClick: function(e, target) {
+        
+        var tab = Ext.getCmp(target.id),
+            tabPanel = this.tabPanel;
+
+        target = e.getTarget();
+
+        if (tab && tab.isDisabled && !tab.isDisabled()) {
+            if (tab.closable && target === tab.closeEl.dom) {
+                tab.onCloseClick();
+            } else {
+                if (tabPanel) {
+                    
+                    tabPanel.setActiveTab(tab.card);
+                } else {
+                    this.setActiveTab(tab);
+                }
+                tab.focus();
             }
         }
-        return -1;
     },
 
     
-    isCellEditable : function(colIndex, rowIndex){
-        var c = this.config[colIndex],
-            ed = c.editable;
+    closeTab: function(tab) {
+        var me = this,
+            card = tab.card,
+            tabPanel = me.tabPanel,
+            nextTab;
+
+        if (card && card.fireEvent('beforeclose', card) === false) {
+            return false;
+        }
 
+        if (tab.active && me.items.getCount() > 1) {
+            nextTab = me.previousTab || tab.next('tab') || me.items.first();
+            me.setActiveTab(nextTab);
+            if (tabPanel) {
+                tabPanel.setActiveTab(nextTab.card);
+            }
+        }
         
-        return !!(ed || (!Ext.isDefined(ed) && c.editor));
-    },
+        tab.fireClose();
+        me.remove(tab);
 
-    
-    getCellEditor : function(colIndex, rowIndex){
-        return this.config[colIndex].getCellEditor(rowIndex);
+        if (tabPanel && card) {
+            card.fireEvent('close', card);
+            tabPanel.remove(card);
+        }
+
+        if (nextTab) {
+            nextTab.focus();
+        }
     },
 
     
-    setEditable : function(col, editable){
-        this.config[col].editable = editable;
-    },
+    setActiveTab: function(tab) {
+        if (tab.disabled) {
+            return;
+        }
+        var me = this;
+        if (me.activeTab) {
+            me.previousTab = me.activeTab;
+            me.activeTab.deactivate();
+        }
+        tab.activate();
+
+        if (me.rendered) {
+            me.layout.layout();
+            tab.el && tab.el.scrollIntoView(me.layout.getRenderTarget());
+        }
+        me.activeTab = tab;
+        me.fireEvent('change', me, tab, tab.card);
+    }
+});
+
+
+Ext.define('Ext.tab.Panel', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.tabpanel',
+    alternateClassName: ['Ext.TabPanel'],
+
+    requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
 
     
-    isHidden : function(colIndex){
-        return !!this.config[colIndex].hidden; 
-    },
+    tabPosition : 'top',
 
     
-    isFixed : function(colIndex){
-        return !!this.config[colIndex].fixed;
-    },
 
     
-    isResizable : function(colIndex){
-        return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
-    },
+
     
-    setHidden : function(colIndex, hidden){
-        var c = this.config[colIndex];
-        if(c.hidden !== hidden){
-            c.hidden = hidden;
-            this.totalWidth = null;
-            this.fireEvent("hiddenchange", this, colIndex, hidden);
-        }
-    },
 
     
-    setEditor : function(col, editor){
-        this.config[col].setEditor(editor);
-    },
 
     
-    destroy : function(){
-        var c;
-        for(var i = 0, len = this.config.length; i < len; i++){
-            c = this.config[i];
-            if(c.setEditor){
-                c.setEditor(null);
-            }
-        }
-        this.purgeListeners();
-    },
+    removePanelHeader: true,
+
     
+    plain: false,
+
     
-    setState : function(col, state){
-        Ext.applyIf(this.config[col], state);
-    }
-});
+    itemCls: 'x-tabpanel-child',
 
+    
+    minTabWidth: undefined,
 
-Ext.grid.ColumnModel.defaultRenderer = function(value){
-    if(typeof value == "string" && value.length < 1){
-        return "&#160;";
-    }
-    return value;
-};
-Ext.grid.AbstractSelectionModel = Ext.extend(Ext.util.Observable,  {
     
+    maxTabWidth: undefined,
 
-    constructor : function(){
-        this.locked = false;
-        Ext.grid.AbstractSelectionModel.superclass.constructor.call(this);
-    },
+    
+    deferredRender : true,
 
     
-    init : function(grid){
-        this.grid = grid;
-        if(this.lockOnInit){
-            delete this.lockOnInit;
-            this.locked = false;
-            this.lock();
+    initComponent: function() {
+        var me = this,
+            dockedItems = me.dockedItems || [],
+            activeTab = me.activeTab || 0;
+
+        me.layout = Ext.create('Ext.layout.container.Card', Ext.apply({
+            owner: me,
+            deferredRender: me.deferredRender,
+            itemCls: me.itemCls
+        }, me.layout));
+
+        
+        me.tabBar = Ext.create('Ext.tab.Bar', Ext.apply({}, me.tabBar, {
+            dock: me.tabPosition,
+            plain: me.plain,
+            border: me.border,
+            cardLayout: me.layout,
+            tabPanel: me
+        }));
+
+        if (dockedItems && !Ext.isArray(dockedItems)) {
+            dockedItems = [dockedItems];
         }
-        this.initEvents();
-    },
 
-    
-    lock : function(){
-        if(!this.locked){
-            this.locked = true;
+        dockedItems.push(me.tabBar);
+        me.dockedItems = dockedItems;
+
+        me.addEvents(
             
-            var g = this.grid;
-            if(g){
-                g.getView().on({
-                    scope: this,
-                    beforerefresh: this.sortUnLock,
-                    refresh: this.sortLock
-                });
-            }else{
-                this.lockOnInit = true;
-            }
-        }
-    },
+            'beforetabchange',
 
-    
-    sortLock : function() {
-        this.locked = true;
+            
+            'tabchange'
+        );
+        me.callParent(arguments);
+
+        
+        me.setActiveTab(activeTab);
+        
+        me.on('afterlayout', me.afterInitialLayout, me, {single: true});
     },
 
     
-    sortUnLock : function() {
-        this.locked = false;
+    afterInitialLayout: function() {
+        var me = this,
+            card = me.getComponent(me.activeTab);
+
+        if (card) {
+            me.layout.setActiveItem(card);
+        }
     },
 
     
-    unlock : function(){
-        if(this.locked){
-            this.locked = false;
-            var g = this.grid,
-                gv;
-                
-            
-            if(g){
-                gv = g.getView();
-                gv.un('beforerefresh', this.sortUnLock, this);
-                gv.un('refresh', this.sortLock, this);    
-            }else{
-                delete this.lockOnInit;
+    setActiveTab: function(card) {
+        var me = this,
+            previous;
+
+        card = me.getComponent(card);
+        if (card) {
+            previous = me.getActiveTab();
+
+            if (previous && previous !== card && me.fireEvent('beforetabchange', me, card, previous) === false) {
+                return false;
+            }
+
+            me.tabBar.setActiveTab(card.tab);
+            me.activeTab = card;
+            if (me.rendered) {
+                me.layout.setActiveItem(card);
+            }
+
+            if (previous && previous !== card) {
+                me.fireEvent('tabchange', me, card, previous);
             }
         }
     },
 
     
-    isLocked : function(){
-        return this.locked;
+    getActiveTab: function() {
+        return this.activeTab;
     },
 
-    destroy: function(){
-        this.unlock();
-        this.purgeListeners();
-    }
-});
-Ext.grid.RowSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
     
-    singleSelect : false,
-    
-    constructor : function(config){
-        Ext.apply(this, config);
-        this.selections = new Ext.util.MixedCollection(false, function(o){
-            return o.id;
-        });
-
-        this.last = false;
-        this.lastActive = false;
-
-        this.addEvents(
-               
-               'selectionchange',
-               
-               'beforerowselect',
-               
-               'rowselect',
-               
-               'rowdeselect'
-        );
-        Ext.grid.RowSelectionModel.superclass.constructor.call(this);
+    getTabBar: function() {
+        return this.tabBar;
     },
 
     
-    
-    initEvents : function(){
+    onAdd: function(item, index) {
+        var me = this,
+            cfg = item.tabConfig || {},
+            defaultConfig = {
+                xtype: 'tab',
+                card: item,
+                disabled: item.disabled,
+                closable: item.closable,
+                hidden: item.hidden,
+                tabBar: me.tabBar
+            };
 
-        if(!this.grid.enableDragDrop && !this.grid.enableDrag){
-            this.grid.on('rowmousedown', this.handleMouseDown, this);
+        if (item.closeText) {
+            defaultConfig.closeText = item.closeText;
         }
+        cfg = Ext.applyIf(cfg, defaultConfig);
+        item.tab = me.tabBar.insert(index, cfg);
 
-        this.rowNav = new Ext.KeyNav(this.grid.getGridEl(), {
-            'up' : function(e){
-                if(!e.shiftKey || this.singleSelect){
-                    this.selectPrevious(false);
-                }else if(this.last !== false && this.lastActive !== false){
-                    var last = this.last;
-                    this.selectRange(this.last,  this.lastActive-1);
-                    this.grid.getView().focusRow(this.lastActive);
-                    if(last !== false){
-                        this.last = last;
-                    }
-                }else{
-                    this.selectFirstRow();
-                }
-            },
-            'down' : function(e){
-                if(!e.shiftKey || this.singleSelect){
-                    this.selectNext(false);
-                }else if(this.last !== false && this.lastActive !== false){
-                    var last = this.last;
-                    this.selectRange(this.last,  this.lastActive+1);
-                    this.grid.getView().focusRow(this.lastActive);
-                    if(last !== false){
-                        this.last = last;
-                    }
-                }else{
-                    this.selectFirstRow();
-                }
-            },
-            scope: this
-        });
-
-        this.grid.getView().on({
-            scope: this,
-            refresh: this.onRefresh,
-            rowupdated: this.onRowUpdated,
-            rowremoved: this.onRemove
+        item.on({
+            scope : me,
+            enable: me.onItemEnable,
+            disable: me.onItemDisable,
+            beforeshow: me.onItemBeforeShow,
+            iconchange: me.onItemIconChange,
+            titlechange: me.onItemTitleChange
         });
-    },
 
-    
-    onRefresh : function(){
-        var ds = this.grid.store, index;
-        var s = this.getSelections();
-        this.clearSelections(true);
-        for(var i = 0, len = s.length; i < len; i++){
-            var r = s[i];
-            if((index = ds.indexOfId(r.id)) != -1){
-                this.selectRow(index, true);
+        if (item.isPanel) {
+            if (me.removePanelHeader) {
+                item.preventHeader = true;
+                if (item.rendered) {
+                    item.updateHeader();
+                }
+            }
+            if (item.isPanel && me.border) {
+                item.setBorder(false);
             }
         }
-        if(s.length != this.selections.getCount()){
-            this.fireEvent('selectionchange', this);
+
+        
+        if (this.rendered && me.items.getCount() === 1) {
+            me.setActiveTab(0);
         }
     },
 
     
-    onRemove : function(v, index, r){
-        if(this.selections.remove(r) !== false){
-            this.fireEvent('selectionchange', this);
-        }
+    onItemEnable: function(item){
+        item.tab.enable();
     },
 
     
-    onRowUpdated : function(v, index, r){
-        if(this.isSelected(r)){
-            v.onRowSelect(index);
-        }
+    onItemDisable: function(item){
+        item.tab.disable();
     },
 
     
-    selectRecords : function(records, keepExisting){
-        if(!keepExisting){
-            this.clearSelections();
-        }
-        var ds = this.grid.store;
-        for(var i = 0, len = records.length; i < len; i++){
-            this.selectRow(ds.indexOf(records[i]), true);
+    onItemBeforeShow: function(item) {
+        if (item !== this.activeTab) {
+            this.setActiveTab(item);
+            return false;
         }
     },
 
     
-    getCount : function(){
-        return this.selections.length;
+    onItemIconChange: function(item, newIconCls) {
+        item.tab.setIconCls(newIconCls);
+        this.getTabBar().doLayout();
     },
 
     
-    selectFirstRow : function(){
-        this.selectRow(0);
+    onItemTitleChange: function(item, newTitle) {
+        item.tab.setText(newTitle);
+        this.getTabBar().doLayout();
     },
 
-    
-    selectLastRow : function(keepExisting){
-        this.selectRow(this.grid.store.getCount() - 1, keepExisting);
-    },
 
     
-    selectNext : function(keepExisting){
-        if(this.hasNext()){
-            this.selectRow(this.last+1, keepExisting);
-            this.grid.getView().focusRow(this.last);
-            return true;
+    doRemove: function(item, autoDestroy) {
+        var me = this,
+            items = me.items,
+            
+            
+            
+            hasItemsLeft = items.getCount() > 1;
+
+        if (me.destroying || !hasItemsLeft) {
+            me.activeTab = null;
+        } else if (item === me.activeTab) {
+             me.setActiveTab(item.next() || items.getAt(0));
         }
-        return false;
+        me.callParent(arguments);
+
+        
+        delete item.tab.card;
+        delete item.tab;
     },
 
     
-    selectPrevious : function(keepExisting){
-        if(this.hasPrevious()){
-            this.selectRow(this.last-1, keepExisting);
-            this.grid.getView().focusRow(this.last);
-            return true;
+    onRemove: function(item, autoDestroy) {
+        var me = this;
+
+        item.un({
+            scope : me,
+            enable: me.onItemEnable,
+            disable: me.onItemDisable,
+            beforeshow: me.onItemBeforeShow
+        });
+        if (!me.destroying && item.tab.ownerCt == me.tabBar) {
+            me.tabBar.remove(item.tab);
         }
-        return false;
-    },
+    }
+});
 
-    
-    hasNext : function(){
-        return this.last !== false && (this.last+1) < this.grid.store.getCount();
+
+Ext.define('Ext.toolbar.Spacer', {
+    extend: 'Ext.Component',
+    alias: 'widget.tbspacer',
+    alternateClassName: 'Ext.Toolbar.Spacer',
+    baseCls: Ext.baseCSSPrefix + 'toolbar-spacer',
+    focusable: false
+});
+
+Ext.define('Ext.tree.Column', {
+    extend: 'Ext.grid.column.Column',
+    alias: 'widget.treecolumn',
+
+    initComponent: function() {
+        var origRenderer = this.renderer || this.defaultRenderer,
+            origScope    = this.scope || window;
+
+        this.renderer = function(value, metaData, record, rowIdx, colIdx, store, view) {
+            var buf   = [],
+                format = Ext.String.format,
+                depth = record.getDepth(),
+                treePrefix  = Ext.baseCSSPrefix + 'tree-',
+                elbowPrefix = treePrefix + 'elbow-',
+                expanderCls = treePrefix + 'expander',
+                imgText     = '<img src="{1}" class="{0}" />',
+                checkboxText= '<input type="button" role="checkbox" class="{0}" {1} />',
+                formattedValue = origRenderer.apply(origScope, arguments),
+                href = record.get('href'),
+                target = record.get('hrefTarget'),
+                cls = record.get('cls');
+
+            while (record) {
+                if (!record.isRoot() || (record.isRoot() && view.rootVisible)) {
+                    if (record.getDepth() === depth) {
+                        buf.unshift(format(imgText,
+                            treePrefix + 'icon ' + 
+                            treePrefix + 'icon' + (record.get('icon') ? '-inline ' : (record.isLeaf() ? '-leaf ' : '-parent ')) +
+                            (record.get('iconCls') || ''),
+                            record.get('icon') || Ext.BLANK_IMAGE_URL
+                        ));
+                        if (record.get('checked') !== null) {
+                            buf.unshift(format(
+                                checkboxText,
+                                (treePrefix + 'checkbox') + (record.get('checked') ? ' ' + treePrefix + 'checkbox-checked' : ''),
+                                record.get('checked') ? 'aria-checked="true"' : ''
+                            ));
+                            if (record.get('checked')) {
+                                metaData.tdCls += (' ' + treePrefix + 'checked');
+                            }
+                        }
+                        if (record.isLast()) {
+                            if (record.isExpandable()) {
+                                buf.unshift(format(imgText, (elbowPrefix + 'end-plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
+                            } else {
+                                buf.unshift(format(imgText, (elbowPrefix + 'end'), Ext.BLANK_IMAGE_URL));
+                            }
+                            
+                        } else {
+                            if (record.isExpandable()) {
+                                buf.unshift(format(imgText, (elbowPrefix + 'plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
+                            } else {
+                                buf.unshift(format(imgText, (treePrefix + 'elbow'), Ext.BLANK_IMAGE_URL));
+                            }
+                        }
+                    } else {
+                        if (record.isLast() || record.getDepth() === 0) {
+                            buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL));
+                        } else if (record.getDepth() !== 0) {
+                            buf.unshift(format(imgText, (elbowPrefix + 'line'), Ext.BLANK_IMAGE_URL));
+                        }                      
+                    }
+                }
+                record = record.parentNode;
+            }
+            if (href) {
+                buf.push('<a href="', href, '" target="', target, '">', formattedValue, '</a>');
+            } else {
+                buf.push(formattedValue);
+            }
+            if (cls) {
+                metaData.tdCls += ' ' + cls;
+            }
+            return buf.join('');
+        };
+        this.callParent(arguments);
     },
 
+    defaultRenderer: function(value) {
+        return value;
+    }
+});
+
+Ext.define('Ext.tree.View', {
+    extend: 'Ext.view.Table',
+    alias: 'widget.treeview',
+
+    loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading',
+    expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded',
+
+    expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander',
+    checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox',
+    expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over',
+
     
-    hasPrevious : function(){
-        return !!this.last;
-    },
+    
+    
+    nodeAnimWrapCls: Ext.baseCSSPrefix + 'tree-animator-wrap',
 
+    blockRefresh: true,
 
     
-    getSelections : function(){
-        return [].concat(this.selections.items);
-    },
+    rootVisible: true,
 
     
-    getSelected : function(){
-        return this.selections.itemAt(0);
-    },
 
+    expandDuration: 250,
+    collapseDuration: 250,
     
-    each : function(fn, scope){
-        var s = this.getSelections();
-        for(var i = 0, len = s.length; i < len; i++){
-            if(fn.call(scope || this, s[i], i) === false){
-                return false;
+    toggleOnDblClick: true,
+
+    initComponent: function() {
+        var me = this;
+        
+        if (me.initialConfig.animate === undefined) {
+            me.animate = Ext.enableFx;
+        }
+        
+        me.store = Ext.create('Ext.data.NodeStore', {
+            recursive: true,
+            rootVisible: me.rootVisible,
+            listeners: {
+                beforeexpand: me.onBeforeExpand,
+                expand: me.onExpand,
+                beforecollapse: me.onBeforeCollapse,
+                collapse: me.onCollapse,
+                scope: me
             }
+        });
+        
+        if (me.node) {
+            me.setRootNode(me.node);
         }
-        return true;
+        me.animQueue = {};
+        me.callParent(arguments);
     },
 
-    
-    clearSelections : function(fast){
-        if(this.isLocked()){
-            return;
-        }
-        if(fast !== true){
-            var ds = this.grid.store;
-            var s = this.selections;
-            s.each(function(r){
-                this.deselectRow(ds.indexOfId(r.id));
-            }, this);
-            s.clear();
-        }else{
-            this.selections.clear();
+    processUIEvent: function(e) {
+        
+        
+        
+        if (e.getTarget('.' + this.nodeAnimWrapCls, this.el)) {
+            return false;
         }
-        this.last = false;
+        return this.callParent(arguments);
     },
 
+    onClear: function(){
+        this.store.removeAll();    
+    },
 
-    
-    selectAll : function(){
-        if(this.isLocked()){
-            return;
-        }
-        this.selections.clear();
-        for(var i = 0, len = this.grid.store.getCount(); i < len; i++){
-            this.selectRow(i, true);
+    setRootNode: function(node) {
+        var me = this;        
+        me.store.setNode(node);
+        me.node = node;
+        if (!me.rootVisible) {
+            node.expand();
         }
     },
-
     
-    hasSelection : function(){
-        return this.selections.length > 0;
+    onRender: function() {
+        var me = this,
+            el;
+
+        me.callParent(arguments);
+
+        el = me.el;
+        el.on({
+            scope: me,
+            delegate: me.expanderSelector,
+            mouseover: me.onExpanderMouseOver,
+            mouseout: me.onExpanderMouseOut
+        });
+        el.on({
+            scope: me,
+            delegate: me.checkboxSelector,
+            click: me.onCheckboxChange
+        });
     },
 
+    onCheckboxChange: function(e, t) {
+        var me = this,
+            item = e.getTarget(me.getItemSelector(), me.getTargetEl());
+            
+        if (item) {
+            me.onCheckChange(me.getRecord(item));
+        }
+    },
     
-    isSelected : function(index){
-        var r = Ext.isNumber(index) ? this.grid.store.getAt(index) : index;
-        return (r && this.selections.key(r.id) ? true : false);
+    onCheckChange: function(record){
+        var checked = record.get('checked');
+        if (Ext.isBoolean(checked)) {
+            checked = !checked;
+            record.set('checked', checked);
+            this.fireEvent('checkchange', record, checked);
+        }
     },
 
+    getChecked: function() {
+        var checked = [];
+        this.node.cascadeBy(function(rec){
+            if (rec.get('checked')) {
+                checked.push(rec);
+            }
+        });
+        return checked;
+    },
     
-    isIdSelected : function(id){
-        return (this.selections.key(id) ? true : false);
+    isItemChecked: function(rec){
+        return rec.get('checked');
     },
 
-    
-    handleMouseDown : function(g, rowIndex, e){
-        if(e.button !== 0 || this.isLocked()){
-            return;
+    createAnimWrap: function(record, index) {
+        var thHtml = '',
+            headerCt = this.panel.headerCt,
+            headers = headerCt.getGridColumns(),
+            i = 0, len = headers.length, item,
+            node = this.getNode(record),
+            tmpEl, nodeEl;
+
+        for (; i < len; i++) {
+            item = headers[i];
+            thHtml += '<th style="width: ' + (item.hidden ? 0 : item.getDesiredWidth()) + 'px; height: 0px;"></th>';
         }
-        var view = this.grid.getView();
-        if(e.shiftKey && !this.singleSelect && this.last !== false){
-            var last = this.last;
-            this.selectRange(last, rowIndex, e.ctrlKey);
-            this.last = last; 
-            view.focusRow(rowIndex);
-        }else{
-            var isSelected = this.isSelected(rowIndex);
-            if(e.ctrlKey && isSelected){
-                this.deselectRow(rowIndex);
-            }else if(!isSelected || this.getCount() > 1){
-                this.selectRow(rowIndex, e.ctrlKey || e.shiftKey);
-                view.focusRow(rowIndex);
+
+        nodeEl = Ext.get(node);        
+        tmpEl = nodeEl.insertSibling({
+            tag: 'tr',
+            html: [
+                '<td colspan="' + headerCt.getColumnCount() + '">',
+                    '<div class="' + this.nodeAnimWrapCls + '">',
+                        '<table class="' + Ext.baseCSSPrefix + 'grid-table" style="width: ' + headerCt.getFullWidth() + 'px;"><tbody>',
+                            thHtml,
+                        '</tbody></table>',
+                    '</div>',
+                '</td>'
+            ].join('')
+        }, 'after');
+
+        return {
+            record: record,
+            node: node,
+            el: tmpEl,
+            expanding: false,
+            collapsing: false,
+            animating: false,
+            animateEl: tmpEl.down('div'),
+            targetEl: tmpEl.down('tbody')
+        };
+    },
+
+    getAnimWrap: function(parent) {
+        if (!this.animate) {
+            return null;
+        }
+
+        
+        while (parent) {
+            if (parent.animWrap) {
+                return parent.animWrap;
             }
+            parent = parent.parentNode;
         }
+        return null;
     },
 
-    
-    selectRows : function(rows, keepExisting){
-        if(!keepExisting){
-            this.clearSelections();
+    doAdd: function(nodes, records, index) {
+        
+        
+        var me = this,
+            record = records[0],
+            parent = record.parentNode,
+            a = me.all.elements,
+            relativeIndex = 0,
+            animWrap = me.getAnimWrap(parent),
+            targetEl, children, len;
+
+        if (!animWrap || !animWrap.expanding) {
+            me.resetScrollers();
+            return me.callParent(arguments);
         }
-        for(var i = 0, len = rows.length; i < len; i++){
-            this.selectRow(rows[i], true);
+
+        
+        parent = animWrap.record;
+        
+        
+        targetEl = animWrap.targetEl;
+        children = targetEl.dom.childNodes;
+        
+        
+        len = children.length - 1;
+        
+        
+        relativeIndex = index - me.indexOf(parent) - 1;
+        
+        
+        
+        if (!len || relativeIndex >= len) {
+            targetEl.appendChild(nodes);
+        }
+        
+        
+        else {
+            
+            Ext.fly(children[relativeIndex + 1]).insertSibling(nodes, 'before', true);
         }
-    },
 
+        
+        Ext.Array.insert(a, index, nodes);
+        
+        
+        
+        if (animWrap.isAnimating) {
+            me.onExpand(parent);
+        }
+    },
     
-    selectRange : function(startRow, endRow, keepExisting){
-        var i;
-        if(this.isLocked()){
-            return;
+    beginBulkUpdate: function(){
+        this.bulkUpdate = true;
+        this.ownerCt.changingScrollbars = true;  
+    },
+    
+    endBulkUpdate: function(){
+        var me = this,
+            ownerCt = me.ownerCt;
+        
+        me.bulkUpdate = false;
+        me.ownerCt.changingScrollbars = true;  
+        me.resetScrollers();  
+    },
+    
+    onRemove : function(ds, record, index) {
+        var me = this,
+            bulk = me.bulkUpdate;
+
+        me.doRemove(record, index);
+        if (!bulk) {
+            me.updateIndexes(index);
         }
-        if(!keepExisting){
-            this.clearSelections();
+        if (me.store.getCount() === 0){
+            me.refresh();
         }
-        if(startRow <= endRow){
-            for(i = startRow; i <= endRow; i++){
-                this.selectRow(i, true);
-            }
-        }else{
-            for(i = startRow; i >= endRow; i--){
-                this.selectRow(i, true);
-            }
+        if (!bulk) {
+            me.fireEvent('itemremove', record, index);
         }
     },
-
     
-    deselectRange : function(startRow, endRow, preventViewNotify){
-        if(this.isLocked()){
-            return;
-        }
-        for(var i = startRow; i <= endRow; i++){
-            this.deselectRow(i, preventViewNotify);
+    doRemove: function(record, index) {
+        
+        
+        var me = this,
+            parent = record.parentNode,
+            all = me.all,
+            animWrap = me.getAnimWrap(record),
+            node = all.item(index).dom;
+
+        if (!animWrap || !animWrap.collapsing) {
+            me.resetScrollers();
+            return me.callParent(arguments);
         }
+
+        animWrap.targetEl.appendChild(node);
+        all.removeElement(index);
     },
 
-    
-    selectRow : function(index, keepExisting, preventViewNotify){
-        if(this.isLocked() || (index < 0 || index >= this.grid.store.getCount()) || (keepExisting && this.isSelected(index))){
+    onBeforeExpand: function(parent, records, index) {
+        var me = this,
+            animWrap;
+            
+        if (!me.rendered || !me.animate) {
             return;
         }
-        var r = this.grid.store.getAt(index);
-        if(r && this.fireEvent('beforerowselect', this, index, keepExisting, r) !== false){
-            if(!keepExisting || this.singleSelect){
-                this.clearSelections();
-            }
-            this.selections.add(r);
-            this.last = this.lastActive = index;
-            if(!preventViewNotify){
-                this.grid.getView().onRowSelect(index);
+
+        if (me.getNode(parent)) {
+            animWrap = me.getAnimWrap(parent);
+            if (!animWrap) {
+                animWrap = parent.animWrap = me.createAnimWrap(parent);
+                animWrap.animateEl.setHeight(0);
             }
-            this.fireEvent('rowselect', this, index, r);
-            this.fireEvent('selectionchange', this);
+            else if (animWrap.collapsing) {
+                
+                
+                animWrap.targetEl.select(me.itemSelector).remove();
+            } 
+            animWrap.expanding = true;
+            animWrap.collapsing = false;
         }
     },
 
-    
-    deselectRow : function(index, preventViewNotify){
-        if(this.isLocked()){
+    onExpand: function(parent) {
+        var me = this,
+            queue = me.animQueue,
+            id = parent.getId(),
+            animWrap,
+            animateEl, 
+            targetEl,
+            queueItem;        
+        
+        if (me.singleExpand) {
+            me.ensureSingleExpand(parent);
+        }
+        
+        animWrap = me.getAnimWrap(parent);
+
+        if (!animWrap) {
+            me.resetScrollers();
             return;
         }
-        if(this.last == index){
-            this.last = false;
+        
+        animateEl = animWrap.animateEl;
+        targetEl = animWrap.targetEl;
+
+        animateEl.stopAnimation();
+        
+        queue[id] = true;
+        animateEl.slideIn('t', {
+            duration: me.expandDuration,
+            listeners: {
+                scope: me,
+                lastframe: function() {
+                    
+                    animWrap.el.insertSibling(targetEl.query(me.itemSelector), 'before');
+                    animWrap.el.remove();
+                    me.resetScrollers();
+                    delete animWrap.record.animWrap;
+                    delete queue[id];
+                }
+            }
+        });
+        
+        animWrap.isAnimating = true;
+    },
+    
+    resetScrollers: function(){
+        if (!this.bulkUpdate) {
+            var panel = this.panel;
+            
+            panel.determineScrollbars();
+            panel.invalidateScroller();
         }
-        if(this.lastActive == index){
-            this.lastActive = false;
+    },
+
+    onBeforeCollapse: function(parent, records, index) {
+        var me = this,
+            animWrap;
+            
+        if (!me.rendered || !me.animate) {
+            return;
         }
-        var r = this.grid.store.getAt(index);
-        if(r){
-            this.selections.remove(r);
-            if(!preventViewNotify){
-                this.grid.getView().onRowDeselect(index);
+
+        if (me.getNode(parent)) {
+            animWrap = me.getAnimWrap(parent);
+            if (!animWrap) {
+                animWrap = parent.animWrap = me.createAnimWrap(parent, index);
+            }
+            else if (animWrap.expanding) {
+                
+                
+                animWrap.targetEl.select(this.itemSelector).remove();
             }
-            this.fireEvent('rowdeselect', this, index, r);
-            this.fireEvent('selectionchange', this);
+            animWrap.expanding = false;
+            animWrap.collapsing = true;
         }
     },
-
     
-    restoreLast : function(){
-        if(this._last){
-            this.last = this._last;
+    onCollapse: function(parent) {
+        var me = this,
+            queue = me.animQueue,
+            id = parent.getId(),
+            animWrap = me.getAnimWrap(parent),
+            animateEl, targetEl;
+
+        if (!animWrap) {
+            me.resetScrollers();
+            return;
         }
-    },
+        
+        animateEl = animWrap.animateEl;
+        targetEl = animWrap.targetEl;
 
+        queue[id] = true;
+        
+        
+        animateEl.stopAnimation();
+        animateEl.slideOut('t', {
+            duration: me.collapseDuration,
+            listeners: {
+                scope: me,
+                lastframe: function() {
+                    animWrap.el.remove();
+                    delete animWrap.record.animWrap;
+                    me.resetScrollers();
+                    delete queue[id];
+                }             
+            }
+        });
+        animWrap.isAnimating = true;
+    },
     
-    acceptsNav : function(row, col, cm){
-        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    
+    isAnimating: function(node) {
+        return !!this.animQueue[node.getId()];    
     },
-
     
-    onEditorKey : function(field, e){
-        var k = e.getKey(), 
-            newCell, 
-            g = this.grid, 
-            last = g.lastEdit,
-            ed = g.activeEditor,
-            ae, last, r, c;
-        var shift = e.shiftKey;
-        if(k == e.TAB){
-            e.stopEvent();
-            ed.completeEdit();
-            if(shift){
-                newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
-            }else{
-                newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
-            }
-        }else if(k == e.ENTER){
-            if(this.moveEditorOnEnter !== false){
-                if(shift){
-                    newCell = g.walkCells(last.row - 1, last.col, -1, this.acceptsNav, this);
-                }else{
-                    newCell = g.walkCells(last.row + 1, last.col, 1, this.acceptsNav, this);
+    collectData: function(records) {
+        var data = this.callParent(arguments),
+            rows = data.rows,
+            len = rows.length,
+            i = 0,
+            row, record;
+            
+        for (; i < len; i++) {
+            row = rows[i];
+            record = records[i];
+            if (record.get('qtip')) {
+                row.rowAttr = 'data-qtip="' + record.get('qtip') + '"';
+                if (record.get('qtitle')) {
+                    row.rowAttr += ' ' + 'data-qtitle="' + record.get('qtitle') + '"';
                 }
             }
-        }
-        if(newCell){
-            r = newCell[0];
-            c = newCell[1];
-
-            if(last.row != r){
-                this.selectRow(r); 
+            if (record.isExpanded()) {
+                row.rowCls = (row.rowCls || '') + ' ' + this.expandedCls;
             }
-
-            if(g.isEditor && g.editing){ 
-                ae = g.activeEditor;
-                if(ae && ae.field.triggerBlur){
-                    
-                    ae.field.triggerBlur();
-                }
+            if (record.isLoading()) {
+                row.rowCls = (row.rowCls || '') + ' ' + this.loadingCls;
             }
-            g.startEditing(r, c);
         }
+        
+        return data;
     },
     
-    destroy : function(){
-        if(this.rowNav){
-            this.rowNav.disable();
-            this.rowNav = null;
-        }
-        Ext.grid.RowSelectionModel.superclass.destroy.call(this);
-    }
-});
-Ext.grid.Column = Ext.extend(Object, {
     
+    expand: function(record, deep, callback, scope) {
+        return record.expand(deep, callback, scope);
+    },
     
     
+    collapse: function(record, deep, callback, scope) {
+        return record.collapse(deep, callback, scope);
+    },
     
     
+    toggle: function(record) {
+        this[record.isExpanded() ? 'collapse' : 'expand'](record);
+    },
     
+    onItemDblClick: function(record, item, index) {
+        this.callParent(arguments);
+        if (this.toggleOnDblClick) {
+            this.toggle(record);
+        }
+    },
     
+    onBeforeItemMouseDown: function(record, item, index, e) {
+        if (e.getTarget(this.expanderSelector, item)) {
+            return false;
+        }
+        return this.callParent(arguments);
+    },
     
+    onItemClick: function(record, item, index, e) {
+        if (e.getTarget(this.expanderSelector, item)) {
+            this.toggle(record);
+            return false;
+        }
+        return this.callParent(arguments);
+    },
     
+    onExpanderMouseOver: function(e, t) {
+        e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls);
+    },
     
+    onExpanderMouseOut: function(e, t) {
+        e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls);
+    },
     
     
+    getTreeStore: function() {
+        return this.panel.store;
+    },    
     
+    ensureSingleExpand: function(node) {
+        var parent = node.parentNode;
+        if (parent) {
+            parent.eachChild(function(child) {
+                if (child !== node && child.isExpanded()) {
+                    child.collapse();
+                }
+            });
+        }
+    }
+});
+
+Ext.define('Ext.tree.Panel', {
+    extend: 'Ext.panel.Table',
+    alias: 'widget.treepanel',
+    alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
+    requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
+    viewType: 'treeview',
+    selType: 'treemodel',
+
+    treeCls: Ext.baseCSSPrefix + 'tree-panel',
+
+    deferRowRender: false,
+
     
+    lines: true,
+
     
+    useArrows: false,
+
     
+    singleExpand: false,
+
+    ddConfig: {
+        enableDrag: true,
+        enableDrop: true
+    },
+
     
+
     
+    rootVisible: true,
+
     
+    displayField: 'text',
+
     
+    root: null,
+
     
     
+    normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
+    lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
 
     
-    isColumn : true,
 
-    constructor : function(config){
-        Ext.apply(this, config);
+    
 
-        if(Ext.isString(this.renderer)){
-            this.renderer = Ext.util.Format[this.renderer];
-        }else if(Ext.isObject(this.renderer)){
-            this.scope = this.renderer.scope;
-            this.renderer = this.renderer.fn;
-        }
-        if(!this.scope){
-            this.scope = this;
+    constructor: function(config) {
+        config = config || {};
+        if (config.animate === undefined) {
+            config.animate = Ext.enableFx;
         }
+        this.enableAnimations = config.animate;
+        delete config.animate;
 
-        var ed = this.editor;
-        delete this.editor;
-        this.setEditor(ed);
-    },
-
-    
-    renderer : function(value){
-        if(Ext.isString(value) && value.length < 1){
-            return '&#160;';
-        }
-        return value;
+        this.callParent([config]);
     },
 
-    
-    getEditor: function(rowIndex){
-        return this.editable !== false ? this.editor : null;
-    },
+    initComponent: function() {
+        var me = this,
+            cls = [me.treeCls];
 
-    
-    setEditor : function(editor){
-        var ed = this.editor;
-        if(ed){
-            if(ed.gridEditor){
-                ed.gridEditor.destroy();
-                delete ed.gridEditor;
-            }else{
-                ed.destroy();
-            }
+        if (me.useArrows) {
+            cls.push(Ext.baseCSSPrefix + 'tree-arrows');
+            me.lines = false;
         }
-        this.editor = null;
-        if(editor){
-            
-            if(!editor.isXType){
-                editor = Ext.create(editor, 'textfield');
-            }
-            this.editor = editor;
+
+        if (me.lines) {
+            cls.push(Ext.baseCSSPrefix + 'tree-lines');
+        } else if (!me.useArrows) {
+            cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
         }
-    },
 
-    
-    getCellEditor: function(rowIndex){
-        var ed = this.getEditor(rowIndex);
-        if(ed){
-            if(!ed.startEdit){
-                if(!ed.gridEditor){
-                    ed.gridEditor = new Ext.grid.GridEditor(ed);
-                }
-                ed = ed.gridEditor;
+        if (Ext.isString(me.store)) {
+            me.store = Ext.StoreMgr.lookup(me.store);
+        } else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
+            me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
+                root: me.root,
+                fields: me.fields,
+                model: me.model,
+                folderSort: me.folderSort
+            }));
+        } else if (me.root) {
+            me.store = Ext.data.StoreManager.lookup(me.store);
+            me.store.setRootNode(me.root);
+            if (me.folderSort !== undefined) {
+                me.store.folderSort = me.folderSort;
+                me.store.sort();
             }
         }
-        return ed;
-    }
-});
-
-
-Ext.grid.BooleanColumn = Ext.extend(Ext.grid.Column, {
-    
-    trueText: 'true',
-    
-    falseText: 'false',
-    
-    undefinedText: '&#160;',
 
-    constructor: function(cfg){
-        Ext.grid.BooleanColumn.superclass.constructor.call(this, cfg);
-        var t = this.trueText, f = this.falseText, u = this.undefinedText;
-        this.renderer = function(v){
-            if(v === undefined){
-                return u;
-            }
-            if(!v || v === 'false'){
-                return f;
-            }
-            return t;
-        };
-    }
-});
+        
+        
+        
+        
 
+        me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
+            rootVisible: me.rootVisible,
+            animate: me.enableAnimations,
+            singleExpand: me.singleExpand,
+            node: me.store.getRootNode(),
+            hideHeaders: me.hideHeaders
+        });
 
-Ext.grid.NumberColumn = Ext.extend(Ext.grid.Column, {
-    
-    format : '0,000.00',
-    constructor: function(cfg){
-        Ext.grid.NumberColumn.superclass.constructor.call(this, cfg);
-        this.renderer = Ext.util.Format.numberRenderer(this.format);
-    }
-});
+        me.mon(me.store, {
+            scope: me,
+            rootchange: me.onRootChange,
+            clear: me.onClear
+        });
 
+        me.relayEvents(me.store, [
+            
+            'beforeload',
 
-Ext.grid.DateColumn = Ext.extend(Ext.grid.Column, {
-    
-    format : 'm/d/Y',
-    constructor: function(cfg){
-        Ext.grid.DateColumn.superclass.constructor.call(this, cfg);
-        this.renderer = Ext.util.Format.dateRenderer(this.format);
-    }
-});
+            
+            'load'
+        ]);
 
+        me.store.on({
+            
+            append: me.createRelayer('itemappend'),
 
-Ext.grid.TemplateColumn = Ext.extend(Ext.grid.Column, {
-    
-    constructor: function(cfg){
-        Ext.grid.TemplateColumn.superclass.constructor.call(this, cfg);
-        var tpl = (!Ext.isPrimitive(this.tpl) && this.tpl.compile) ? this.tpl : new Ext.XTemplate(this.tpl);
-        this.renderer = function(value, p, r){
-            return tpl.apply(r.data);
-        };
-        this.tpl = tpl;
-    }
-});
+            
+            remove: me.createRelayer('itemremove'),
 
+            
+            move: me.createRelayer('itemmove'),
 
-Ext.grid.Column.types = {
-    gridcolumn : Ext.grid.Column,
-    booleancolumn: Ext.grid.BooleanColumn,
-    numbercolumn: Ext.grid.NumberColumn,
-    datecolumn: Ext.grid.DateColumn,
-    templatecolumn: Ext.grid.TemplateColumn
-};
-Ext.grid.RowNumberer = Ext.extend(Object, {
-    
-    header: "",
-    
-    width: 23,
-    
-    sortable: false,
-    
-    constructor : function(config){
-        Ext.apply(this, config);
-        if(this.rowspan){
-            this.renderer = this.renderer.createDelegate(this);
-        }
-    },
+            
+            insert: me.createRelayer('iteminsert'),
 
-    
-    fixed:true,
-    hideable: false,
-    menuDisabled:true,
-    dataIndex: '',
-    id: 'numberer',
-    rowspan: undefined,
+            
+            beforeappend: me.createRelayer('beforeitemappend'),
 
-    
-    renderer : function(v, p, record, rowIndex){
-        if(this.rowspan){
-            p.cellAttr = 'rowspan="'+this.rowspan+'"';
-        }
-        return rowIndex+1;
-    }
-});
-Ext.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.RowSelectionModel, {
+            
+            beforeremove: me.createRelayer('beforeitemremove'),
 
-    
-    
-    header : '<div class="x-grid3-hd-checker">&#160;</div>',
-    
-    width : 20,
-    
-    sortable : false,
+            
+            beforemove: me.createRelayer('beforeitemmove'),
 
-    
-    menuDisabled : true,
-    fixed : true,
-    hideable: false,
-    dataIndex : '',
-    id : 'checker',
+            
+            beforeinsert: me.createRelayer('beforeiteminsert'),
 
-    constructor : function(){
-        Ext.grid.CheckboxSelectionModel.superclass.constructor.apply(this, arguments);
+            
+            expand: me.createRelayer('itemexpand'),
 
-        if(this.checkOnly){
-            this.handleMouseDown = Ext.emptyFn;
-        }
-    },
+            
+            collapse: me.createRelayer('itemcollapse'),
 
-    
-    initEvents : function(){
-        Ext.grid.CheckboxSelectionModel.superclass.initEvents.call(this);
-        this.grid.on('render', function(){
-            var view = this.grid.getView();
-            view.mainBody.on('mousedown', this.onMouseDown, this);
-            Ext.fly(view.innerHd).on('mousedown', this.onHdMouseDown, this);
+            
+            beforeexpand: me.createRelayer('beforeitemexpand'),
 
-        }, this);
-    },
+            
+            beforecollapse: me.createRelayer('beforeitemcollapse')
+        });
 
-    
-    
-    handleMouseDown : function() {
-        Ext.grid.CheckboxSelectionModel.superclass.handleMouseDown.apply(this, arguments);
-        this.mouseHandled = true;
-    },
+        
+        if (!me.columns) {
+            if (me.initialConfig.hideHeaders === undefined) {
+                me.hideHeaders = true;
+            }
+            me.columns = [{
+                xtype    : 'treecolumn',
+                text     : 'Name',
+                flex     : 1,
+                dataIndex: me.displayField
+            }];
+        }
 
-    
-    onMouseDown : function(e, t){
-        if(e.button === 0 && t.className == 'x-grid3-row-checker'){ 
-            e.stopEvent();
-            var row = e.getTarget('.x-grid3-row');
+        if (me.cls) {
+            cls.push(me.cls);
+        }
+        me.cls = cls.join(' ');
+        me.callParent();
 
+        me.relayEvents(me.getView(), [
             
-            if(!this.mouseHandled && row){
-                var index = row.rowIndex;
-                if(this.isSelected(index)){
-                    this.deselectRow(index);
-                }else{
-                    this.selectRow(index, true);
-                    this.grid.getView().focusRow(index);
-                }
-            }
-        }
-        this.mouseHandled = false;
-    },
+            'checkchange'
+        ]);
 
-    
-    onHdMouseDown : function(e, t){
-        if(t.className == 'x-grid3-hd-checker'){
-            e.stopEvent();
-            var hd = Ext.fly(t.parentNode);
-            var isChecked = hd.hasClass('x-grid3-hd-checker-on');
-            if(isChecked){
-                hd.removeClass('x-grid3-hd-checker-on');
-                this.clearSelections();
-            }else{
-                hd.addClass('x-grid3-hd-checker-on');
-                this.selectAll();
-            }
+        
+        if (!me.getView().rootVisible && !me.getRootNode()) {
+            me.setRootNode({
+                expanded: true
+            });
         }
     },
 
-    
-    renderer : function(v, p, record){
-        return '<div class="x-grid3-row-checker">&#160;</div>';
-    }
-});
-Ext.grid.CellSelectionModel = Ext.extend(Ext.grid.AbstractSelectionModel,  {
-    
-    constructor : function(config){
-        Ext.apply(this, config);
-
-           this.selection = null;
-       
-           this.addEvents(
-               
-               "beforecellselect",
-               
-               "cellselect",
-               
-               "selectionchange"
-           );
-       
-           Ext.grid.CellSelectionModel.superclass.constructor.call(this);
+    onClear: function(){
+        this.view.onClear();
     },
 
     
-    initEvents : function(){
-        this.grid.on('cellmousedown', this.handleMouseDown, this);
-        this.grid.on(Ext.EventManager.useKeydown ? 'keydown' : 'keypress', this.handleKeyDown, this);
-        this.grid.getView().on({
-            scope: this,
-            refresh: this.onViewChange,
-            rowupdated: this.onRowUpdated,
-            beforerowremoved: this.clearSelections,
-            beforerowsinserted: this.clearSelections
-        });
-        if(this.grid.isEditor){
-            this.grid.on('beforeedit', this.beforeEdit,  this);
-        }
+    setRootNode: function() {
+        return this.store.setRootNode.apply(this.store, arguments);
     },
 
-       
-    beforeEdit : function(e){
-        this.select(e.row, e.column, false, true, e.record);
+    
+    getRootNode: function() {
+        return this.store.getRootNode();
     },
 
-       
-    onRowUpdated : function(v, index, r){
-        if(this.selection && this.selection.record == r){
-            v.onCellSelect(index, this.selection.cell[1]);
-        }
+    onRootChange: function(root) {
+        this.view.setRootNode(root);
     },
 
-       
-    onViewChange : function(){
-        this.clearSelections(true);
+    
+    getChecked: function() {
+        return this.getView().getChecked();
     },
 
-       
-    getSelectedCell : function(){
-        return this.selection ? this.selection.cell : null;
+    isItemChecked: function(rec) {
+        return rec.get('checked');
     },
 
     
-    clearSelections : function(preventNotify){
-        var s = this.selection;
-        if(s){
-            if(preventNotify !== true){
-                this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
+    expandAll : function(callback, scope) {
+        var root = this.getRootNode(),
+            animate = this.enableAnimations,
+            view = this.getView();
+        if (root) {
+            if (!animate) {
+                view.beginBulkUpdate();
+            }
+            root.expand(true, callback, scope);
+            if (!animate) {
+                view.endBulkUpdate();
             }
-            this.selection = null;
-            this.fireEvent("selectionchange", this, null);
         }
     },
 
     
-    hasSelection : function(){
-        return this.selection ? true : false;
+    collapseAll : function(callback, scope) {
+        var root = this.getRootNode(),
+            animate = this.enableAnimations,
+            view = this.getView();
+
+        if (root) {
+            if (!animate) {
+                view.beginBulkUpdate();
+            }
+            if (view.rootVisible) {
+                root.collapse(true, callback, scope);
+            } else {
+                root.collapseChildren(true, callback, scope);
+            }
+            if (!animate) {
+                view.endBulkUpdate();
+            }
+        }
     },
 
     
-    handleMouseDown : function(g, row, cell, e){
-        if(e.button !== 0 || this.isLocked()){
+    expandPath: function(path, field, separator, callback, scope) {
+        var me = this,
+            current = me.getRootNode(),
+            index = 1,
+            view = me.getView(),
+            keys,
+            expander;
+
+        field = field || me.getRootNode().idProperty;
+        separator = separator || '/';
+
+        if (Ext.isEmpty(path)) {
+            Ext.callback(callback, scope || me, [false, null]);
+            return;
+        }
+
+        keys = path.split(separator);
+        if (current.get(field) != keys[1]) {
+            
+            Ext.callback(callback, scope || me, [false, current]);
             return;
         }
-        this.select(row, cell);
+
+        expander = function(){
+            if (++index === keys.length) {
+                Ext.callback(callback, scope || me, [true, current]);
+                return;
+            }
+            var node = current.findChild(field, keys[index]);
+            if (!node) {
+                Ext.callback(callback, scope || me, [false, current]);
+                return;
+            }
+            current = node;
+            current.expand(false, expander);
+        };
+        current.expand(false, expander);
     },
 
     
-    select : function(rowIndex, colIndex, preventViewNotify, preventFocus,  r){
-        if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
-            this.clearSelections();
-            r = r || this.grid.store.getAt(rowIndex);
-            this.selection = {
-                record : r,
-                cell : [rowIndex, colIndex]
-            };
-            if(!preventViewNotify){
-                var v = this.grid.getView();
-                v.onCellSelect(rowIndex, colIndex);
-                if(preventFocus !== true){
-                    v.focusCell(rowIndex, colIndex);
+    selectPath: function(path, field, separator, callback, scope) {
+        var me = this,
+            keys,
+            last;
+
+        field = field || me.getRootNode().idProperty;
+        separator = separator || '/';
+
+        keys = path.split(separator);
+        last = keys.pop();
+
+        me.expandPath(keys.join(separator), field, separator, function(success, node){
+            var doSuccess = false;
+            if (success && node) {
+                node = node.findChild(field, last);
+                if (node) {
+                    me.getSelectionModel().select(node);
+                    Ext.callback(callback, scope || me, [true, node]);
+                    doSuccess = true;
                 }
+            } else if (node === me.getRootNode()) {
+                doSuccess = true;
             }
-            this.fireEvent("cellselect", this, rowIndex, colIndex);
-            this.fireEvent("selectionchange", this, this.selection);
+            Ext.callback(callback, scope || me, [doSuccess, node]);
+        }, me);
+    }
+});
+
+
+Ext.define('Ext.view.DragZone', {
+    extend: 'Ext.dd.DragZone',
+    containerScroll: false,
+
+    constructor: function(config) {
+        var me = this;
+
+        Ext.apply(me, config);
+
+        
+        
+        
+        
+        
+        if (!me.ddGroup) {
+            me.ddGroup = 'view-dd-zone-' + me.view.id;
         }
+
+        
+        
+        
+        
+        
+        
+        
+        me.callParent([me.view.el.dom.parentNode]);
+
+        me.ddel = Ext.get(document.createElement('div'));
+        me.ddel.addCls(Ext.baseCSSPrefix + 'grid-dd-wrap');
     },
 
-       
-    isSelectable : function(rowIndex, colIndex, cm){
-        return !cm.isHidden(colIndex);
+    init: function(id, sGroup, config) {
+        this.initTarget(id, sGroup, config);
+        this.view.mon(this.view, {
+            itemmousedown: this.onItemMouseDown,
+            scope: this
+        });
     },
-    
-    
-    onEditorKey: function(field, e){
-        if(e.getKey() == e.TAB){
-            this.handleKeyDown(e);
+
+    onItemMouseDown: function(view, record, item, index, e) {
+        if (!this.isPreventDrag(e, record, item, index)) {
+            this.handleMouseDown(e);
+
+            
+            
+            if (view.getSelectionModel().selectionMode == 'MULTI' && !e.ctrlKey && view.getSelectionModel().isSelected(record)) {
+                return false;
+            }
         }
     },
 
     
-    handleKeyDown : function(e){
-        if(!e.isNavKeyPress()){
-            return;
-        }
-        
-        var k = e.getKey(),
-            g = this.grid,
-            s = this.selection,
-            sm = this,
-            walk = function(row, col, step){
-                return g.walkCells(
-                    row,
-                    col,
-                    step,
-                    g.isEditor && g.editing ? sm.acceptsNav : sm.isSelectable, 
-                    sm
-                );
-            },
-            cell, newCell, r, c, ae;
-
-        switch(k){
-            case e.ESC:
-            case e.PAGE_UP:
-            case e.PAGE_DOWN:
-                
-                break;
-            default:
-                
-                e.stopEvent();
-                break;
-        }
+    isPreventDrag: function(e) {
+        return false;
+    },
 
-        if(!s){
-            cell = walk(0, 0, 1); 
-            if(cell){
-                this.select(cell[0], cell[1]);
-            }
-            return;
-        }
+    getDragData: function(e) {
+        var view = this.view,
+            item = e.getTarget(view.getItemSelector()),
+            record, selectionModel, records;
 
-        cell = s.cell;  
-        r = cell[0];    
-        c = cell[1];    
-        
-        switch(k){
-            case e.TAB:
-                if(e.shiftKey){
-                    newCell = walk(r, c - 1, -1);
-                }else{
-                    newCell = walk(r, c + 1, 1);
-                }
-                break;
-            case e.DOWN:
-                newCell = walk(r + 1, c, 1);
-                break;
-            case e.UP:
-                newCell = walk(r - 1, c, -1);
-                break;
-            case e.RIGHT:
-                newCell = walk(r, c + 1, 1);
-                break;
-            case e.LEFT:
-                newCell = walk(r, c - 1, -1);
-                break;
-            case e.ENTER:
-                if (g.isEditor && !g.editing) {
-                    g.startEditing(r, c);
-                    return;
-                }
-                break;
+        if (item) {
+            record = view.getRecord(item);
+            selectionModel = view.getSelectionModel();
+            records = selectionModel.getSelection();
+            return {
+                copy: this.view.copy || (this.view.allowCopy && e.ctrlKey),
+                event: new Ext.EventObjectImpl(e),
+                view: view,
+                ddel: this.ddel,
+                item: item,
+                records: records,
+                fromPosition: Ext.fly(item).getXY()
+            };
         }
+    },
 
-        if(newCell){
-            
-            r = newCell[0];
-            c = newCell[1];
-
-            this.select(r, c); 
+    onInitDrag: function(x, y) {
+        var me = this,
+            data = me.dragData,
+            view = data.view,
+            selectionModel = view.getSelectionModel(),
+            record = view.getRecord(data.item),
+            e = data.event;
 
-            if(g.isEditor && g.editing){ 
-                ae = g.activeEditor;
-                if(ae && ae.field.triggerBlur){
-                    
-                    ae.field.triggerBlur();
-                }
-                g.startEditing(r, c);
-            }
+        
+        
+        if (!selectionModel.isSelected(record) || e.hasModifier()) {
+            selectionModel.selectWithEvent(record, e, true);
         }
+        data.records = selectionModel.getSelection();
+
+        me.ddel.update(me.getDragText());
+        me.proxy.update(me.ddel.dom);
+        me.onStartDrag(x, y);
+        return true;
     },
 
-    acceptsNav : function(row, col, cm){
-        return !cm.isHidden(col) && cm.isCellEditable(col, row);
+    getDragText: function() {
+        var count = this.dragData.records.length;
+        return Ext.String.format(this.dragText, count, count == 1 ? '' : 's');
+    },
+
+    getRepairXY : function(e, data){
+        return data ? data.fromPosition : false;
     }
 });
-Ext.grid.EditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
-    
-    clicksToEdit: 2,
+Ext.define('Ext.tree.ViewDragZone', {
+    extend: 'Ext.view.DragZone',
 
+    isPreventDrag: function(e, record) {
+        return (record.get('allowDrag') === false) || !!e.getTarget(this.view.expanderSelector);
+    },
     
-    forceValidation: false,
+    afterRepair: function() {
+        var me = this,
+            view = me.view,
+            selectedRowCls = view.selectedItemCls,
+            records = me.dragData.records,
+            fly = Ext.fly;
+        
+        if (Ext.enableFx && me.repairHighlight) {
+            
+            Ext.Array.forEach(records, function(record) {
+                
+                
+                var item = view.getNode(record);
+                
+                
+                
+                fly(item.firstChild).highlight(me.repairHighlightColor, {
+                    listeners: {
+                        beforeanimate: function() {
+                            if (view.isSelected(item)) {
+                                fly(item).removeCls(selectedRowCls);
+                            }
+                        },
+                        afteranimate: function() {
+                            if (view.isSelected(item)) {
+                                fly(item).addCls(selectedRowCls);
+                            }
+                        }
+                    }
+                });
+            });
+        }
+        me.dragging = false;
+    }
+});
+
+Ext.define('Ext.tree.ViewDropZone', {
+    extend: 'Ext.view.DropZone',
 
     
-    isEditor : true,
+    allowParentInserts: false,
     
-    detectEdit: false,
+    allowContainerDrops: false,
 
     
-    autoEncode : false,
+    appendOnly: false,
 
     
+    expandDelay : 500,
+
+    indicatorCls: 'x-tree-ddindicator',
+
     
-    trackMouseOver: false, 
+    expandNode : function(node) {
+        var view = this.view;
+        if (!node.isLeaf() && !node.isExpanded()) {
+            view.expand(node);
+            this.expandProcId = false;
+        }
+    },
 
     
-    initComponent : function(){
-        Ext.grid.EditorGridPanel.superclass.initComponent.call(this);
+    queueExpand : function(node) {
+        this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]);
+    },
 
-        if(!this.selModel){
-            
-            this.selModel = new Ext.grid.CellSelectionModel();
+    
+    cancelExpand : function() {
+        if (this.expandProcId) {
+            clearTimeout(this.expandProcId);
+            this.expandProcId = false;
         }
+    },
 
-        this.activeEditor = null;
+    getPosition: function(e, node) {
+        var view = this.view,
+            record = view.getRecord(node),
+            y = e.getPageY(),
+            noAppend = record.isLeaf(),
+            noBelow = false,
+            region = Ext.fly(node).getRegion(),
+            fragment;
 
-        this.addEvents(
-            
-            "beforeedit",
-            
-            "afteredit",
-            
-            "validateedit"
-        );
-    },
+        
+        if (record.isRoot()) {
+            return 'append';
+        }
 
-    
-    initEvents : function(){
-        Ext.grid.EditorGridPanel.superclass.initEvents.call(this);
+        
+        if (this.appendOnly) {
+            return noAppend ? false : 'append';
+        }
 
-        this.getGridEl().on('mousewheel', this.stopEditing.createDelegate(this, [true]), this);
-        this.on('columnresize', this.stopEditing, this, [true]);
+        if (!this.allowParentInsert) {
+            noBelow = record.hasChildNodes() && record.isExpanded();
+        }
 
-        if(this.clicksToEdit == 1){
-            this.on("cellclick", this.onCellDblClick, this);
-        }else {
-            var view = this.getView();
-            if(this.clicksToEdit == 'auto' && view.mainBody){
-                view.mainBody.on('mousedown', this.onAutoEditClick, this);
-            }
-            this.on('celldblclick', this.onCellDblClick, this);
+        fragment = (region.bottom - region.top) / (noAppend ? 2 : 3);
+        if (y >= region.top && y < (region.top + fragment)) {
+            return 'before';
+        }
+        else if (!noBelow && (noAppend || (y >= (region.bottom - fragment) && y <= region.bottom))) {
+            return 'after';
+        }
+        else {
+            return 'append';
         }
     },
 
-    onResize : function(){
-        Ext.grid.EditorGridPanel.superclass.onResize.apply(this, arguments);
-        var ae = this.activeEditor;
-        if(this.editing && ae){
-            ae.realign(true);
+    isValidDropPoint : function(node, position, dragZone, e, data) {
+        if (!node || !data.item) {
+            return false;
         }
-    },
 
-    
-    onCellDblClick : function(g, row, col){
-        this.startEditing(row, col);
-    },
+        var view = this.view,
+            targetNode = view.getRecord(node),
+            draggedRecords = data.records,
+            dataLength = draggedRecords.length,
+            ln = draggedRecords.length,
+            i, record;
 
-    
-    onAutoEditClick : function(e, t){
-        if(e.button !== 0){
-            return;
+        
+        if (!(targetNode && position && dataLength)) {
+            return false;
         }
-        var row = this.view.findRowIndex(t),
-            col = this.view.findCellIndex(t);
-        if(row !== false && col !== false){
-            this.stopEditing();
-            if(this.selModel.getSelectedCell){ 
-                var sc = this.selModel.getSelectedCell();
-                if(sc && sc[0] === row && sc[1] === col){
-                    this.startEditing(row, col);
-                }
-            }else{
-                if(this.selModel.isSelected(row)){
-                    this.startEditing(row, col);
-                }
+
+        
+        for (i = 0; i < ln; i++) {
+            record = draggedRecords[i];
+            if (record.isNode && record.contains(targetNode)) {
+                return false;
             }
         }
+        
+        
+        if (position === 'append' && targetNode.get('allowDrop') === false) {
+            return false;
+        }
+        else if (position != 'append' && targetNode.parentNode.get('allowDrop') === false) {
+            return false;
+        }
+
+        
+        if (Ext.Array.contains(draggedRecords, targetNode)) {
+             return false;
+        }
+
+        
+        
+        return true;
     },
 
-    
-    onEditComplete : function(ed, value, startValue){
-        this.editing = false;
-        this.lastActiveEditor = this.activeEditor;
-        this.activeEditor = null;
-
-        var r = ed.record,
-            field = this.colModel.getDataIndex(ed.col);
-        value = this.postEditValue(value, startValue, r, field);
-        if(this.forceValidation === true || String(value) !== String(startValue)){
-            var e = {
-                grid: this,
-                record: r,
-                field: field,
-                originalValue: startValue,
-                value: value,
-                row: ed.row,
-                column: ed.col,
-                cancel:false
-            };
-            if(this.fireEvent("validateedit", e) !== false && !e.cancel && String(value) !== String(startValue)){
-                r.set(field, e.value);
-                delete e.cancel;
-                this.fireEvent("afteredit", e);
-            }
-        }
-        this.view.focusCell(ed.row, ed.col);
-    },
-
-    
-    startEditing : function(row, col){
-        this.stopEditing();
-        if(this.colModel.isCellEditable(col, row)){
-            this.view.ensureVisible(row, col, true);
-            var r = this.store.getAt(row),
-                field = this.colModel.getDataIndex(col),
-                e = {
-                    grid: this,
-                    record: r,
-                    field: field,
-                    value: r.data[field],
-                    row: row,
-                    column: col,
-                    cancel:false
-                };
-            if(this.fireEvent("beforeedit", e) !== false && !e.cancel){
-                this.editing = true;
-                var ed = this.colModel.getCellEditor(col, row);
-                if(!ed){
-                    return;
-                }
-                if(!ed.rendered){
-                    ed.parentEl = this.view.getEditorParent(ed);
-                    ed.on({
-                        scope: this,
-                        render: {
-                            fn: function(c){
-                                c.field.focus(false, true);
-                            },
-                            single: true,
-                            scope: this
-                        },
-                        specialkey: function(field, e){
-                            this.getSelectionModel().onEditorKey(field, e);
-                        },
-                        complete: this.onEditComplete,
-                        canceledit: this.stopEditing.createDelegate(this, [true])
-                    });
-                }
-                Ext.apply(ed, {
-                    row     : row,
-                    col     : col,
-                    record  : r
-                });
-                this.lastEdit = {
-                    row: row,
-                    col: col
-                };
-                this.activeEditor = ed;
-                
-                
-                ed.selectSameEditor = (this.activeEditor == this.lastActiveEditor);
-                var v = this.preEditValue(r, field);
-                ed.startEdit(this.view.getCell(row, col).firstChild, Ext.isDefined(v) ? v : '');
+    onNodeOver : function(node, dragZone, e, data) {
+        var position = this.getPosition(e, node),
+            returnCls = this.dropNotAllowed,
+            view = this.view,
+            targetNode = view.getRecord(node),
+            indicator = this.getIndicator(),
+            indicatorX = 0,
+            indicatorY = 0;
+
+        
+        this.cancelExpand();
+        if (position == 'append' && !this.expandProcId && !Ext.Array.contains(data.records, targetNode) && !targetNode.isLeaf() && !targetNode.isExpanded()) {
+            this.queueExpand(targetNode);
+        }
+            
+            
+        if (this.isValidDropPoint(node, position, dragZone, e, data)) {
+            this.valid = true;
+            this.currentPosition = position;
+            this.overRecord = targetNode;
+
+            indicator.setWidth(Ext.fly(node).getWidth());
+            indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1;
 
+            
+            if (position == 'before') {
+                returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
+                indicator.showAt(0, indicatorY);
+                dragZone.proxy.show();
+            } else if (position == 'after') {
+                returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
+                indicatorY += Ext.fly(node).getHeight();
+                indicator.showAt(0, indicatorY);
+                dragZone.proxy.show();
+            } else {
+                returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append';
                 
-                (function(){
-                    delete ed.selectSameEditor;
-                }).defer(50);
+                indicator.hide();
             }
+        } else {
+            this.valid = false;
         }
-    },
 
-    
-    preEditValue : function(r, field){
-        var value = r.data[field];
-        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlDecode(value) : value;
+        this.currentCls = returnCls;
+        return returnCls;
     },
 
+    onContainerOver : function(dd, e, data) {
+        return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed;
+    },
     
-    postEditValue : function(value, originalValue, r, field){
-        return this.autoEncode && Ext.isString(value) ? Ext.util.Format.htmlEncode(value) : value;
+    notifyOut: function() {
+        this.callParent(arguments);
+        this.cancelExpand();
     },
 
-    
-    stopEditing : function(cancel){
-        if(this.editing){
-            
-            var ae = this.lastActiveEditor = this.activeEditor;
-            if(ae){
-                ae[cancel === true ? 'cancelEdit' : 'completeEdit']();
-                this.view.focusCell(ae.row, ae.col);
+    handleNodeDrop : function(data, targetNode, position) {
+        var me = this,
+            view = me.view,
+            parentNode = targetNode.parentNode,
+            store = view.getStore(),
+            recordDomNodes = [],
+            records, i, len,
+            insertionMethod, argList,
+            needTargetExpand,
+            transferData,
+            processDrop;
+
+        
+        if (data.copy) {
+            records = data.records;
+            data.records = [];
+            for (i = 0, len = records.length; i < len; i++) {
+                data.records.push(Ext.apply({}, records[i].data));
             }
-            this.activeEditor = null;
         }
-        this.editing = false;
-    }
-});
-Ext.reg('editorgrid', Ext.grid.EditorGridPanel);
-
-Ext.grid.GridEditor = function(field, config){
-    Ext.grid.GridEditor.superclass.constructor.call(this, field, config);
-    field.monitorTab = false;
-};
-
-Ext.extend(Ext.grid.GridEditor, Ext.Editor, {
-    alignment: "tl-tl",
-    autoSize: "width",
-    hideEl : false,
-    cls: "x-small-editor x-grid-editor",
-    shim:false,
-    shadow:false
-});
-Ext.grid.PropertyRecord = Ext.data.Record.create([
-    {name:'name',type:'string'}, 'value'
-]);
 
+        
+        me.cancelExpand();
 
-Ext.grid.PropertyStore = Ext.extend(Ext.util.Observable, {
-    
-    constructor : function(grid, source){
-        this.grid = grid;
-        this.store = new Ext.data.Store({
-            recordType : Ext.grid.PropertyRecord
-        });
-        this.store.on('update', this.onUpdate,  this);
-        if(source){
-            this.setSource(source);
+        
+        
+        
+        
+        if (position == 'before') {
+            insertionMethod = parentNode.insertBefore;
+            argList = [null, targetNode];
+            targetNode = parentNode;
         }
-        Ext.grid.PropertyStore.superclass.constructor.call(this);    
-    },
-    
-    
-    setSource : function(o){
-        this.source = o;
-        this.store.removeAll();
-        var data = [];
-        for(var k in o){
-            if(this.isEditableValue(o[k])){
-                data.push(new Ext.grid.PropertyRecord({name: k, value: o[k]}, k));
+        else if (position == 'after') {
+            if (targetNode.nextSibling) {
+                insertionMethod = parentNode.insertBefore;
+                argList = [null, targetNode.nextSibling];
+            }
+            else {
+                insertionMethod = parentNode.appendChild;
+                argList = [null];
             }
+            targetNode = parentNode;
         }
-        this.store.loadRecords({records: data}, {}, true);
-    },
-
-    
-    onUpdate : function(ds, record, type){
-        if(type == Ext.data.Record.EDIT){
-            var v = record.data.value;
-            var oldValue = record.modified.value;
-            if(this.grid.fireEvent('beforepropertychange', this.source, record.id, v, oldValue) !== false){
-                this.source[record.id] = v;
-                record.commit();
-                this.grid.fireEvent('propertychange', this.source, record.id, v, oldValue);
-            }else{
-                record.reject();
+        else {
+            if (!targetNode.isExpanded()) {
+                needTargetExpand = true;
             }
+            insertionMethod = targetNode.appendChild;
+            argList = [null];
         }
-    },
-
-    
-    getProperty : function(row){
-       return this.store.getAt(row);
-    },
 
-    
-    isEditableValue: function(val){
-        return Ext.isPrimitive(val) || Ext.isDate(val);
-    },
-
-    
-    setValue : function(prop, value, create){
-        var r = this.getRec(prop);
-        if(r){
-            r.set('value', value);
-            this.source[prop] = value;
-        }else if(create){
+        
+        transferData = function() {
+            var node;
+            for (i = 0, len = data.records.length; i < len; i++) {
+                argList[0] = data.records[i];
+                node = insertionMethod.apply(targetNode, argList);
+                
+                if (Ext.enableFx && me.dropHighlight) {
+                    recordDomNodes.push(view.getNode(node));
+                }
+            }
+            
             
-            this.source[prop] = value;
-            r = new Ext.grid.PropertyRecord({name: prop, value: value}, prop);
-            this.store.add(r);
+            
+            if (Ext.enableFx && me.dropHighlight) {
+                
+                
+                Ext.Array.forEach(recordDomNodes, function(n) {
+                    if (n) {
+                        Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor);
+                    }
+                });
+            }
+        };
 
+        
+        if (needTargetExpand) {
+            targetNode.expand(false, transferData);
         }
-    },
-    
-    
-    remove : function(prop){
-        var r = this.getRec(prop);
-        if(r){
-            this.store.remove(r);
-            delete this.source[prop];
+        
+        else {
+            transferData();
         }
-    },
-    
-    
-    getRec : function(prop){
-        return this.store.getById(prop);
-    },
-
-    
-    getSource : function(){
-        return this.source;
     }
 });
 
+Ext.define('Ext.tree.plugin.TreeViewDragDrop', {
+    extend: 'Ext.AbstractPlugin',
+    alias: 'plugin.treeviewdragdrop',
 
-Ext.grid.PropertyColumnModel = Ext.extend(Ext.grid.ColumnModel, {
-    
-    nameText : 'Name',
-    valueText : 'Value',
-    dateFormat : 'm/j/Y',
-    trueText: 'true',
-    falseText: 'false',
-    
-    constructor : function(grid, store){
-        var g = Ext.grid,
-               f = Ext.form;
-               
-           this.grid = grid;
-           g.PropertyColumnModel.superclass.constructor.call(this, [
-               {header: this.nameText, width:50, sortable: true, dataIndex:'name', id: 'name', menuDisabled:true},
-               {header: this.valueText, width:50, resizable:false, dataIndex: 'value', id: 'value', menuDisabled:true}
-           ]);
-           this.store = store;
-       
-           var bfield = new f.Field({
-               autoCreate: {tag: 'select', children: [
-                   {tag: 'option', value: 'true', html: this.trueText},
-                   {tag: 'option', value: 'false', html: this.falseText}
-               ]},
-               getValue : function(){
-                   return this.el.dom.value == 'true';
-               }
-           });
-           this.editors = {
-               'date' : new g.GridEditor(new f.DateField({selectOnFocus:true})),
-               'string' : new g.GridEditor(new f.TextField({selectOnFocus:true})),
-               'number' : new g.GridEditor(new f.NumberField({selectOnFocus:true, style:'text-align:left;'})),
-               'boolean' : new g.GridEditor(bfield, {
-                   autoSize: 'both'
-               })
-           };
-           this.renderCellDelegate = this.renderCell.createDelegate(this);
-           this.renderPropDelegate = this.renderProp.createDelegate(this);
-    },
-
-    
-    renderDate : function(dateVal){
-        return dateVal.dateFormat(this.dateFormat);
-    },
-
-    
-    renderBool : function(bVal){
-        return this[bVal ? 'trueText' : 'falseText'];
-    },
+    uses: [
+        'Ext.tree.ViewDragZone',
+        'Ext.tree.ViewDropZone'
+    ],
 
     
-    isCellEditable : function(colIndex, rowIndex){
-        return colIndex == 1;
-    },
 
     
-    getRenderer : function(col){
-        return col == 1 ?
-            this.renderCellDelegate : this.renderPropDelegate;
-    },
 
-    
-    renderProp : function(v){
-        return this.getPropertyName(v);
-    },
+    dragText : '{0} selected node{1}',
 
     
-    renderCell : function(val, meta, rec){
-        var renderer = this.grid.customRenderers[rec.get('name')];
-        if(renderer){
-            return renderer.apply(this, arguments);
-        }
-        var rv = val;
-        if(Ext.isDate(val)){
-            rv = this.renderDate(val);
-        }else if(typeof val == 'boolean'){
-            rv = this.renderBool(val);
-        }
-        return Ext.util.Format.htmlEncode(rv);
-    },
+    allowParentInserts: false,
 
     
-    getPropertyName : function(name){
-        var pn = this.grid.propertyNames;
-        return pn && pn[name] ? pn[name] : name;
-    },
+    allowContainerDrops: false,
 
     
-    getCellEditor : function(colIndex, rowIndex){
-        var p = this.store.getProperty(rowIndex),
-            n = p.data.name, 
-            val = p.data.value;
-        if(this.grid.customEditors[n]){
-            return this.grid.customEditors[n];
-        }
-        if(Ext.isDate(val)){
-            return this.editors.date;
-        }else if(typeof val == 'number'){
-            return this.editors.number;
-        }else if(typeof val == 'boolean'){
-            return this.editors['boolean'];
-        }else{
-            return this.editors.string;
-        }
-    },
+    appendOnly: false,
 
     
-    destroy : function(){
-        Ext.grid.PropertyColumnModel.superclass.destroy.call(this);
-        for(var ed in this.editors){
-            Ext.destroy(this.editors[ed]);
-        }
-    }
-});
+    ddGroup : "TreeDD",
 
+    
 
-Ext.grid.PropertyGrid = Ext.extend(Ext.grid.EditorGridPanel, {
     
+
     
+    expandDelay : 1000,
+
     
+    enableDrop: true,
+
     
+    enableDrag: true,
+
     
+    nodeHighlightColor: 'c3daf9',
 
     
-    enableColumnMove:false,
-    stripeRows:false,
-    trackMouseOver: false,
-    clicksToEdit:1,
-    enableHdMenu : false,
-    viewConfig : {
-        forceFit:true
-    },
+    nodeHighlightOnDrop: Ext.enableFx,
 
     
-    initComponent : function(){
-        this.customRenderers = this.customRenderers || {};
-        this.customEditors = this.customEditors || {};
-        this.lastEditRow = null;
-        var store = new Ext.grid.PropertyStore(this);
-        this.propStore = store;
-        var cm = new Ext.grid.PropertyColumnModel(this, store);
-        store.store.sort('name', 'ASC');
-        this.addEvents(
-            
-            'beforepropertychange',
-            
-            'propertychange'
-        );
-        this.cm = cm;
-        this.ds = store.store;
-        Ext.grid.PropertyGrid.superclass.initComponent.call(this);
+    nodeHighlightOnRepair: Ext.enableFx,
 
-               this.mon(this.selModel, 'beforecellselect', function(sm, rowIndex, colIndex){
-            if(colIndex === 0){
-                this.startEditing.defer(200, this, [rowIndex, 1]);
-                return false;
-            }
-        }, this);
+    init : function(view) {
+        view.on('render', this.onViewRender, this, {single: true});
     },
 
     
-    onRender : function(){
-        Ext.grid.PropertyGrid.superclass.onRender.apply(this, arguments);
-
-        this.getGridEl().addClass('x-props-grid');
+    destroy: function() {
+        Ext.destroy(this.dragZone, this.dropZone);
     },
 
-    
-    afterRender: function(){
-        Ext.grid.PropertyGrid.superclass.afterRender.apply(this, arguments);
-        if(this.source){
-            this.setSource(this.source);
+    onViewRender : function(view) {
+        var me = this;
+
+        if (me.enableDrag) {
+            me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
+                view: view,
+                ddGroup: me.dragGroup || me.ddGroup,
+                dragText: me.dragText,
+                repairHighlightColor: me.nodeHighlightColor,
+                repairHighlight: me.nodeHighlightOnRepair
+            });
         }
-    },
 
+        if (me.enableDrop) {
+            me.dropZone = Ext.create('Ext.tree.ViewDropZone', {
+                view: view,
+                ddGroup: me.dropGroup || me.ddGroup,
+                allowContainerDrops: me.allowContainerDrops,
+                appendOnly: me.appendOnly,
+                allowParentInserts: me.allowParentInserts,
+                expandDelay: me.expandDelay,
+                dropHighlightColor: me.nodeHighlightColor,
+                dropHighlight: me.nodeHighlightOnDrop
+            });
+        }
+    }
+});
+
+Ext.define('Ext.util.Cookies', {
+    singleton: true,
     
-    setSource : function(source){
-        this.propStore.setSource(source);
+    
+    set : function(name, value){
+        var argv = arguments,
+            argc = arguments.length,
+            expires = (argc > 2) ? argv[2] : null,
+            path = (argc > 3) ? argv[3] : '/',
+            domain = (argc > 4) ? argv[4] : null,
+            secure = (argc > 5) ? argv[5] : false;
+            
+        document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
     },
 
     
-    getSource : function(){
-        return this.propStore.getSource();
+    get : function(name){
+        var arg = name + "=",
+            alen = arg.length,
+            clen = document.cookie.length,
+            i = 0,
+            j = 0;
+            
+        while(i < clen){
+            j = i + alen;
+            if(document.cookie.substring(i, j) == arg){
+                return this.getCookieVal(j);
+            }
+            i = document.cookie.indexOf(" ", i) + 1;
+            if(i === 0){
+                break;
+            }
+        }
+        return null;
     },
+
     
-    
-    setProperty : function(prop, value, create){
-        this.propStore.setValue(prop, value, create);    
+    clear : function(name, path){
+        if(this.get(name)){
+            path = path || '/';
+            document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=' + path;
+        }
     },
     
     
-    removeProperty : function(prop){
-        this.propStore.remove(prop);
+    getCookieVal : function(offset){
+        var endstr = document.cookie.indexOf(";", offset);
+        if(endstr == -1){
+            endstr = document.cookie.length;
+        }
+        return unescape(document.cookie.substring(offset, endstr));
     }
-
-    
-    
-    
-    
 });
-Ext.reg("propertygrid", Ext.grid.PropertyGrid);
 
-Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
 
-    
-    groupByText : 'Group By This Field',
-    
-    showGroupsText : 'Show in Groups',
-    
-    hideGroupedColumn : false,
-    
-    showGroupName : true,
-    
-    startCollapsed : false,
-    
-    enableGrouping : true,
-    
-    enableGroupingMenu : true,
-    
-    enableNoGroups : true,
-    
-    emptyGroupText : '(None)',
-    
-    ignoreAdd : false,
-    
-    groupTextTpl : '{text}',
+Ext.define('Ext.util.CSS', function() {
+    var rules = null;
+    var doc = document;
 
-    
-    groupMode: 'value',
+    var camelRe = /(-[a-z])/gi;
+    var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
 
-    
+    return {
 
-    
-    initTemplates : function(){
-        Ext.grid.GroupingView.superclass.initTemplates.call(this);
-        this.state = {};
+        singleton: true,
 
-        var sm = this.grid.getSelectionModel();
-        sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
-                this.onBeforeRowSelect, this);
+        constructor: function() {
+            this.rules = {};
+            this.initialized = false;
+        },
 
-        if(!this.startGroup){
-            this.startGroup = new Ext.XTemplate(
-                '<div id="{groupId}" class="x-grid-group {cls}">',
-                    '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>',
-                    '<div id="{groupId}-bd" class="x-grid-group-body">'
-            );
-        }
-        this.startGroup.compile();
+        
+        createStyleSheet : function(cssText, id) {
+            var ss,
+                head = doc.getElementsByTagName("head")[0],
+                styleEl = doc.createElement("style");
 
-        if (!this.endGroup) {
-            this.endGroup = '</div></div>';
-        }
-    },
+            styleEl.setAttribute("type", "text/css");
+            if (id) {
+               styleEl.setAttribute("id", id);
+            }
 
-    
-    findGroup : function(el){
-        return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
-    },
+            if (Ext.isIE) {
+               head.appendChild(styleEl);
+               ss = styleEl.styleSheet;
+               ss.cssText = cssText;
+            } else {
+                try{
+                    styleEl.appendChild(doc.createTextNode(cssText));
+                } catch(e) {
+                   styleEl.cssText = cssText;
+                }
+                head.appendChild(styleEl);
+                ss = styleEl.styleSheet ? styleEl.styleSheet : (styleEl.sheet || doc.styleSheets[doc.styleSheets.length-1]);
+            }
+            this.cacheStyleSheet(ss);
+            return ss;
+        },
 
-    
-    getGroups : function(){
-        return this.hasRows() ? this.mainBody.dom.childNodes : [];
-    },
+        
+        removeStyleSheet : function(id) {
+            var existing = document.getElementById(id);
+            if (existing) {
+                existing.parentNode.removeChild(existing);
+            }
+        },
 
-    
-    onAdd : function(ds, records, index) {
-        if (this.canGroup() && !this.ignoreAdd) {
-            var ss = this.getScrollState();
-            this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1));
-            this.refresh();
-            this.restoreScroll(ss);
-            this.fireEvent('rowsinserted', ds, index, index + (records.length-1));
-        } else if (!this.canGroup()) {
-            Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
-        }
-    },
+        
+        swapStyleSheet : function(id, url) {
+            var doc = document;
+            this.removeStyleSheet(id);
+            var ss = doc.createElement("link");
+            ss.setAttribute("rel", "stylesheet");
+            ss.setAttribute("type", "text/css");
+            ss.setAttribute("id", id);
+            ss.setAttribute("href", url);
+            doc.getElementsByTagName("head")[0].appendChild(ss);
+        },
 
-    
-    onRemove : function(ds, record, index, isUpdate){
-        Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
-        var g = document.getElementById(record._groupId);
-        if(g && g.childNodes[1].childNodes.length < 1){
-            Ext.removeNode(g);
-        }
-        this.applyEmptyText();
-    },
+        
+        refreshCache : function() {
+            return this.getRules(true);
+        },
 
-    
-    refreshRow : function(record){
-        if(this.ds.getCount()==1){
-            this.refresh();
-        }else{
-            this.isUpdating = true;
-            Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
-            this.isUpdating = false;
-        }
-    },
+        
+        cacheStyleSheet : function(ss) {
+            if(!rules){
+                rules = {};
+            }
+            try {
+                var ssRules = ss.cssRules || ss.rules,
+                    selectorText,
+                    i = ssRules.length - 1,
+                    j,
+                    selectors;
 
-    
-    beforeMenuShow : function(){
-        var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false;
-        if((item = items.get('groupBy'))){
-            item.setDisabled(disabled);
-        }
-        if((item = items.get('showGroups'))){
-            item.setDisabled(disabled);
-            item.setChecked(this.canGroup(), true);
-        }
-    },
+                for (; i >= 0; --i) {
+                    selectorText = ssRules[i].selectorText;
+                    if (selectorText) {
 
-    
-    renderUI : function(){
-        Ext.grid.GroupingView.superclass.renderUI.call(this);
-        this.mainBody.on('mousedown', this.interceptMouse, this);
+                        
+                        selectorText = selectorText.split(',');
+                        selectors = selectorText.length;
+                        for (j = 0; j < selectors; j++) {
+                            rules[Ext.String.trim(selectorText[j]).toLowerCase()] = ssRules[i];
+                        }
+                    }
+                }
+            } catch(e) {}
+        },
 
-        if(this.enableGroupingMenu && this.hmenu){
-            this.hmenu.add('-',{
-                itemId:'groupBy',
-                text: this.groupByText,
-                handler: this.onGroupByClick,
-                scope: this,
-                iconCls:'x-group-by-icon'
-            });
-            if(this.enableNoGroups){
-                this.hmenu.add({
-                    itemId:'showGroups',
-                    text: this.showGroupsText,
-                    checked: true,
-                    checkHandler: this.onShowGroupsClick,
-                    scope: this
-                });
-            }
-            this.hmenu.on('beforeshow', this.beforeMenuShow, this);
-        }
-    },
+        
+        getRules : function(refreshCache) {
+            if (rules === null || refreshCache) {
+                rules = {};
+                var ds = doc.styleSheets,
+                    i = 0,
+                    len = ds.length;
 
-    processEvent: function(name, e){
-        Ext.grid.GroupingView.superclass.processEvent.call(this, name, e);
-        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
-        if(hd){
-            
-            var field = this.getGroupField(),
-                prefix = this.getPrefix(field),
-                groupValue = hd.id.substring(prefix.length),
-                emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd');
+                for (; i < len; i++) {
+                    try {
+                        if (!ds[i].disabled) {
+                            this.cacheStyleSheet(ds[i]);
+                        }
+                    } catch(e) {}
+                }
+            }
+            return rules;
+        },
 
-            
-            groupValue = groupValue.substr(0, groupValue.length - 3);
-            
-            
-            if(groupValue || emptyRe.test(hd.id)){
-                this.grid.fireEvent('group' + name, this.grid, field, groupValue, e);
+        
+        getRule: function(selector, refreshCache) {
+            var rs = this.getRules(refreshCache);
+            if (!Ext.isArray(selector)) {
+                return rs[selector.toLowerCase()];
             }
-            if(name == 'mousedown' && e.button == 0){
-                this.toggleGroup(hd.parentNode);
+            for (var i = 0; i < selector.length; i++) {
+                if (rs[selector[i]]) {
+                    return rs[selector[i].toLowerCase()];
+                }
+            }
+            return null;
+        },
+
+        
+        updateRule : function(selector, property, value){
+            if (!Ext.isArray(selector)) {
+                var rule = this.getRule(selector);
+                if (rule) {
+                    rule.style[property.replace(camelRe, camelFn)] = value;
+                    return true;
+                }
+            } else {
+                for (var i = 0; i < selector.length; i++) {
+                    if (this.updateRule(selector[i], property, value)) {
+                        return true;
+                    }
+                }
             }
+            return false;
         }
+    };
+}());
 
+Ext.define('Ext.util.History', {
+    singleton: true,
+    alternateClassName: 'Ext.History',
+    mixins: {
+        observable: 'Ext.util.Observable'
     },
 
-    
-    onGroupByClick : function(){
-        this.enableGrouping = true;
-        this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
-        this.grid.fireEvent('groupchange', this, this.grid.store.getGroupState());
-        this.beforeMenuShow(); 
-        this.refresh();
+    constructor: function() {
+        var me = this;
+        me.oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
+        me.iframe = null;
+        me.hiddenField = null;
+        me.ready = false;
+        me.currentToken = null;
     },
 
-    
-    onShowGroupsClick : function(mi, checked){
-        this.enableGrouping = checked;
-        if(checked){
-            this.onGroupByClick();
-        }else{
-            this.grid.store.clearGrouping();
-            this.grid.fireEvent('groupchange', this, null);
-        }
-    },
+    getHash: function() {
+        var href = window.location.href,
+            i = href.indexOf("#");
 
-    
-    toggleRowIndex : function(rowIndex, expanded){
-        if(!this.canGroup()){
-            return;
-        }
-        var row = this.getRow(rowIndex);
-        if(row){
-            this.toggleGroup(this.findGroup(row), expanded);
-        }
+        return i >= 0 ? href.substr(i + 1) : null;
     },
 
-    
-    toggleGroup : function(group, expanded){
-        var gel = Ext.get(group);
-        expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed');
-        if(this.state[gel.id] !== expanded){
-            this.grid.stopEditing(true);
-            this.state[gel.id] = expanded;
-            gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
-        }
+    doSave: function() {
+        this.hiddenField.value = this.currentToken;
     },
 
-    
-    toggleAllGroups : function(expanded){
-        var groups = this.getGroups();
-        for(var i = 0, len = groups.length; i < len; i++){
-            this.toggleGroup(groups[i], expanded);
-        }
-    },
 
-    
-    expandAllGroups : function(){
-        this.toggleAllGroups(true);
+    handleStateChange: function(token) {
+        this.currentToken = token;
+        this.fireEvent('change', token);
     },
 
-    
-    collapseAllGroups : function(){
-        this.toggleAllGroups(false);
+    updateIFrame: function(token) {
+        var html = '<html><body><div id="state">' +
+                    Ext.util.Format.htmlEncode(token) +
+                    '</div></body></html>';
+
+        try {
+            var doc = this.iframe.contentWindow.document;
+            doc.open();
+            doc.write(html);
+            doc.close();
+            return true;
+        } catch (e) {
+            return false;
+        }
     },
 
-    
-    interceptMouse : function(e){
-        var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
-        if(hd){
-            e.stopEvent();
-            this.toggleGroup(hd.parentNode);
+    checkIFrame: function () {
+        var me = this,
+            contentWindow = me.iframe.contentWindow;
+
+        if (!contentWindow || !contentWindow.document) {
+            Ext.Function.defer(this.checkIFrame, 10, this);
+            return;
         }
+
+        var doc = contentWindow.document,
+            elem = doc.getElementById("state"),
+            oldToken = elem ? elem.innerText : null,
+            oldHash = me.getHash();
+
+        Ext.TaskManager.start({
+            run: function () {
+                var doc = contentWindow.document,
+                    elem = doc.getElementById("state"),
+                    newToken = elem ? elem.innerText : null,
+                    newHash = me.getHash();
+
+                if (newToken !== oldToken) {
+                    oldToken = newToken;
+                    me.handleStateChange(newToken);
+                    window.top.location.hash = newToken;
+                    oldHash = newToken;
+                    me.doSave();
+                } else if (newHash !== oldHash) {
+                    oldHash = newHash;
+                    me.updateIFrame(newHash);
+                }
+            },
+            interval: 50,
+            scope: me
+        });
+        me.ready = true;
+        me.fireEvent('ready', me);
     },
 
-    
-    getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){
-        var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
-        if(g === '' || g === '&#160;'){
-            g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
+    startUp: function () {
+        var me = this;
+
+        me.currentToken = me.hiddenField.value || this.getHash();
+
+        if (me.oldIEMode) {
+            me.checkIFrame();
+        } else {
+            var hash = me.getHash();
+            Ext.TaskManager.start({
+                run: function () {
+                    var newHash = me.getHash();
+                    if (newHash !== hash) {
+                        hash = newHash;
+                        me.handleStateChange(hash);
+                        me.doSave();
+                    }
+                },
+                interval: 50,
+                scope: me
+            });
+            me.ready = true;
+            me.fireEvent('ready', me);
         }
-        return g;
+
     },
 
     
-    getGroupField : function(){
-        return this.grid.store.getGroupState();
-    },
+    fieldId: Ext.baseCSSPrefix + 'history-field',
+    
+    iframeId: Ext.baseCSSPrefix + 'history-frame',
 
     
-    afterRender : function(){
-        if(!this.ds || !this.cm){
+    init: function (onReady, scope) {
+        var me = this;
+
+        if (me.ready) {
+            Ext.callback(onReady, scope, [me]);
             return;
         }
-        Ext.grid.GroupingView.superclass.afterRender.call(this);
-        if(this.grid.deferRowRender){
-            this.updateGroupWidths();
-        }
-    },
 
-    
-    renderRows : function(){
-        var groupField = this.getGroupField();
-        var eg = !!groupField;
-        
-        if(this.hideGroupedColumn) {
-            var colIndex = this.cm.findColumnIndex(groupField),
-                hasLastGroupField = Ext.isDefined(this.lastGroupField);
-            if(!eg && hasLastGroupField){
-                this.mainBody.update('');
-                this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false);
-                delete this.lastGroupField;
-            }else if (eg && !hasLastGroupField){
-                this.lastGroupField = groupField;
-                this.cm.setHidden(colIndex, true);
-            }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) {
-                this.mainBody.update('');
-                var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
-                this.cm.setHidden(oldIndex, false);
-                this.lastGroupField = groupField;
-                this.cm.setHidden(colIndex, true);
-            }
+        if (!Ext.isReady) {
+            Ext.onReady(function() {
+                me.init(onReady, scope);
+            });
+            return;
         }
-        return Ext.grid.GroupingView.superclass.renderRows.apply(
-                    this, arguments);
-    },
 
-    
-    doRender : function(cs, rs, ds, startRow, colCount, stripe){
-        if(rs.length < 1){
-            return '';
+        me.hiddenField = Ext.getDom(me.fieldId);
+
+        if (me.oldIEMode) {
+            me.iframe = Ext.getDom(me.iframeId);
         }
 
-        if(!this.canGroup() || this.isUpdating){
-            return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments);
+        me.addEvents(
+            
+            'ready',
+            
+            'change'
+        );
+
+        if (onReady) {
+            me.on('ready', onReady, scope, {single: true});
         }
+        me.startUp();
+    },
 
-        var groupField = this.getGroupField(),
-            colIndex = this.cm.findColumnIndex(groupField),
-            g,
-            gstyle = 'width:' + this.getTotalWidth() + ';',
-            cfg = this.cm.config[colIndex],
-            groupRenderer = cfg.groupRenderer || cfg.renderer,
-            prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '',
-            groups = [],
-            curGroup, i, len, gid;
-
-        for(i = 0, len = rs.length; i < len; i++){
-            var rowIndex = startRow + i,
-                r = rs[i],
-                gvalue = r.data[groupField];
-
-                g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds);
-            if(!curGroup || curGroup.group != g){
-                gid = this.constructId(gvalue, groupField, colIndex);
-                
-                
-                this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed);
-                curGroup = {
-                    group: g,
-                    gvalue: gvalue,
-                    text: prefix + g,
-                    groupId: gid,
-                    startRow: rowIndex,
-                    rs: [r],
-                    cls: this.state[gid] ? '' : 'x-grid-group-collapsed',
-                    style: gstyle
-                };
-                groups.push(curGroup);
-            }else{
-                curGroup.rs.push(r);
+    
+    add: function (token, preventDup) {
+        var me = this;
+
+        if (preventDup !== false) {
+            if (me.getToken() === token) {
+                return true;
             }
-            r._groupId = gid;
         }
 
-        var buf = [];
-        for(i = 0, len = groups.length; i < len; i++){
-            g = groups[i];
-            this.doGroupStart(buf, g, cs, ds, colCount);
-            buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
-                    this, cs, g.rs, ds, g.startRow, colCount, stripe);
-
-            this.doGroupEnd(buf, g, cs, ds, colCount);
+        if (me.oldIEMode) {
+            return me.updateIFrame(token);
+        } else {
+            window.top.location.hash = token;
+            return true;
         }
-        return buf.join('');
     },
 
     
-    getGroupId : function(value){
-        var field = this.getGroupField();
-        return this.constructId(value, field, this.cm.findColumnIndex(field));
+    back: function() {
+        window.history.go(-1);
     },
 
     
-    constructId : function(value, field, idx){
-        var cfg = this.cm.config[idx],
-            groupRenderer = cfg.groupRenderer || cfg.renderer,
-            val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds);
-
-        return this.getPrefix(field) + Ext.util.Format.htmlEncode(val);
+    forward: function(){
+        window.history.go(1);
     },
 
     
-    canGroup  : function(){
-        return this.enableGrouping && !!this.getGroupField();
+    getToken: function() {
+        return this.ready ? this.currentToken : this.getHash();
+    }
+});
+
+Ext.define('Ext.view.TableChunker', {
+    singleton: true,
+    requires: ['Ext.XTemplate'],
+    metaTableTpl: [
+        '{[this.openTableWrap()]}',
+        '<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" border="0" cellspacing="0" cellpadding="0" {[this.embedFullWidth()]}>',
+            '<tbody>',
+            '<tr class="' + Ext.baseCSSPrefix + 'grid-header-row">',
+            '<tpl for="columns">',
+                '<th class="' + Ext.baseCSSPrefix + 'grid-col-resizer-{id}" style="width: {width}px; height: 0px;"></th>',
+            '</tpl>',
+            '</tr>',
+            '{[this.openRows()]}',
+                '{row}',
+                '<tpl for="features">',
+                    '{[this.embedFeature(values, parent, xindex, xcount)]}',
+                '</tpl>',
+            '{[this.closeRows()]}',
+            '</tbody>',
+        '</table>',
+        '{[this.closeTableWrap()]}'
+    ],
+
+    constructor: function() {
+        Ext.XTemplate.prototype.recurse = function(values, reference) {
+            return this.apply(reference ? values[reference] : values);
+        };
     },
 
-    
-    getPrefix: function(field){
-        return this.grid.getGridEl().id + '-gp-' + field + '-';
+    embedFeature: function(values, parent, x, xcount) {
+        var tpl = '';
+        if (!values.disabled) {
+            tpl = values.getFeatureTpl(values, parent, x, xcount);
+        }
+        return tpl;
     },
 
-    
-    doGroupStart : function(buf, g, cs, ds, colCount){
-        buf[buf.length] = this.startGroup.apply(g);
+    embedFullWidth: function() {
+        return 'style="width: {fullWidth}px;"';
     },
 
-    
-    doGroupEnd : function(buf, g, cs, ds, colCount){
-        buf[buf.length] = this.endGroup;
+    openRows: function() {
+        return '<tpl for="rows">';
     },
 
-    
-    getRows : function(){
-        if(!this.canGroup()){
-            return Ext.grid.GroupingView.superclass.getRows.call(this);
-        }
-        var r = [],
-            gs = this.getGroups(),
-            g,
-            i = 0,
-            len = gs.length,
-            j,
-            jlen;
-        for(; i < len; ++i){
-            g = gs[i].childNodes[1];
-            if(g){
-                g = g.childNodes;
-                for(j = 0, jlen = g.length; j < jlen; ++j){
-                    r[r.length] = g[j];
-                }
-            }
-        }
-        return r;
+    closeRows: function() {
+        return '</tpl>';
     },
 
+    metaRowTpl: [
+        '<tr class="' + Ext.baseCSSPrefix + 'grid-row {addlSelector} {[this.embedRowCls()]}" {[this.embedRowAttr()]}>',
+            '<tpl for="columns">',
+                '<td class="{cls} ' + Ext.baseCSSPrefix + 'grid-cell ' + Ext.baseCSSPrefix + 'grid-cell-{columnId} {{id}-modified} {{id}-tdCls} {[this.firstOrLastCls(xindex, xcount)]}" {{id}-tdAttr}><div unselectable="on" class="' + Ext.baseCSSPrefix + 'grid-cell-inner ' + Ext.baseCSSPrefix + 'unselectable" style="{{id}-style}; text-align: {align};">{{id}}</div></td>',
+            '</tpl>',
+        '</tr>'
+    ],
     
-    updateGroupWidths : function(){
-        if(!this.canGroup() || !this.hasRows()){
-            return;
-        }
-        var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px';
-        var gs = this.getGroups();
-        for(var i = 0, len = gs.length; i < len; i++){
-            gs[i].firstChild.style.width = tw;
+    firstOrLastCls: function(xindex, xcount) {
+        var cssCls = '';
+        if (xindex === 1) {
+            cssCls = Ext.baseCSSPrefix + 'grid-cell-first';
+        } else if (xindex === xcount) {
+            cssCls = Ext.baseCSSPrefix + 'grid-cell-last';
         }
+        return cssCls;
     },
-
     
-    onColumnWidthUpdated : function(col, w, tw){
-        Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw);
-        this.updateGroupWidths();
+    embedRowCls: function() {
+        return '{rowCls}';
     },
-
     
-    onAllColumnWidthsUpdated : function(ws, tw){
-        Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw);
-        this.updateGroupWidths();
+    embedRowAttr: function() {
+        return '{rowAttr}';
     },
-
     
-    onColumnHiddenUpdated : function(col, hidden, tw){
-        Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw);
-        this.updateGroupWidths();
+    openTableWrap: function() {
+        return '';
     },
-
     
-    onLayout : function(){
-        this.updateGroupWidths();
+    closeTableWrap: function() {
+        return '';
     },
 
-    
-    onBeforeRowSelect : function(sm, rowIndex){
-        this.toggleRowIndex(rowIndex, true);
+    getTableTpl: function(cfg, textOnly) {
+        var tpl,
+            tableTplMemberFns = {
+                openRows: this.openRows,
+                closeRows: this.closeRows,
+                embedFeature: this.embedFeature,
+                embedFullWidth: this.embedFullWidth,
+                openTableWrap: this.openTableWrap,
+                closeTableWrap: this.closeTableWrap
+            },
+            tplMemberFns = {},
+            features = cfg.features || [],
+            ln = features.length,
+            i  = 0,
+            memberFns = {
+                embedRowCls: this.embedRowCls,
+                embedRowAttr: this.embedRowAttr,
+                firstOrLastCls: this.firstOrLastCls
+            },
+            
+            metaRowTpl = Array.prototype.slice.call(this.metaRowTpl, 0),
+            metaTableTpl;
+            
+        for (; i < ln; i++) {
+            if (!features[i].disabled) {
+                features[i].mutateMetaRowTpl(metaRowTpl);
+                Ext.apply(memberFns, features[i].getMetaRowTplFragments());
+                Ext.apply(tplMemberFns, features[i].getFragmentTpl());
+                Ext.apply(tableTplMemberFns, features[i].getTableFragments());
+            }
+        }
+        
+        metaRowTpl = Ext.create('Ext.XTemplate', metaRowTpl.join(''), memberFns);
+        cfg.row = metaRowTpl.applyTemplate(cfg);
+        
+        metaTableTpl = Ext.create('Ext.XTemplate', this.metaTableTpl.join(''), tableTplMemberFns);
+        
+        tpl = metaTableTpl.applyTemplate(cfg);
+        
+        
+        if (!textOnly) {
+            tpl = Ext.create('Ext.XTemplate', tpl, tplMemberFns);
+        }
+        return tpl;
+        
     }
 });
 
-Ext.grid.GroupingView.GROUP_ID = 1000;
+
+
+