initial import
[roojs1] / Roo / BoxComponent.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11
12 /**
13  * @class Roo.BoxComponent
14  * @extends Roo.Component
15  * Base class for any visual {@link Roo.Component} that uses a box container.  BoxComponent provides automatic box
16  * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model.  All
17  * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
18  * layout containers.
19  * @constructor
20  * @param {Roo.Element/String/Object} config The configuration options.
21  */
22 Roo.BoxComponent = function(config){
23     Roo.Component.call(this, config);
24     this.addEvents({
25         /**
26          * @event resize
27          * Fires after the component is resized.
28              * @param {Roo.Component} this
29              * @param {Number} adjWidth The box-adjusted width that was set
30              * @param {Number} adjHeight The box-adjusted height that was set
31              * @param {Number} rawWidth The width that was originally specified
32              * @param {Number} rawHeight The height that was originally specified
33              */
34         resize : true,
35         /**
36          * @event move
37          * Fires after the component is moved.
38              * @param {Roo.Component} this
39              * @param {Number} x The new x position
40              * @param {Number} y The new y position
41              */
42         move : true
43     });
44 };
45
46 Roo.extend(Roo.BoxComponent, Roo.Component, {
47     // private, set in afterRender to signify that the component has been rendered
48     boxReady : false,
49     // private, used to defer height settings to subclasses
50     deferHeight: false,
51     /** @cfg {Number} width
52      * width (optional) size of component
53      */
54      /** @cfg {Number} height
55      * height (optional) size of component
56      */
57      
58     /**
59      * Sets the width and height of the component.  This method fires the resize event.  This method can accept
60      * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
61      * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
62      * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
63      * @return {Roo.BoxComponent} this
64      */
65     setSize : function(w, h){
66         // support for standard size objects
67         if(typeof w == 'object'){
68             h = w.height;
69             w = w.width;
70         }
71         // not rendered
72         if(!this.boxReady){
73             this.width = w;
74             this.height = h;
75             return this;
76         }
77
78         // prevent recalcs when not needed
79         if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
80             return this;
81         }
82         this.lastSize = {width: w, height: h};
83
84         var adj = this.adjustSize(w, h);
85         var aw = adj.width, ah = adj.height;
86         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
87             var rz = this.getResizeEl();
88             if(!this.deferHeight && aw !== undefined && ah !== undefined){
89                 rz.setSize(aw, ah);
90             }else if(!this.deferHeight && ah !== undefined){
91                 rz.setHeight(ah);
92             }else if(aw !== undefined){
93                 rz.setWidth(aw);
94             }
95             this.onResize(aw, ah, w, h);
96             this.fireEvent('resize', this, aw, ah, w, h);
97         }
98         return this;
99     },
100
101     /**
102      * Gets the current size of the component's underlying element.
103      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
104      */
105     getSize : function(){
106         return this.el.getSize();
107     },
108
109     /**
110      * Gets the current XY position of the component's underlying element.
111      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
112      * @return {Array} The XY position of the element (e.g., [100, 200])
113      */
114     getPosition : function(local){
115         if(local === true){
116             return [this.el.getLeft(true), this.el.getTop(true)];
117         }
118         return this.xy || this.el.getXY();
119     },
120
121     /**
122      * Gets the current box measurements of the component's underlying element.
123      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
124      * @returns {Object} box An object in the format {x, y, width, height}
125      */
126     getBox : function(local){
127         var s = this.el.getSize();
128         if(local){
129             s.x = this.el.getLeft(true);
130             s.y = this.el.getTop(true);
131         }else{
132             var xy = this.xy || this.el.getXY();
133             s.x = xy[0];
134             s.y = xy[1];
135         }
136         return s;
137     },
138
139     /**
140      * Sets the current box measurements of the component's underlying element.
141      * @param {Object} box An object in the format {x, y, width, height}
142      * @returns {Roo.BoxComponent} this
143      */
144     updateBox : function(box){
145         this.setSize(box.width, box.height);
146         this.setPagePosition(box.x, box.y);
147         return this;
148     },
149
150     // protected
151     getResizeEl : function(){
152         return this.resizeEl || this.el;
153     },
154
155     // protected
156     getPositionEl : function(){
157         return this.positionEl || this.el;
158     },
159
160     /**
161      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
162      * This method fires the move event.
163      * @param {Number} left The new left
164      * @param {Number} top The new top
165      * @returns {Roo.BoxComponent} this
166      */
167     setPosition : function(x, y){
168         this.x = x;
169         this.y = y;
170         if(!this.boxReady){
171             return this;
172         }
173         var adj = this.adjustPosition(x, y);
174         var ax = adj.x, ay = adj.y;
175
176         var el = this.getPositionEl();
177         if(ax !== undefined || ay !== undefined){
178             if(ax !== undefined && ay !== undefined){
179                 el.setLeftTop(ax, ay);
180             }else if(ax !== undefined){
181                 el.setLeft(ax);
182             }else if(ay !== undefined){
183                 el.setTop(ay);
184             }
185             this.onPosition(ax, ay);
186             this.fireEvent('move', this, ax, ay);
187         }
188         return this;
189     },
190
191     /**
192      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
193      * This method fires the move event.
194      * @param {Number} x The new x position
195      * @param {Number} y The new y position
196      * @returns {Roo.BoxComponent} this
197      */
198     setPagePosition : function(x, y){
199         this.pageX = x;
200         this.pageY = y;
201         if(!this.boxReady){
202             return;
203         }
204         if(x === undefined || y === undefined){ // cannot translate undefined points
205             return;
206         }
207         var p = this.el.translatePoints(x, y);
208         this.setPosition(p.left, p.top);
209         return this;
210     },
211
212     // private
213     onRender : function(ct, position){
214         Roo.BoxComponent.superclass.onRender.call(this, ct, position);
215         if(this.resizeEl){
216             this.resizeEl = Roo.get(this.resizeEl);
217         }
218         if(this.positionEl){
219             this.positionEl = Roo.get(this.positionEl);
220         }
221     },
222
223     // private
224     afterRender : function(){
225         Roo.BoxComponent.superclass.afterRender.call(this);
226         this.boxReady = true;
227         this.setSize(this.width, this.height);
228         if(this.x || this.y){
229             this.setPosition(this.x, this.y);
230         }
231         if(this.pageX || this.pageY){
232             this.setPagePosition(this.pageX, this.pageY);
233         }
234     },
235
236     /**
237      * Force the component's size to recalculate based on the underlying element's current height and width.
238      * @returns {Roo.BoxComponent} this
239      */
240     syncSize : function(){
241         delete this.lastSize;
242         this.setSize(this.el.getWidth(), this.el.getHeight());
243         return this;
244     },
245
246     /**
247      * Called after the component is resized, this method is empty by default but can be implemented by any
248      * subclass that needs to perform custom logic after a resize occurs.
249      * @param {Number} adjWidth The box-adjusted width that was set
250      * @param {Number} adjHeight The box-adjusted height that was set
251      * @param {Number} rawWidth The width that was originally specified
252      * @param {Number} rawHeight The height that was originally specified
253      */
254     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
255
256     },
257
258     /**
259      * Called after the component is moved, this method is empty by default but can be implemented by any
260      * subclass that needs to perform custom logic after a move occurs.
261      * @param {Number} x The new x position
262      * @param {Number} y The new y position
263      */
264     onPosition : function(x, y){
265
266     },
267
268     // private
269     adjustSize : function(w, h){
270         if(this.autoWidth){
271             w = 'auto';
272         }
273         if(this.autoHeight){
274             h = 'auto';
275         }
276         return {width : w, height: h};
277     },
278
279     // private
280     adjustPosition : function(x, y){
281         return {x : x, y: y};
282     }
283 });