Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / src / widgets / list / ColumnResizer.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 /**
8  * @class Ext.list.ColumnResizer
9  * @extends Ext.util.Observable
10  * <p>Supporting Class for Ext.list.ListView</p>
11  * @constructor
12  * @param {Object} config
13  */
14 Ext.list.ColumnResizer = Ext.extend(Ext.util.Observable, {
15     /**
16      * @cfg {Number} minPct The minimum percentage to allot for any column (defaults to <tt>.05</tt>)
17      */
18     minPct: .05,
19
20     constructor: function(config){
21         Ext.apply(this, config);
22         Ext.list.ColumnResizer.superclass.constructor.call(this);
23     },
24     init : function(listView){
25         this.view = listView;
26         listView.on('render', this.initEvents, this);
27     },
28
29     initEvents : function(view){
30         view.mon(view.innerHd, 'mousemove', this.handleHdMove, this);
31         this.tracker = new Ext.dd.DragTracker({
32             onBeforeStart: this.onBeforeStart.createDelegate(this),
33             onStart: this.onStart.createDelegate(this),
34             onDrag: this.onDrag.createDelegate(this),
35             onEnd: this.onEnd.createDelegate(this),
36             tolerance: 3,
37             autoStart: 300
38         });
39         this.tracker.initEl(view.innerHd);
40         view.on('beforedestroy', this.tracker.destroy, this.tracker);
41     },
42
43     handleHdMove : function(e, t){
44         var handleWidth = 5,
45             x = e.getPageX(),
46             header = e.getTarget('em', 3, true);
47         if(header){
48             var region = header.getRegion(),
49                 style = header.dom.style,
50                 parentNode = header.dom.parentNode;
51
52             if(x - region.left <= handleWidth && parentNode != parentNode.parentNode.firstChild){
53                 this.activeHd = Ext.get(parentNode.previousSibling.firstChild);
54                 style.cursor = Ext.isWebKit ? 'e-resize' : 'col-resize';
55             } else if(region.right - x <= handleWidth && parentNode != parentNode.parentNode.lastChild.previousSibling){
56                 this.activeHd = header;
57                 style.cursor = Ext.isWebKit ? 'w-resize' : 'col-resize';
58             } else{
59                 delete this.activeHd;
60                 style.cursor = '';
61             }
62         }
63     },
64
65     onBeforeStart : function(e){
66         this.dragHd = this.activeHd;
67         return !!this.dragHd;
68     },
69
70     onStart: function(e){
71         
72         var me = this,
73             view = me.view,
74             dragHeader = me.dragHd,
75             x = me.tracker.getXY()[0];            
76         
77         me.proxy = view.el.createChild({cls:'x-list-resizer'});
78         me.dragX = dragHeader.getX();
79         me.headerIndex = view.findHeaderIndex(dragHeader);
80         
81         me.headersDisabled = view.disableHeaders;
82         view.disableHeaders = true;
83         
84         me.proxy.setHeight(view.el.getHeight());
85         me.proxy.setX(me.dragX);
86         me.proxy.setWidth(x - me.dragX);
87         
88         this.setBoundaries();
89         
90     },
91     
92     // Sets up the boundaries for the drag/drop operation
93     setBoundaries: function(relativeX){
94         var view = this.view,
95             headerIndex = this.headerIndex,
96             width = view.innerHd.getWidth(),
97             relativeX = view.innerHd.getX(),
98             minWidth = Math.ceil(width * this.minPct),
99             maxWidth = width - minWidth,
100             numColumns = view.columns.length,
101             headers = view.innerHd.select('em', true),
102             minX = minWidth + relativeX,
103             maxX = maxWidth + relativeX,
104             header;
105           
106         if (numColumns == 2) {
107             this.minX = minX;
108             this.maxX = maxX;
109         }else{
110             header = headers.item(headerIndex + 2);
111             this.minX = headers.item(headerIndex).getX() + minWidth;
112             this.maxX = header ? header.getX() - minWidth : maxX;
113             if (headerIndex == 0) {
114                 // First
115                 this.minX = minX;
116             } else if (headerIndex == numColumns - 2) {
117                 // Last
118                 this.maxX = maxX;
119             }
120         }
121     },
122
123     onDrag: function(e){
124         var me = this,
125             cursorX = me.tracker.getXY()[0].constrain(me.minX, me.maxX);
126             
127         me.proxy.setWidth(cursorX - this.dragX);
128     },
129
130     onEnd: function(e){
131         /* calculate desired width by measuring proxy and then remove it */
132         var newWidth = this.proxy.getWidth(),
133             index = this.headerIndex,
134             view = this.view,
135             columns = view.columns,
136             width = view.innerHd.getWidth(),
137             newPercent = Math.ceil(newWidth * view.maxColumnWidth / width) / 100,
138             disabled = this.headersDisabled,
139             headerCol = columns[index],
140             otherCol = columns[index + 1],
141             totalPercent = headerCol.width + otherCol.width;
142
143         this.proxy.remove();
144
145         headerCol.width = newPercent;
146         otherCol.width = totalPercent - newPercent;
147       
148         delete this.dragHd;
149         view.setHdWidths();
150         view.refresh();
151         
152         setTimeout(function(){
153             view.disableHeaders = disabled;
154         }, 100);
155     }
156 });
157
158 // Backwards compatibility alias
159 Ext.ListView.ColumnResizer = Ext.list.ColumnResizer;