Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / portal / classes / PortalDropZone.js
diff --git a/examples/portal/classes/PortalDropZone.js b/examples/portal/classes/PortalDropZone.js
new file mode 100644 (file)
index 0000000..c0a1da4
--- /dev/null
@@ -0,0 +1,190 @@
+/**
+ * @class Ext.app.PortalDropZone
+ * @extends Ext.dd.DropTarget
+ * Internal class that manages drag/drop for {@link Ext.app.PortalPanel}.
+ */
+Ext.define('Ext.app.PortalDropZone', {
+    extend: 'Ext.dd.DropTarget',
+
+    constructor: function(portal, cfg) {
+        this.portal = portal;
+        Ext.dd.ScrollManager.register(portal.body);
+        Ext.app.PortalDropZone.superclass.constructor.call(this, portal.body, cfg);
+        portal.body.ddScrollConfig = this.ddScrollConfig;
+    },
+
+    ddScrollConfig: {
+        vthresh: 50,
+        hthresh: -1,
+        animate: true,
+        increment: 200
+    },
+
+    createEvent: function(dd, e, data, col, c, pos) {
+        return {
+            portal: this.portal,
+            panel: data.panel,
+            columnIndex: col,
+            column: c,
+            position: pos,
+            data: data,
+            source: dd,
+            rawEvent: e,
+            status: this.dropAllowed
+        };
+    },
+
+    notifyOver: function(dd, e, data) {
+        var xy = e.getXY(),
+            portal = this.portal,
+            proxy = dd.proxy;
+
+        // case column widths
+        if (!this.grid) {
+            this.grid = this.getGrid();
+        }
+
+        // handle case scroll where scrollbars appear during drag
+        var cw = portal.body.dom.clientWidth;
+        if (!this.lastCW) {
+            // set initial client width
+            this.lastCW = cw;
+        } else if (this.lastCW != cw) {
+            // client width has changed, so refresh layout & grid calcs
+            this.lastCW = cw;
+            //portal.doLayout();
+            this.grid = this.getGrid();
+        }
+
+        // determine column
+        var colIndex = 0,
+            colRight = 0,
+            cols = this.grid.columnX,
+            len = cols.length,
+            cmatch = false;
+
+        for (len; colIndex < len; colIndex++) {
+            colRight = cols[colIndex].x + cols[colIndex].w;
+            if (xy[0] < colRight) {
+                cmatch = true;
+                break;
+            }
+        }
+        // no match, fix last index
+        if (!cmatch) {
+            colIndex--;
+        }
+
+        // find insert position
+        var overPortlet, pos = 0,
+            h = 0,
+            match = false,
+            overColumn = portal.items.getAt(colIndex),
+            portlets = overColumn.items.items,
+            overSelf = false;
+
+        len = portlets.length;
+
+        for (len; pos < len; pos++) {
+            overPortlet = portlets[pos];
+            h = overPortlet.el.getHeight();
+            if (h === 0) {
+                overSelf = true;
+            } else if ((overPortlet.el.getY() + (h / 2)) > xy[1]) {
+                match = true;
+                break;
+            }
+        }
+
+        pos = (match && overPortlet ? pos : overColumn.items.getCount()) + (overSelf ? -1 : 0);
+        var overEvent = this.createEvent(dd, e, data, colIndex, overColumn, pos);
+
+        if (portal.fireEvent('validatedrop', overEvent) !== false && portal.fireEvent('beforedragover', overEvent) !== false) {
+
+            // make sure proxy width is fluid in different width columns
+            proxy.getProxy().setWidth('auto');
+
+            if (overPortlet) {
+                proxy.moveProxy(overPortlet.el.dom.parentNode, match ? overPortlet.el.dom : null);
+            } else {
+                proxy.moveProxy(overColumn.el.dom, null);
+            }
+
+            this.lastPos = {
+                c: overColumn,
+                col: colIndex,
+                p: overSelf || (match && overPortlet) ? pos : false
+            };
+            this.scrollPos = portal.body.getScroll();
+
+            portal.fireEvent('dragover', overEvent);
+            return overEvent.status;
+        } else {
+            return overEvent.status;
+        }
+
+    },
+
+    notifyOut: function() {
+        delete this.grid;
+    },
+
+    notifyDrop: function(dd, e, data) {
+        delete this.grid;
+        if (!this.lastPos) {
+            return;
+        }
+        var c = this.lastPos.c,
+            col = this.lastPos.col,
+            pos = this.lastPos.p,
+            panel = dd.panel,
+            dropEvent = this.createEvent(dd, e, data, col, c, pos !== false ? pos : c.items.getCount());
+
+        if (this.portal.fireEvent('validatedrop', dropEvent) !== false && this.portal.fireEvent('beforedrop', dropEvent) !== false) {
+
+            // make sure panel is visible prior to inserting so that the layout doesn't ignore it
+            panel.el.dom.style.display = '';
+
+            if (pos !== false) {
+                c.insert(pos, panel);
+            } else {
+                c.add(panel);
+            }
+
+            dd.proxy.hide();
+            this.portal.fireEvent('drop', dropEvent);
+
+            // scroll position is lost on drop, fix it
+            var st = this.scrollPos.top;
+            if (st) {
+                var d = this.portal.body.dom;
+                setTimeout(function() {
+                    d.scrollTop = st;
+                },
+                10);
+            }
+
+        }
+        delete this.lastPos;
+        return true;
+    },
+
+    // internal cache of body and column coords
+    getGrid: function() {
+        var box = this.portal.body.getBox();
+        box.columnX = [];
+        this.portal.items.each(function(c) {
+            box.columnX.push({
+                x: c.el.getX(),
+                w: c.el.getWidth()
+            });
+        });
+        return box;
+    },
+
+    // unregister the dropzone from ScrollManager
+    unreg: function() {
+        Ext.dd.ScrollManager.unregister(this.portal.body);
+        Ext.app.PortalDropZone.superclass.unreg.call(this);
+    }
+});