Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / ResizeTracker.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-resizer.ResizeTracker'>/**
2 </span> * @class Ext.resizer.ResizeTracker
3  * @extends Ext.dd.DragTracker
4  */
5 Ext.define('Ext.resizer.ResizeTracker', {
6     extend: 'Ext.dd.DragTracker',
7     dynamic: true,
8     preserveRatio: false,
9
10     // Default to no constraint
11     constrainTo: null,
12
13     constructor: function(config) {
14         var me = this;
15
16         if (!config.el) {
17             if (config.target.isComponent) {
18                 me.el = config.target.getEl();
19             } else {
20                 me.el = config.target;
21             }
22         }
23         this.callParent(arguments);
24
25         // Ensure that if we are preserving aspect ratio, the largest minimum is honoured
26         if (me.preserveRatio &amp;&amp; me.minWidth &amp;&amp; me.minHeight) {
27             var widthRatio = me.minWidth / me.el.getWidth(),
28                 heightRatio = me.minHeight / me.el.getHeight();
29
30             // largest ratio of minimum:size must be preserved.
31             // So if a 400x200 pixel image has
32             // minWidth: 50, maxWidth: 50, the maxWidth will be 400 * (50/200)... that is 100
33             if (heightRatio &gt; widthRatio) {
34                 me.minWidth = me.el.getWidth() * heightRatio;
35             } else {
36                 me.minHeight = me.el.getHeight() * widthRatio;
37             }
38         }
39
40         // If configured as throttled, create an instance version of resize which calls
41         // a throttled function to perform the resize operation.
42         if (me.throttle) {
43             var throttledResizeFn = Ext.Function.createThrottled(function() {
44                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
45                 }, me.throttle);
46
47             me.resize = function(box, direction, atEnd) {
48                 if (atEnd) {
49                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
50                 } else {
51                     throttledResizeFn.apply(null, arguments);
52                 }
53             };
54         }
55     },
56
57     onBeforeStart: function(e) {
58         // record the startBox
59         this.startBox = this.el.getBox();
60     },
61
62 <span id='Ext-resizer.ResizeTracker-method-getDynamicTarget'>    /**
63 </span>     * @private
64      * Returns the object that will be resized on every mousemove event.
65      * If dynamic is false, this will be a proxy, otherwise it will be our actual target.
66      */
67     getDynamicTarget: function() {
68         var d = this.target;
69         if (this.dynamic) {
70             return d;
71         } else if (!this.proxy) {
72             this.proxy = d.isComponent ? d.getProxy().addCls(Ext.baseCSSPrefix + 'resizable-proxy') : d.createProxy({tag: 'div', cls: Ext.baseCSSPrefix + 'resizable-proxy', id: d.id + '-rzproxy'}, Ext.getBody());
73             this.proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
74         }
75         this.proxy.show();
76         return this.proxy;
77     },
78
79     onStart: function(e) {
80         // returns the Ext.ResizeHandle that the user started dragging
81         this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
82
83         // If we are using a proxy, ensure it is sized.
84         if (!this.dynamic) {
85             this.resize(this.startBox, {
86                 horizontal: 'none',
87                 vertical: 'none'
88             });
89         }
90     },
91
92     onDrag: function(e) {
93         // dynamic resizing, update dimensions during resize
94         if (this.dynamic || this.proxy) {
95             this.updateDimensions(e);
96         }
97     },
98
99     updateDimensions: function(e, atEnd) {
100         var me = this,
101             region = me.activeResizeHandle.region,
102             offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
103             box = me.startBox,
104             ratio,
105             widthAdjust = 0,
106             heightAdjust = 0,
107             adjustX = 0,
108             adjustY = 0,
109             dragRatio,
110             horizDir = offset[0] &lt; 0 ? 'right' : 'left',
111             vertDir = offset[1] &lt; 0 ? 'down' : 'up',
112             oppositeCorner,
113             axis; // 1 = x, 2 = y, 3 = x and y.
114
115         switch (region) {
116             case 'south':
117                 heightAdjust = offset[1];
118                 axis = 2;
119                 break;
120             case 'north':
121                 heightAdjust = -offset[1];
122                 adjustY = -heightAdjust;
123                 axis = 2;
124                 break;
125             case 'east':
126                 widthAdjust = offset[0];
127                 axis = 1;
128                 break;
129             case 'west':
130                 widthAdjust = -offset[0];
131                 adjustX = -widthAdjust;
132                 axis = 1;
133                 break;
134             case 'northeast':
135                 heightAdjust = -offset[1];
136                 adjustY = -heightAdjust;
137                 widthAdjust = offset[0];
138                 oppositeCorner = [box.x, box.y + box.height];
139                 axis = 3;
140                 break;
141             case 'southeast':
142                 heightAdjust = offset[1];
143                 widthAdjust = offset[0];
144                 oppositeCorner = [box.x, box.y];
145                 axis = 3;
146                 break;
147             case 'southwest':
148                 widthAdjust = -offset[0];
149                 adjustX = -widthAdjust;
150                 heightAdjust = offset[1];
151                 oppositeCorner = [box.x + box.width, box.y];
152                 axis = 3;
153                 break;
154             case 'northwest':
155                 heightAdjust = -offset[1];
156                 adjustY = -heightAdjust;
157                 widthAdjust = -offset[0];
158                 adjustX = -widthAdjust;
159                 oppositeCorner = [box.x + box.width, box.y + box.height];
160                 axis = 3;
161                 break;
162         }
163
164         var newBox = {
165             width: box.width + widthAdjust,
166             height: box.height + heightAdjust,
167             x: box.x + adjustX,
168             y: box.y + adjustY
169         };
170
171         // out of bounds
172         if (newBox.width &lt; me.minWidth || newBox.width &gt; me.maxWidth) {
173             newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
174             newBox.x = me.lastX || newBox.x;
175         } else {
176             me.lastX = newBox.x;
177         }
178         if (newBox.height &lt; me.minHeight || newBox.height &gt; me.maxHeight) {
179             newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
180             newBox.y = me.lastY || newBox.y;
181         } else {
182             me.lastY = newBox.y;
183         }
184
185         // If this is configured to preserve the aspect ratio, or they are dragging using the shift key
186         if (me.preserveRatio || e.shiftKey) {
187             var newHeight,
188                 newWidth;
189
190             ratio = me.startBox.width / me.startBox.height;
191
192             // Calculate aspect ratio constrained values.
193             newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
194             newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
195
196             // X axis: width-only change, height must obey
197             if (axis == 1) {
198                 newBox.height = newHeight;
199             }
200
201             // Y axis: height-only change, width must obey
202             else if (axis == 2) {
203                 newBox.width = newWidth;
204             }
205
206             // Corner drag.
207             else {
208                 // Drag ratio is the ratio of the mouse point from the opposite corner.
209                 // Basically what edge we are dragging, a horizontal edge or a vertical edge.
210                 dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
211
212                 // If drag ratio &gt; aspect ratio then width is dominant and height must obey
213                 if (dragRatio &gt; ratio) {
214                     newBox.height = newHeight;
215                 } else {
216                     newBox.width = newWidth;
217                 }
218
219                 // Handle dragging start coordinates
220                 if (region == 'northeast') {
221                     newBox.y = box.y - (newBox.height - box.height);
222                 } else if (region == 'northwest') {
223                     newBox.y = box.y - (newBox.height - box.height);
224                     newBox.x = box.x - (newBox.width - box.width);
225                 } else if (region == 'southwest') {
226                     newBox.x = box.x - (newBox.width - box.width);
227                 }
228             }
229         }
230
231         if (heightAdjust === 0) {
232             vertDir = 'none';
233         }
234         if (widthAdjust === 0) {
235             horizDir = 'none';
236         }
237         me.resize(newBox, {
238             horizontal: horizDir,
239             vertical: vertDir
240         }, atEnd);
241     },
242
243     getResizeTarget: function(atEnd) {
244         return atEnd ? this.target : this.getDynamicTarget();
245     },
246
247     resize: function(box, direction, atEnd) {
248         var target = this.getResizeTarget(atEnd);
249         if (target.isComponent) {
250             if (target.floating) {
251                 target.setPagePosition(box.x, box.y);
252             }
253             target.setSize(box.width, box.height);
254         } else {
255             target.setBox(box);
256             // update the originalTarget if this was wrapped.
257             if (this.originalTarget) {
258                 this.originalTarget.setBox(box);
259             }
260         }
261     },
262
263     onEnd: function(e) {
264         this.updateDimensions(e, true);
265         if (this.proxy) {
266             this.proxy.hide();
267         }
268     }
269 });
270 </pre></pre></body></html>