    /**
     * @class Ext.dd.PanelProxy
     * A custom drag proxy implementation specific to {@link Ext.Panel}s. This class is primarily used internally
     * for the Panel's drag drop implementation, and should never need to be created directly.
     * @constructor
     * @param panel The {@link Ext.Panel} to proxy for
     * @param config Configuration options
     */
    Ext.dd.PanelProxy  = Ext.extend(Object, {

        constructor : function(panel, config){
            this.panel = panel;
            this.id = this.panel.id +'-ddproxy';
            Ext.apply(this, config);
        },

        /**
         * @cfg {Boolean} insertProxy True to insert a placeholder proxy element while dragging the panel,
         * false to drag with no proxy (defaults to true).
         */
        insertProxy : true,

        // private overrides
        setStatus : Ext.emptyFn,
        reset : Ext.emptyFn,
        update : Ext.emptyFn,
        stop : Ext.emptyFn,
        sync: Ext.emptyFn,

        /**
         * Gets the proxy's element
         * @return {Element} The proxy's element
         */
        getEl : function(){
            return this.ghost;
        },

        /**
         * Gets the proxy's ghost element
         * @return {Element} The proxy's ghost element
         */
        getGhost : function(){
            return this.ghost;
        },

        /**
         * Gets the proxy's element
         * @return {Element} The proxy's element
         */
        getProxy : function(){
            return this.proxy;
        },

        /**
         * Hides the proxy
         */
        hide : function(){
            if(this.ghost){
                if(this.proxy){
                    this.proxy.remove();
                    delete this.proxy;
                }
                this.panel.el.dom.style.display = '';
                this.ghost.remove();
                delete this.ghost;
            }
        },

        /**
         * Shows the proxy
         */
        show : function(){
            if(!this.ghost){
                this.ghost = this.panel.createGhost(this.panel.initialConfig.cls, 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';
            }
        },

        // private
        repair : function(xy, callback, scope){
            this.hide();
            if(typeof callback == "function"){
                callback.call(scope || this);
            }
        },

        /**
         * Moves the proxy to a different position in the DOM.  This is typically called while dragging the Panel
         * to keep the proxy sync'd to the Panel's location.
         * @param {HTMLElement} parentNode The proxy's parent DOM node
         * @param {HTMLElement} before (optional) The sibling node before which the proxy should be inserted (defaults
         * to the parent's last child if not specified)
         */
        moveProxy : function(parentNode, before){
            if(this.proxy){
                parentNode.insertBefore(this.proxy.dom, before);
            }
        }
    });

    // private - DD implementation for Panels
    Ext.Panel.DD = Ext.extend(Ext.dd.DragSource, {

        constructor : 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,
                el = panel.body;
            if(h){
                this.setHandleElId(h.id);
                el = panel.header;
            }
            el.setStyle('cursor', 'move');
            this.scroll = false;
        },

        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.dom;
        },
        endDrag : function(e){
            this.proxy.hide();
            this.panel.saveState();
        },

        autoOffset : function(x, y) {
            x -= this.startPageX;
            y -= this.startPageY;
            this.setDelta(x, y);
        }
    });