Roo/BoxComponent.js
[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         Roo.log('BoxComponent!!!!!!!!!!');
67         Roo.log(w);
68         Roo.log(h);
69         // support for standard size objects
70         if(typeof w == 'object'){
71             h = w.height;
72             w = w.width;
73         }
74         // not rendered
75         if(!this.boxReady){
76             this.width = w;
77             this.height = h;
78             return this;
79         }
80
81         // prevent recalcs when not needed
82         if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
83             return this;
84         }
85         this.lastSize = {width: w, height: h};
86
87         var adj = this.adjustSize(w, h);
88         var aw = adj.width, ah = adj.height;
89         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
90             var rz = this.getResizeEl();
91             if(!this.deferHeight && aw !== undefined && ah !== undefined){
92                 rz.setSize(aw, ah);
93             }else if(!this.deferHeight && ah !== undefined){
94                 rz.setHeight(ah);
95             }else if(aw !== undefined){
96                 rz.setWidth(aw);
97             }
98             this.onResize(aw, ah, w, h);
99             this.fireEvent('resize', this, aw, ah, w, h);
100         }
101         return this;
102     },
103
104     /**
105      * Gets the current size of the component's underlying element.
106      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
107      */
108     getSize : function(){
109         return this.el.getSize();
110     },
111
112     /**
113      * Gets the current XY position of the component's underlying element.
114      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
115      * @return {Array} The XY position of the element (e.g., [100, 200])
116      */
117     getPosition : function(local){
118         if(local === true){
119             return [this.el.getLeft(true), this.el.getTop(true)];
120         }
121         return this.xy || this.el.getXY();
122     },
123
124     /**
125      * Gets the current box measurements of the component's underlying element.
126      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
127      * @returns {Object} box An object in the format {x, y, width, height}
128      */
129     getBox : function(local){
130         var s = this.el.getSize();
131         if(local){
132             s.x = this.el.getLeft(true);
133             s.y = this.el.getTop(true);
134         }else{
135             var xy = this.xy || this.el.getXY();
136             s.x = xy[0];
137             s.y = xy[1];
138         }
139         return s;
140     },
141
142     /**
143      * Sets the current box measurements of the component's underlying element.
144      * @param {Object} box An object in the format {x, y, width, height}
145      * @returns {Roo.BoxComponent} this
146      */
147     updateBox : function(box){
148         this.setSize(box.width, box.height);
149         this.setPagePosition(box.x, box.y);
150         return this;
151     },
152
153     // protected
154     getResizeEl : function(){
155         return this.resizeEl || this.el;
156     },
157
158     // protected
159     getPositionEl : function(){
160         return this.positionEl || this.el;
161     },
162
163     /**
164      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
165      * This method fires the move event.
166      * @param {Number} left The new left
167      * @param {Number} top The new top
168      * @returns {Roo.BoxComponent} this
169      */
170     setPosition : function(x, y){
171         this.x = x;
172         this.y = y;
173         if(!this.boxReady){
174             return this;
175         }
176         var adj = this.adjustPosition(x, y);
177         var ax = adj.x, ay = adj.y;
178
179         var el = this.getPositionEl();
180         if(ax !== undefined || ay !== undefined){
181             if(ax !== undefined && ay !== undefined){
182                 el.setLeftTop(ax, ay);
183             }else if(ax !== undefined){
184                 el.setLeft(ax);
185             }else if(ay !== undefined){
186                 el.setTop(ay);
187             }
188             this.onPosition(ax, ay);
189             this.fireEvent('move', this, ax, ay);
190         }
191         return this;
192     },
193
194     /**
195      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
196      * This method fires the move event.
197      * @param {Number} x The new x position
198      * @param {Number} y The new y position
199      * @returns {Roo.BoxComponent} this
200      */
201     setPagePosition : function(x, y){
202         this.pageX = x;
203         this.pageY = y;
204         if(!this.boxReady){
205             return;
206         }
207         if(x === undefined || y === undefined){ // cannot translate undefined points
208             return;
209         }
210         var p = this.el.translatePoints(x, y);
211         this.setPosition(p.left, p.top);
212         return this;
213     },
214
215     // private
216     onRender : function(ct, position){
217         Roo.BoxComponent.superclass.onRender.call(this, ct, position);
218         if(this.resizeEl){
219             this.resizeEl = Roo.get(this.resizeEl);
220         }
221         if(this.positionEl){
222             this.positionEl = Roo.get(this.positionEl);
223         }
224     },
225
226     // private
227     afterRender : function(){
228         Roo.BoxComponent.superclass.afterRender.call(this);
229         this.boxReady = true;
230         this.setSize(this.width, this.height);
231         if(this.x || this.y){
232             this.setPosition(this.x, this.y);
233         }
234         if(this.pageX || this.pageY){
235             this.setPagePosition(this.pageX, this.pageY);
236         }
237     },
238
239     /**
240      * Force the component's size to recalculate based on the underlying element's current height and width.
241      * @returns {Roo.BoxComponent} this
242      */
243     syncSize : function(){
244         delete this.lastSize;
245         this.setSize(this.el.getWidth(), this.el.getHeight());
246         return this;
247     },
248
249     /**
250      * Called after the component is resized, this method is empty by default but can be implemented by any
251      * subclass that needs to perform custom logic after a resize occurs.
252      * @param {Number} adjWidth The box-adjusted width that was set
253      * @param {Number} adjHeight The box-adjusted height that was set
254      * @param {Number} rawWidth The width that was originally specified
255      * @param {Number} rawHeight The height that was originally specified
256      */
257     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
258
259     },
260
261     /**
262      * Called after the component is moved, this method is empty by default but can be implemented by any
263      * subclass that needs to perform custom logic after a move occurs.
264      * @param {Number} x The new x position
265      * @param {Number} y The new y position
266      */
267     onPosition : function(x, y){
268
269     },
270
271     // private
272     adjustSize : function(w, h){
273         if(this.autoWidth){
274             w = 'auto';
275         }
276         if(this.autoHeight){
277             h = 'auto';
278         }
279         return {width : w, height: h};
280     },
281
282     // private
283     adjustPosition : function(x, y){
284         return {x : x, y: y};
285     }
286 });