Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / util / ComponentDragger.js
diff --git a/src/util/ComponentDragger.js b/src/util/ComponentDragger.js
new file mode 100644 (file)
index 0000000..33b0d32
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * @class Ext.util.ComponentDragger
+ * @extends Ext.dd.DragTracker
+ * <p>A subclass of Ext.dd.DragTracker which handles dragging any Component.</p>
+ * <p>This is configured with a Component to be made draggable, and a config object for the
+ * {@link Ext.dd.DragTracker} class.</p>
+ * <p>A {@link #} delegate may be provided which may be either the element to use as the mousedown target
+ * or a {@link Ext.DomQuery} selector to activate multiple mousedown targets.</p>
+ * @constructor Create a new ComponentTracker
+ * @param {object} comp The Component to provide dragging for.
+ * @param {object} config The config object
+ */
+Ext.define('Ext.util.ComponentDragger', {
+
+    /**
+     * @cfg {Boolean} constrain
+     * Specify as <code>true</code> to constrain the Component to within the bounds of the {@link #constrainTo} region.
+     */
+
+    /**
+     * @cfg {String/Element} delegate
+     * Optional. <p>A {@link Ext.DomQuery DomQuery} selector which identifies child elements within the Component's encapsulating
+     * Element which are the drag handles. This limits dragging to only begin when the matching elements are mousedowned.</p>
+     * <p>This may also be a specific child element within the Component's encapsulating element to use as the drag handle.</p>
+     */
+
+    /**
+     * @cfg {Boolean} constrainDelegate
+     * Specify as <code>true</code> to constrain the drag handles within the {@link constrainTo} region.
+     */
+
+    extend: 'Ext.dd.DragTracker',
+
+    autoStart: 500,
+
+    constructor: function(comp, config) {
+        this.comp = comp;
+        this.initialConstrainTo = config.constrainTo;
+        this.callParent([ config ]);
+    },
+
+    onStart: function(e) {
+        var me = this,
+            comp = me.comp;
+
+        // Cache the start [X, Y] array
+        this.startPosition = comp.getPosition();
+
+        // If client Component has a ghost method to show a lightweight version of itself
+        // then use that as a drag proxy unless configured to liveDrag.
+        if (comp.ghost && !comp.liveDrag) {
+             me.proxy = comp.ghost();
+             me.dragTarget = me.proxy.header.el;
+        }
+
+        // Set the constrainTo Region before we start dragging.
+        if (me.constrain || me.constrainDelegate) {
+            me.constrainTo = me.calculateConstrainRegion();
+        }
+    },
+
+    calculateConstrainRegion: function() {
+        var me = this,
+            comp = me.comp,
+            c = me.initialConstrainTo,
+            delegateRegion,
+            elRegion,
+            shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
+
+        // The configured constrainTo might be a Region or an element
+        if (!(c instanceof Ext.util.Region)) {
+            c =  Ext.fly(c).getViewRegion();
+        }
+
+        // Reduce the constrain region to allow for shadow
+        if (shadowSize) {
+            c.adjust(0, -shadowSize, -shadowSize, shadowSize);
+        }
+
+        // If they only want to constrain the *delegate* to within the constrain region,
+        // adjust the region to be larger based on the insets of the delegate from the outer
+        // edges of the Component.
+        if (!me.constrainDelegate) {
+            delegateRegion = Ext.fly(me.dragTarget).getRegion();
+            elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
+
+            c.adjust(
+                delegateRegion.top - elRegion.top,
+                delegateRegion.right - elRegion.right,
+                delegateRegion.bottom - elRegion.bottom,
+                delegateRegion.left - elRegion.left
+            );
+        }
+        return c;
+    },
+
+    // Move either the ghost Component or the target Component to its new position on drag
+    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);
+
+        comp.setPosition.apply(comp, [me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]]);
+    },
+
+    onEnd: function(e) {
+        if (this.proxy && !this.comp.liveDrag) {
+            this.comp.unghost();
+        }
+    }
+});
\ No newline at end of file