3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 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.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.resizer.ResizeTracker
17 * @extends Ext.dd.DragTracker
18 * Private utility class for Ext.resizer.Resizer.
21 Ext.define('Ext.resizer.ResizeTracker', {
22 extend: 'Ext.dd.DragTracker',
26 // Default to no constraint
29 proxyCls: Ext.baseCSSPrefix + 'resizable-proxy',
31 constructor: function(config) {
35 if (config.target.isComponent) {
36 me.el = config.target.getEl();
38 me.el = config.target;
41 this.callParent(arguments);
43 // Ensure that if we are preserving aspect ratio, the largest minimum is honoured
44 if (me.preserveRatio && me.minWidth && me.minHeight) {
45 var widthRatio = me.minWidth / me.el.getWidth(),
46 heightRatio = me.minHeight / me.el.getHeight();
48 // largest ratio of minimum:size must be preserved.
49 // So if a 400x200 pixel image has
50 // minWidth: 50, maxWidth: 50, the maxWidth will be 400 * (50/200)... that is 100
51 if (heightRatio > widthRatio) {
52 me.minWidth = me.el.getWidth() * heightRatio;
54 me.minHeight = me.el.getHeight() * widthRatio;
58 // If configured as throttled, create an instance version of resize which calls
59 // a throttled function to perform the resize operation.
61 var throttledResizeFn = Ext.Function.createThrottled(function() {
62 Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
65 me.resize = function(box, direction, atEnd) {
67 Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
69 throttledResizeFn.apply(null, arguments);
75 onBeforeStart: function(e) {
76 // record the startBox
77 this.startBox = this.el.getBox();
82 * Returns the object that will be resized on every mousemove event.
83 * If dynamic is false, this will be a proxy, otherwise it will be our actual target.
85 getDynamicTarget: function() {
91 } else if (!me.proxy) {
92 me.proxy = me.createProxy(target);
99 * Create a proxy for this resizer
100 * @param {Ext.Component/Ext.Element} target The target
101 * @return {Ext.Element} A proxy element
103 createProxy: function(target){
108 if (target.isComponent) {
109 proxy = target.getProxy().addCls(cls);
111 renderTo = Ext.getBody();
112 if (Ext.scopeResetCSS) {
113 renderTo = Ext.getBody().createChild({
114 cls: Ext.baseCSSPrefix + 'reset'
117 proxy = target.createProxy({
120 id: target.id + '-rzproxy'
123 proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
127 onStart: function(e) {
128 // returns the Ext.ResizeHandle that the user started dragging
129 this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
131 // If we are using a proxy, ensure it is sized.
133 this.resize(this.startBox, {
140 onDrag: function(e) {
141 // dynamic resizing, update dimensions during resize
142 if (this.dynamic || this.proxy) {
143 this.updateDimensions(e);
147 updateDimensions: function(e, atEnd) {
149 region = me.activeResizeHandle.region,
150 offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
160 horizDir = offset[0] < 0 ? 'right' : 'left',
161 vertDir = offset[1] < 0 ? 'down' : 'up',
163 axis; // 1 = x, 2 = y, 3 = x and y.
167 heightAdjust = offset[1];
171 heightAdjust = -offset[1];
172 adjustY = -heightAdjust;
176 widthAdjust = offset[0];
180 widthAdjust = -offset[0];
181 adjustX = -widthAdjust;
185 heightAdjust = -offset[1];
186 adjustY = -heightAdjust;
187 widthAdjust = offset[0];
188 oppositeCorner = [box.x, box.y + box.height];
192 heightAdjust = offset[1];
193 widthAdjust = offset[0];
194 oppositeCorner = [box.x, box.y];
198 widthAdjust = -offset[0];
199 adjustX = -widthAdjust;
200 heightAdjust = offset[1];
201 oppositeCorner = [box.x + box.width, box.y];
205 heightAdjust = -offset[1];
206 adjustY = -heightAdjust;
207 widthAdjust = -offset[0];
208 adjustX = -widthAdjust;
209 oppositeCorner = [box.x + box.width, box.y + box.height];
215 width: box.width + widthAdjust,
216 height: box.height + heightAdjust,
221 // Snap value between stops according to configured increments
222 snappedWidth = Ext.Number.snap(newBox.width, me.widthIncrement);
223 snappedHeight = Ext.Number.snap(newBox.height, me.heightIncrement);
224 if (snappedWidth != newBox.width || snappedHeight != newBox.height){
227 newBox.y -= snappedHeight - newBox.height;
230 newBox.y -= snappedHeight - newBox.height;
233 newBox.x -= snappedWidth - newBox.width;
236 newBox.x -= snappedWidth - newBox.width;
239 newBox.x -= snappedWidth - newBox.width;
240 newBox.y -= snappedHeight - newBox.height;
242 newBox.width = snappedWidth;
243 newBox.height = snappedHeight;
247 if (newBox.width < me.minWidth || newBox.width > me.maxWidth) {
248 newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
250 // Re-adjust the X position if we were dragging the west side
252 newBox.x = box.x + (box.width - newBox.width);
257 if (newBox.height < me.minHeight || newBox.height > me.maxHeight) {
258 newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
260 // Re-adjust the Y position if we were dragging the north side
262 newBox.y = box.y + (box.height - newBox.height);
268 // If this is configured to preserve the aspect ratio, or they are dragging using the shift key
269 if (me.preserveRatio || e.shiftKey) {
273 ratio = me.startBox.width / me.startBox.height;
275 // Calculate aspect ratio constrained values.
276 newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
277 newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
279 // X axis: width-only change, height must obey
281 newBox.height = newHeight;
284 // Y axis: height-only change, width must obey
285 else if (axis == 2) {
286 newBox.width = newWidth;
291 // Drag ratio is the ratio of the mouse point from the opposite corner.
292 // Basically what edge we are dragging, a horizontal edge or a vertical edge.
293 dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
295 // If drag ratio > aspect ratio then width is dominant and height must obey
296 if (dragRatio > ratio) {
297 newBox.height = newHeight;
299 newBox.width = newWidth;
302 // Handle dragging start coordinates
303 if (region == 'northeast') {
304 newBox.y = box.y - (newBox.height - box.height);
305 } else if (region == 'northwest') {
306 newBox.y = box.y - (newBox.height - box.height);
307 newBox.x = box.x - (newBox.width - box.width);
308 } else if (region == 'southwest') {
309 newBox.x = box.x - (newBox.width - box.width);
314 if (heightAdjust === 0) {
317 if (widthAdjust === 0) {
321 horizontal: horizDir,
326 getResizeTarget: function(atEnd) {
327 return atEnd ? this.target : this.getDynamicTarget();
330 resize: function(box, direction, atEnd) {
331 var target = this.getResizeTarget(atEnd);
332 if (target.isComponent) {
333 if (target.floating) {
334 target.setPagePosition(box.x, box.y);
336 target.setSize(box.width, box.height);
339 // update the originalTarget if this was wrapped.
340 if (this.originalTarget) {
341 this.originalTarget.setBox(box);
347 this.updateDimensions(e, true);