1 | /* |
---|
2 | * Ext JS Library 2.2.1 |
---|
3 | * Copyright(c) 2006-2009, Ext JS, LLC. |
---|
4 | * licensing@extjs.com |
---|
5 | * |
---|
6 | * http://extjs.com/license |
---|
7 | */ |
---|
8 | |
---|
9 | /** |
---|
10 | * @class Ext.layout.BorderLayout |
---|
11 | * @extends Ext.layout.ContainerLayout |
---|
12 | * <p>This is a multi-pane, application-oriented UI layout style that supports multiple nested panels, automatic |
---|
13 | * split bars between regions and built-in expanding and collapsing of regions. |
---|
14 | * This class is intended to be extended or created via the layout:'border' {@link Ext.Container#layout} config, |
---|
15 | * and should generally not need to be created directly via the new keyword.</p> |
---|
16 | * <p>BorderLayout does not have any direct config options (other than inherited ones). All configs available |
---|
17 | * for customizing the BorderLayout are at the {@link Ext.layout.BorderLayout.Region} and |
---|
18 | * {@link Ext.layout.BorderLayout.SplitRegion} levels.</p> |
---|
19 | * <p><b>The regions of a BorderLayout are fixed at render time and thereafter, no regions may be removed or |
---|
20 | * added. The BorderLayout must have a center region, which will always fill the remaining space not used by |
---|
21 | * the other regions in the layout.</b></p> |
---|
22 | * <p>Example usage:</p> |
---|
23 | * <pre><code> |
---|
24 | var border = new Ext.Panel({ |
---|
25 | title: 'Border Layout', |
---|
26 | layout:'border', |
---|
27 | items: [{ |
---|
28 | title: 'South Panel', |
---|
29 | region: 'south', |
---|
30 | height: 100, |
---|
31 | minSize: 75, |
---|
32 | maxSize: 250, |
---|
33 | margins: '0 5 5 5' |
---|
34 | },{ |
---|
35 | title: 'West Panel', |
---|
36 | region:'west', |
---|
37 | margins: '5 0 0 5', |
---|
38 | cmargins: '5 5 0 5', |
---|
39 | width: 200, |
---|
40 | minSize: 100, |
---|
41 | maxSize: 300 |
---|
42 | },{ |
---|
43 | title: 'Main Content', |
---|
44 | region:'center', |
---|
45 | margins: '5 5 0 0' |
---|
46 | }] |
---|
47 | }); |
---|
48 | </code></pre> |
---|
49 | */ |
---|
50 | Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, { |
---|
51 | // private |
---|
52 | monitorResize:true, |
---|
53 | // private |
---|
54 | rendered : false, |
---|
55 | |
---|
56 | // private |
---|
57 | onLayout : function(ct, target){ |
---|
58 | var collapsed; |
---|
59 | if(!this.rendered){ |
---|
60 | target.position(); |
---|
61 | target.addClass('x-border-layout-ct'); |
---|
62 | var items = ct.items.items; |
---|
63 | collapsed = []; |
---|
64 | for(var i = 0, len = items.length; i < len; i++) { |
---|
65 | var c = items[i]; |
---|
66 | var pos = c.region; |
---|
67 | if(c.collapsed){ |
---|
68 | collapsed.push(c); |
---|
69 | } |
---|
70 | c.collapsed = false; |
---|
71 | if(!c.rendered){ |
---|
72 | c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel'; |
---|
73 | c.render(target, i); |
---|
74 | } |
---|
75 | this[pos] = pos != 'center' && c.split ? |
---|
76 | new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) : |
---|
77 | new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos); |
---|
78 | this[pos].render(target, c); |
---|
79 | } |
---|
80 | this.rendered = true; |
---|
81 | } |
---|
82 | |
---|
83 | var size = target.getViewSize(); |
---|
84 | if(size.width < 20 || size.height < 20){ // display none? |
---|
85 | if(collapsed){ |
---|
86 | this.restoreCollapsed = collapsed; |
---|
87 | } |
---|
88 | return; |
---|
89 | }else if(this.restoreCollapsed){ |
---|
90 | collapsed = this.restoreCollapsed; |
---|
91 | delete this.restoreCollapsed; |
---|
92 | } |
---|
93 | |
---|
94 | var w = size.width, h = size.height; |
---|
95 | var centerW = w, centerH = h, centerY = 0, centerX = 0; |
---|
96 | |
---|
97 | var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center; |
---|
98 | if(!c && Ext.layout.BorderLayout.WARN !== false){ |
---|
99 | throw 'No center region defined in BorderLayout ' + ct.id; |
---|
100 | } |
---|
101 | |
---|
102 | if(n && n.isVisible()){ |
---|
103 | var b = n.getSize(); |
---|
104 | var m = n.getMargins(); |
---|
105 | b.width = w - (m.left+m.right); |
---|
106 | b.x = m.left; |
---|
107 | b.y = m.top; |
---|
108 | centerY = b.height + b.y + m.bottom; |
---|
109 | centerH -= centerY; |
---|
110 | n.applyLayout(b); |
---|
111 | } |
---|
112 | if(s && s.isVisible()){ |
---|
113 | var b = s.getSize(); |
---|
114 | var m = s.getMargins(); |
---|
115 | b.width = w - (m.left+m.right); |
---|
116 | b.x = m.left; |
---|
117 | var totalHeight = (b.height + m.top + m.bottom); |
---|
118 | b.y = h - totalHeight + m.top; |
---|
119 | centerH -= totalHeight; |
---|
120 | s.applyLayout(b); |
---|
121 | } |
---|
122 | if(west && west.isVisible()){ |
---|
123 | var b = west.getSize(); |
---|
124 | var m = west.getMargins(); |
---|
125 | b.height = centerH - (m.top+m.bottom); |
---|
126 | b.x = m.left; |
---|
127 | b.y = centerY + m.top; |
---|
128 | var totalWidth = (b.width + m.left + m.right); |
---|
129 | centerX += totalWidth; |
---|
130 | centerW -= totalWidth; |
---|
131 | west.applyLayout(b); |
---|
132 | } |
---|
133 | if(e && e.isVisible()){ |
---|
134 | var b = e.getSize(); |
---|
135 | var m = e.getMargins(); |
---|
136 | b.height = centerH - (m.top+m.bottom); |
---|
137 | var totalWidth = (b.width + m.left + m.right); |
---|
138 | b.x = w - totalWidth + m.left; |
---|
139 | b.y = centerY + m.top; |
---|
140 | centerW -= totalWidth; |
---|
141 | e.applyLayout(b); |
---|
142 | } |
---|
143 | |
---|
144 | if(c){ |
---|
145 | var m = c.getMargins(); |
---|
146 | var centerBox = { |
---|
147 | x: centerX + m.left, |
---|
148 | y: centerY + m.top, |
---|
149 | width: centerW - (m.left+m.right), |
---|
150 | height: centerH - (m.top+m.bottom) |
---|
151 | }; |
---|
152 | c.applyLayout(centerBox); |
---|
153 | } |
---|
154 | if(collapsed){ |
---|
155 | for(var i = 0, len = collapsed.length; i < len; i++){ |
---|
156 | collapsed[i].collapse(false); |
---|
157 | } |
---|
158 | } |
---|
159 | |
---|
160 | if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue |
---|
161 | target.repaint(); |
---|
162 | } |
---|
163 | }, |
---|
164 | |
---|
165 | // inherit docs |
---|
166 | destroy: function() { |
---|
167 | var r = ['north', 'south', 'east', 'west']; |
---|
168 | for (var i = 0; i < r.length; i++) { |
---|
169 | var region = this[r[i]]; |
---|
170 | if(region){ |
---|
171 | if(region.destroy){ |
---|
172 | region.destroy(); |
---|
173 | }else if (region.split){ |
---|
174 | region.split.destroy(true); |
---|
175 | } |
---|
176 | } |
---|
177 | } |
---|
178 | Ext.layout.BorderLayout.superclass.destroy.call(this); |
---|
179 | } |
---|
180 | |
---|
181 | /** |
---|
182 | * @property activeItem |
---|
183 | * @hide |
---|
184 | */ |
---|
185 | }); |
---|
186 | |
---|
187 | /** |
---|
188 | * @class Ext.layout.BorderLayout.Region |
---|
189 | * This is a region of a BorderLayout that acts as a subcontainer within the layout. Each region has its own |
---|
190 | * layout that is independent of other regions and the containing BorderLayout, and can be any of the valid |
---|
191 | * Ext layout types. Region size is managed automatically and cannot be changed by the user -- for resizable |
---|
192 | * regions, see {@link Ext.layout.BorderLayout.SplitRegion}. |
---|
193 | * @constructor |
---|
194 | * Create a new Region. |
---|
195 | * @param {Layout} layout Any valid Ext layout class |
---|
196 | * @param {Object} config The configuration options |
---|
197 | * @param {String} position The region position. Valid values are: north, south, east, west and center. Every |
---|
198 | * BorderLayout must have a center region for the primary content -- all other regions are optional. |
---|
199 | */ |
---|
200 | Ext.layout.BorderLayout.Region = function(layout, config, pos){ |
---|
201 | Ext.apply(this, config); |
---|
202 | this.layout = layout; |
---|
203 | this.position = pos; |
---|
204 | this.state = {}; |
---|
205 | if(typeof this.margins == 'string'){ |
---|
206 | this.margins = this.layout.parseMargins(this.margins); |
---|
207 | } |
---|
208 | this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins); |
---|
209 | if(this.collapsible){ |
---|
210 | if(typeof this.cmargins == 'string'){ |
---|
211 | this.cmargins = this.layout.parseMargins(this.cmargins); |
---|
212 | } |
---|
213 | if(this.collapseMode == 'mini' && !this.cmargins){ |
---|
214 | this.cmargins = {left:0,top:0,right:0,bottom:0}; |
---|
215 | }else{ |
---|
216 | this.cmargins = Ext.applyIf(this.cmargins || {}, |
---|
217 | pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins); |
---|
218 | } |
---|
219 | } |
---|
220 | }; |
---|
221 | |
---|
222 | Ext.layout.BorderLayout.Region.prototype = { |
---|
223 | /** |
---|
224 | * @cfg {Boolean} animFloat |
---|
225 | * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated panel that will |
---|
226 | * close again once the user mouses out of that panel (or clicks out if autoHide = false). Setting animFloat |
---|
227 | * to false will prevent the open and close of these floated panels from being animated (defaults to true). |
---|
228 | */ |
---|
229 | /** |
---|
230 | * @cfg {Boolean} autoHide |
---|
231 | * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated panel. If |
---|
232 | * autoHide is true, the panel will automatically hide after the user mouses out of the panel. If autoHide |
---|
233 | * is false, the panel will continue to display until the user clicks outside of the panel (defaults to true). |
---|
234 | */ |
---|
235 | /** |
---|
236 | * @cfg {Boolean} collapsed |
---|
237 | * By default, collapsible regions will be visible when rendered. Set the collapsed config to true to render |
---|
238 | * the region as collapsed. |
---|
239 | */ |
---|
240 | /** |
---|
241 | * @cfg {String} collapseMode |
---|
242 | * By default, collapsible regions are collapsed by clicking the expand/collapse tool button that renders into |
---|
243 | * the region's title bar. Optionally, when collapseMode is set to 'mini' the region's split bar will also |
---|
244 | * display a small collapse button in the center of the bar. In 'mini' mode the region will collapse to a |
---|
245 | * thinner bar than in normal mode. By default collapseMode is undefined, and the only two supported values |
---|
246 | * are undefined and 'mini'. Note that if a collapsible region does not have a title bar, then collapseMode |
---|
247 | * must be set to 'mini' in order for the region to be collapsible by the user as the tool button will not |
---|
248 | * be rendered. |
---|
249 | */ |
---|
250 | /** |
---|
251 | * @cfg {Object} margins |
---|
252 | * An object containing margins to apply to the region when in the expanded state in the format:<pre><code> |
---|
253 | { |
---|
254 | top: (top margin), |
---|
255 | right: (right margin), |
---|
256 | bottom: (bottom margin) |
---|
257 | left: (left margin), |
---|
258 | }</code></pre> |
---|
259 | * <p>May also be a string containing space-separated, numeric margin values. The order of the sides associated |
---|
260 | * with each value matches the way CSS processes margin values:</p> |
---|
261 | * <p><ul> |
---|
262 | * <li>If there is only one value, it applies to all sides.</li> |
---|
263 | * <li>If there are two values, the top and bottom borders are set to the first value and the right |
---|
264 | * and left are set to the second.</li> |
---|
265 | * <li>If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom |
---|
266 | * is set to the third.</li> |
---|
267 | * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li> |
---|
268 | * </ul></p> |
---|
269 | */ |
---|
270 | /** |
---|
271 | * @cfg {Object} cmargins |
---|
272 | * An object containing margins to apply to the region when in the collapsed state in the format:<pre><code> |
---|
273 | { |
---|
274 | top: (top margin), |
---|
275 | right: (right margin), |
---|
276 | bottom: (bottom margin) |
---|
277 | left: (left margin), |
---|
278 | }</code></pre> |
---|
279 | * <p>May also be a string containing space-separated, numeric margin values. The order of the sides associated |
---|
280 | * with each value matches the way CSS processes margin values.</p> |
---|
281 | * <p><ul> |
---|
282 | * <li>If there is only one value, it applies to all sides.</li> |
---|
283 | * <li>If there are two values, the top and bottom borders are set to the first value and the right |
---|
284 | * and left are set to the second.</li> |
---|
285 | * <li>If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom |
---|
286 | * is set to the third.</li> |
---|
287 | * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li> |
---|
288 | * </ul></p> |
---|
289 | */ |
---|
290 | /** |
---|
291 | * @cfg {Boolean} collapsible |
---|
292 | * True to allow the user to collapse this region (defaults to false). If true, an expand/collapse tool button |
---|
293 | * will automatically be rendered into the title bar of the region, otherwise the button will not be shown. |
---|
294 | * Note that a title bar is required to display the toggle button -- if no region title is specified, the |
---|
295 | * region will only be collapsible if {@link #collapseMode} is set to 'mini'. |
---|
296 | */ |
---|
297 | collapsible : false, |
---|
298 | /** |
---|
299 | * @cfg {Boolean} split |
---|
300 | * True to display a {@link Ext.SplitBar} between this region and its neighbor, allowing the user to resize |
---|
301 | * the regions dynamically (defaults to false). When split == true, it is common to specify a minSize |
---|
302 | * and maxSize for the BoxComponent representing the region. These are not native configs of BoxComponent, and |
---|
303 | * are used only by this class. |
---|
304 | */ |
---|
305 | split:false, |
---|
306 | /** |
---|
307 | * @cfg {Boolean} floatable |
---|
308 | * True to allow clicking a collapsed region's bar to display the region's panel floated above the layout, |
---|
309 | * false to force the user to fully expand a collapsed region by clicking the expand button to see it again |
---|
310 | * (defaults to true). |
---|
311 | */ |
---|
312 | floatable: true, |
---|
313 | /** |
---|
314 | * @cfg {Number} minWidth |
---|
315 | * The minimum allowable width in pixels for this region (defaults to 50) |
---|
316 | */ |
---|
317 | minWidth:50, |
---|
318 | /** |
---|
319 | * @cfg {Number} minHeight |
---|
320 | * The minimum allowable height in pixels for this region (defaults to 50) |
---|
321 | */ |
---|
322 | minHeight:50, |
---|
323 | |
---|
324 | // private |
---|
325 | defaultMargins : {left:0,top:0,right:0,bottom:0}, |
---|
326 | // private |
---|
327 | defaultNSCMargins : {left:5,top:5,right:5,bottom:5}, |
---|
328 | // private |
---|
329 | defaultEWCMargins : {left:5,top:0,right:5,bottom:0}, |
---|
330 | |
---|
331 | /** |
---|
332 | * True if this region is collapsed. Read-only. |
---|
333 | * @type Boolean |
---|
334 | * @property |
---|
335 | */ |
---|
336 | isCollapsed : false, |
---|
337 | |
---|
338 | /** |
---|
339 | * This region's panel. Read-only. |
---|
340 | * @type Ext.Panel |
---|
341 | * @property panel |
---|
342 | */ |
---|
343 | /** |
---|
344 | * This region's layout. Read-only. |
---|
345 | * @type Layout |
---|
346 | * @property layout |
---|
347 | */ |
---|
348 | /** |
---|
349 | * This region's layout position (north, south, east, west or center). Read-only. |
---|
350 | * @type String |
---|
351 | * @property position |
---|
352 | */ |
---|
353 | |
---|
354 | // private |
---|
355 | render : function(ct, p){ |
---|
356 | this.panel = p; |
---|
357 | p.el.enableDisplayMode(); |
---|
358 | this.targetEl = ct; |
---|
359 | this.el = p.el; |
---|
360 | |
---|
361 | var gs = p.getState, ps = this.position; |
---|
362 | p.getState = function(){ |
---|
363 | return Ext.apply(gs.call(p) || {}, this.state); |
---|
364 | }.createDelegate(this); |
---|
365 | |
---|
366 | if(ps != 'center'){ |
---|
367 | p.allowQueuedExpand = false; |
---|
368 | p.on({ |
---|
369 | beforecollapse: this.beforeCollapse, |
---|
370 | collapse: this.onCollapse, |
---|
371 | beforeexpand: this.beforeExpand, |
---|
372 | expand: this.onExpand, |
---|
373 | hide: this.onHide, |
---|
374 | show: this.onShow, |
---|
375 | scope: this |
---|
376 | }); |
---|
377 | if(this.collapsible){ |
---|
378 | p.collapseEl = 'el'; |
---|
379 | p.slideAnchor = this.getSlideAnchor(); |
---|
380 | } |
---|
381 | if(p.tools && p.tools.toggle){ |
---|
382 | p.tools.toggle.addClass('x-tool-collapse-'+ps); |
---|
383 | p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over'); |
---|
384 | } |
---|
385 | } |
---|
386 | }, |
---|
387 | |
---|
388 | // private |
---|
389 | getCollapsedEl : function(){ |
---|
390 | if(!this.collapsedEl){ |
---|
391 | if(!this.toolTemplate){ |
---|
392 | var tt = new Ext.Template( |
---|
393 | '<div class="x-tool x-tool-{id}"> </div>' |
---|
394 | ); |
---|
395 | tt.disableFormats = true; |
---|
396 | tt.compile(); |
---|
397 | Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt; |
---|
398 | } |
---|
399 | this.collapsedEl = this.targetEl.createChild({ |
---|
400 | cls: "x-layout-collapsed x-layout-collapsed-"+this.position, |
---|
401 | id: this.panel.id + '-xcollapsed' |
---|
402 | }); |
---|
403 | this.collapsedEl.enableDisplayMode('block'); |
---|
404 | |
---|
405 | if(this.collapseMode == 'mini'){ |
---|
406 | this.collapsedEl.addClass('x-layout-cmini-'+this.position); |
---|
407 | this.miniCollapsedEl = this.collapsedEl.createChild({ |
---|
408 | cls: "x-layout-mini x-layout-mini-"+this.position, html: " " |
---|
409 | }); |
---|
410 | this.miniCollapsedEl.addClassOnOver('x-layout-mini-over'); |
---|
411 | this.collapsedEl.addClassOnOver("x-layout-collapsed-over"); |
---|
412 | this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true}); |
---|
413 | }else { |
---|
414 | var t = this.toolTemplate.append( |
---|
415 | this.collapsedEl.dom, |
---|
416 | {id:'expand-'+this.position}, true); |
---|
417 | t.addClassOnOver('x-tool-expand-'+this.position+'-over'); |
---|
418 | t.on('click', this.onExpandClick, this, {stopEvent:true}); |
---|
419 | |
---|
420 | if(this.floatable !== false){ |
---|
421 | this.collapsedEl.addClassOnOver("x-layout-collapsed-over"); |
---|
422 | this.collapsedEl.on("click", this.collapseClick, this); |
---|
423 | } |
---|
424 | } |
---|
425 | } |
---|
426 | return this.collapsedEl; |
---|
427 | }, |
---|
428 | |
---|
429 | // private |
---|
430 | onExpandClick : function(e){ |
---|
431 | if(this.isSlid){ |
---|
432 | this.afterSlideIn(); |
---|
433 | this.panel.expand(false); |
---|
434 | }else{ |
---|
435 | this.panel.expand(); |
---|
436 | } |
---|
437 | }, |
---|
438 | |
---|
439 | // private |
---|
440 | onCollapseClick : function(e){ |
---|
441 | this.panel.collapse(); |
---|
442 | }, |
---|
443 | |
---|
444 | // private |
---|
445 | beforeCollapse : function(p, animate){ |
---|
446 | this.lastAnim = animate; |
---|
447 | if(this.splitEl){ |
---|
448 | this.splitEl.hide(); |
---|
449 | } |
---|
450 | this.getCollapsedEl().show(); |
---|
451 | this.panel.el.setStyle('z-index', 100); |
---|
452 | this.isCollapsed = true; |
---|
453 | this.layout.layout(); |
---|
454 | }, |
---|
455 | |
---|
456 | // private |
---|
457 | onCollapse : function(animate){ |
---|
458 | this.panel.el.setStyle('z-index', 1); |
---|
459 | if(this.lastAnim === false || this.panel.animCollapse === false){ |
---|
460 | this.getCollapsedEl().dom.style.visibility = 'visible'; |
---|
461 | }else{ |
---|
462 | this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2}); |
---|
463 | } |
---|
464 | this.state.collapsed = true; |
---|
465 | this.panel.saveState(); |
---|
466 | }, |
---|
467 | |
---|
468 | // private |
---|
469 | beforeExpand : function(animate){ |
---|
470 | var c = this.getCollapsedEl(); |
---|
471 | this.el.show(); |
---|
472 | if(this.position == 'east' || this.position == 'west'){ |
---|
473 | this.panel.setSize(undefined, c.getHeight()); |
---|
474 | }else{ |
---|
475 | this.panel.setSize(c.getWidth(), undefined); |
---|
476 | } |
---|
477 | c.hide(); |
---|
478 | c.dom.style.visibility = 'hidden'; |
---|
479 | this.panel.el.setStyle('z-index', 100); |
---|
480 | }, |
---|
481 | |
---|
482 | // private |
---|
483 | onExpand : function(){ |
---|
484 | this.isCollapsed = false; |
---|
485 | if(this.splitEl){ |
---|
486 | this.splitEl.show(); |
---|
487 | } |
---|
488 | this.layout.layout(); |
---|
489 | this.panel.el.setStyle('z-index', 1); |
---|
490 | this.state.collapsed = false; |
---|
491 | this.panel.saveState(); |
---|
492 | }, |
---|
493 | |
---|
494 | // private |
---|
495 | collapseClick : function(e){ |
---|
496 | if(this.isSlid){ |
---|
497 | e.stopPropagation(); |
---|
498 | this.slideIn(); |
---|
499 | }else{ |
---|
500 | e.stopPropagation(); |
---|
501 | this.slideOut(); |
---|
502 | } |
---|
503 | }, |
---|
504 | |
---|
505 | // private |
---|
506 | onHide : function(){ |
---|
507 | if(this.isCollapsed){ |
---|
508 | this.getCollapsedEl().hide(); |
---|
509 | }else if(this.splitEl){ |
---|
510 | this.splitEl.hide(); |
---|
511 | } |
---|
512 | }, |
---|
513 | |
---|
514 | // private |
---|
515 | onShow : function(){ |
---|
516 | if(this.isCollapsed){ |
---|
517 | this.getCollapsedEl().show(); |
---|
518 | }else if(this.splitEl){ |
---|
519 | this.splitEl.show(); |
---|
520 | } |
---|
521 | }, |
---|
522 | |
---|
523 | /** |
---|
524 | * True if this region is currently visible, else false. |
---|
525 | * @return {Boolean} |
---|
526 | */ |
---|
527 | isVisible : function(){ |
---|
528 | return !this.panel.hidden; |
---|
529 | }, |
---|
530 | |
---|
531 | /** |
---|
532 | * Returns the current margins for this region. If the region is collapsed, the cmargins (collapsed |
---|
533 | * margins) value will be returned, otherwise the margins value will be returned. |
---|
534 | * @return {Object} An object containing the element's margins: {left: (left margin), top: (top margin), |
---|
535 | * right: (right margin), bottom: (bottom margin)} |
---|
536 | */ |
---|
537 | getMargins : function(){ |
---|
538 | return this.isCollapsed && this.cmargins ? this.cmargins : this.margins; |
---|
539 | }, |
---|
540 | |
---|
541 | /** |
---|
542 | * Returns the current size of this region. If the region is collapsed, the size of the collapsedEl will |
---|
543 | * be returned, otherwise the size of the region's panel will be returned. |
---|
544 | * @return {Object} An object containing the element's size: {width: (element width), height: (element height)} |
---|
545 | */ |
---|
546 | getSize : function(){ |
---|
547 | return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize(); |
---|
548 | }, |
---|
549 | |
---|
550 | /** |
---|
551 | * Sets the specified panel as the container element for this region. |
---|
552 | * @param {Ext.Panel} panel The new panel |
---|
553 | */ |
---|
554 | setPanel : function(panel){ |
---|
555 | this.panel = panel; |
---|
556 | }, |
---|
557 | |
---|
558 | /** |
---|
559 | * Returns the minimum allowable width for this region. |
---|
560 | * @return {Number} The minimum width |
---|
561 | */ |
---|
562 | getMinWidth: function(){ |
---|
563 | return this.minWidth; |
---|
564 | }, |
---|
565 | |
---|
566 | /** |
---|
567 | * Returns the minimum allowable height for this region. |
---|
568 | * @return {Number} The minimum height |
---|
569 | */ |
---|
570 | getMinHeight: function(){ |
---|
571 | return this.minHeight; |
---|
572 | }, |
---|
573 | |
---|
574 | // private |
---|
575 | applyLayoutCollapsed : function(box){ |
---|
576 | var ce = this.getCollapsedEl(); |
---|
577 | ce.setLeftTop(box.x, box.y); |
---|
578 | ce.setSize(box.width, box.height); |
---|
579 | }, |
---|
580 | |
---|
581 | // private |
---|
582 | applyLayout : function(box){ |
---|
583 | if(this.isCollapsed){ |
---|
584 | this.applyLayoutCollapsed(box); |
---|
585 | }else{ |
---|
586 | this.panel.setPosition(box.x, box.y); |
---|
587 | this.panel.setSize(box.width, box.height); |
---|
588 | } |
---|
589 | }, |
---|
590 | |
---|
591 | // private |
---|
592 | beforeSlide: function(){ |
---|
593 | this.panel.beforeEffect(); |
---|
594 | }, |
---|
595 | |
---|
596 | // private |
---|
597 | afterSlide : function(){ |
---|
598 | this.panel.afterEffect(); |
---|
599 | }, |
---|
600 | |
---|
601 | // private |
---|
602 | initAutoHide : function(){ |
---|
603 | if(this.autoHide !== false){ |
---|
604 | if(!this.autoHideHd){ |
---|
605 | var st = new Ext.util.DelayedTask(this.slideIn, this); |
---|
606 | this.autoHideHd = { |
---|
607 | "mouseout": function(e){ |
---|
608 | if(!e.within(this.el, true)){ |
---|
609 | st.delay(500); |
---|
610 | } |
---|
611 | }, |
---|
612 | "mouseover" : function(e){ |
---|
613 | st.cancel(); |
---|
614 | }, |
---|
615 | scope : this |
---|
616 | }; |
---|
617 | } |
---|
618 | this.el.on(this.autoHideHd); |
---|
619 | } |
---|
620 | }, |
---|
621 | |
---|
622 | // private |
---|
623 | clearAutoHide : function(){ |
---|
624 | if(this.autoHide !== false){ |
---|
625 | this.el.un("mouseout", this.autoHideHd.mouseout); |
---|
626 | this.el.un("mouseover", this.autoHideHd.mouseover); |
---|
627 | } |
---|
628 | }, |
---|
629 | |
---|
630 | // private |
---|
631 | clearMonitor : function(){ |
---|
632 | Ext.getDoc().un("click", this.slideInIf, this); |
---|
633 | }, |
---|
634 | |
---|
635 | // these names are backwards but not changed for compat |
---|
636 | // private |
---|
637 | slideOut : function(){ |
---|
638 | if(this.isSlid || this.el.hasActiveFx()){ |
---|
639 | return; |
---|
640 | } |
---|
641 | this.isSlid = true; |
---|
642 | var ts = this.panel.tools; |
---|
643 | if(ts && ts.toggle){ |
---|
644 | ts.toggle.hide(); |
---|
645 | } |
---|
646 | this.el.show(); |
---|
647 | if(this.position == 'east' || this.position == 'west'){ |
---|
648 | this.panel.setSize(undefined, this.collapsedEl.getHeight()); |
---|
649 | }else{ |
---|
650 | this.panel.setSize(this.collapsedEl.getWidth(), undefined); |
---|
651 | } |
---|
652 | this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top]; |
---|
653 | this.el.alignTo(this.collapsedEl, this.getCollapseAnchor()); |
---|
654 | this.el.setStyle("z-index", 102); |
---|
655 | this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating'); |
---|
656 | if(this.animFloat !== false){ |
---|
657 | this.beforeSlide(); |
---|
658 | this.el.slideIn(this.getSlideAnchor(), { |
---|
659 | callback: function(){ |
---|
660 | this.afterSlide(); |
---|
661 | this.initAutoHide(); |
---|
662 | Ext.getDoc().on("click", this.slideInIf, this); |
---|
663 | }, |
---|
664 | scope: this, |
---|
665 | block: true |
---|
666 | }); |
---|
667 | }else{ |
---|
668 | this.initAutoHide(); |
---|
669 | Ext.getDoc().on("click", this.slideInIf, this); |
---|
670 | } |
---|
671 | }, |
---|
672 | |
---|
673 | // private |
---|
674 | afterSlideIn : function(){ |
---|
675 | this.clearAutoHide(); |
---|
676 | this.isSlid = false; |
---|
677 | this.clearMonitor(); |
---|
678 | this.el.setStyle("z-index", ""); |
---|
679 | this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed'); |
---|
680 | this.el.dom.style.left = this.restoreLT[0]; |
---|
681 | this.el.dom.style.top = this.restoreLT[1]; |
---|
682 | |
---|
683 | var ts = this.panel.tools; |
---|
684 | if(ts && ts.toggle){ |
---|
685 | ts.toggle.show(); |
---|
686 | } |
---|
687 | }, |
---|
688 | |
---|
689 | // private |
---|
690 | slideIn : function(cb){ |
---|
691 | if(!this.isSlid || this.el.hasActiveFx()){ |
---|
692 | Ext.callback(cb); |
---|
693 | return; |
---|
694 | } |
---|
695 | this.isSlid = false; |
---|
696 | if(this.animFloat !== false){ |
---|
697 | this.beforeSlide(); |
---|
698 | this.el.slideOut(this.getSlideAnchor(), { |
---|
699 | callback: function(){ |
---|
700 | this.el.hide(); |
---|
701 | this.afterSlide(); |
---|
702 | this.afterSlideIn(); |
---|
703 | Ext.callback(cb); |
---|
704 | }, |
---|
705 | scope: this, |
---|
706 | block: true |
---|
707 | }); |
---|
708 | }else{ |
---|
709 | this.el.hide(); |
---|
710 | this.afterSlideIn(); |
---|
711 | } |
---|
712 | }, |
---|
713 | |
---|
714 | // private |
---|
715 | slideInIf : function(e){ |
---|
716 | if(!e.within(this.el)){ |
---|
717 | this.slideIn(); |
---|
718 | } |
---|
719 | }, |
---|
720 | |
---|
721 | // private |
---|
722 | anchors : { |
---|
723 | "west" : "left", |
---|
724 | "east" : "right", |
---|
725 | "north" : "top", |
---|
726 | "south" : "bottom" |
---|
727 | }, |
---|
728 | |
---|
729 | // private |
---|
730 | sanchors : { |
---|
731 | "west" : "l", |
---|
732 | "east" : "r", |
---|
733 | "north" : "t", |
---|
734 | "south" : "b" |
---|
735 | }, |
---|
736 | |
---|
737 | // private |
---|
738 | canchors : { |
---|
739 | "west" : "tl-tr", |
---|
740 | "east" : "tr-tl", |
---|
741 | "north" : "tl-bl", |
---|
742 | "south" : "bl-tl" |
---|
743 | }, |
---|
744 | |
---|
745 | // private |
---|
746 | getAnchor : function(){ |
---|
747 | return this.anchors[this.position]; |
---|
748 | }, |
---|
749 | |
---|
750 | // private |
---|
751 | getCollapseAnchor : function(){ |
---|
752 | return this.canchors[this.position]; |
---|
753 | }, |
---|
754 | |
---|
755 | // private |
---|
756 | getSlideAnchor : function(){ |
---|
757 | return this.sanchors[this.position]; |
---|
758 | }, |
---|
759 | |
---|
760 | // private |
---|
761 | getAlignAdj : function(){ |
---|
762 | var cm = this.cmargins; |
---|
763 | switch(this.position){ |
---|
764 | case "west": |
---|
765 | return [0, 0]; |
---|
766 | break; |
---|
767 | case "east": |
---|
768 | return [0, 0]; |
---|
769 | break; |
---|
770 | case "north": |
---|
771 | return [0, 0]; |
---|
772 | break; |
---|
773 | case "south": |
---|
774 | return [0, 0]; |
---|
775 | break; |
---|
776 | } |
---|
777 | }, |
---|
778 | |
---|
779 | // private |
---|
780 | getExpandAdj : function(){ |
---|
781 | var c = this.collapsedEl, cm = this.cmargins; |
---|
782 | switch(this.position){ |
---|
783 | case "west": |
---|
784 | return [-(cm.right+c.getWidth()+cm.left), 0]; |
---|
785 | break; |
---|
786 | case "east": |
---|
787 | return [cm.right+c.getWidth()+cm.left, 0]; |
---|
788 | break; |
---|
789 | case "north": |
---|
790 | return [0, -(cm.top+cm.bottom+c.getHeight())]; |
---|
791 | break; |
---|
792 | case "south": |
---|
793 | return [0, cm.top+cm.bottom+c.getHeight()]; |
---|
794 | break; |
---|
795 | } |
---|
796 | } |
---|
797 | }; |
---|
798 | |
---|
799 | /** |
---|
800 | * @class Ext.layout.BorderLayout.SplitRegion |
---|
801 | * @extends Ext.layout.BorderLayout.Region |
---|
802 | * This is a specialized type of BorderLayout region that has a built-in {@link Ext.SplitBar} for user resizing of regions. |
---|
803 | * @constructor |
---|
804 | * Create a new SplitRegion. |
---|
805 | * @param {Layout} layout Any valid Ext layout class |
---|
806 | * @param {Object} config The configuration options |
---|
807 | * @param {String} position The region position. Valid values are: north, south, east, west and center. Every |
---|
808 | * BorderLayout must have a center region for the primary content -- all other regions are optional. |
---|
809 | */ |
---|
810 | Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){ |
---|
811 | Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos); |
---|
812 | // prevent switch |
---|
813 | this.applyLayout = this.applyFns[pos]; |
---|
814 | }; |
---|
815 | |
---|
816 | Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, { |
---|
817 | /** |
---|
818 | * @cfg {String} splitTip |
---|
819 | * The tooltip to display when the user hovers over a non-collapsible region's split bar (defaults to "Drag |
---|
820 | * to resize."). Only applies if {@link #useSplitTips} = true. |
---|
821 | */ |
---|
822 | splitTip : "Drag to resize.", |
---|
823 | /** |
---|
824 | * @cfg {String} collapsibleSplitTip |
---|
825 | * The tooltip to display when the user hovers over a collapsible region's split bar (defaults to "Drag |
---|
826 | * to resize. Double click to hide."). Only applies if {@link #useSplitTips} = true. |
---|
827 | */ |
---|
828 | collapsibleSplitTip : "Drag to resize. Double click to hide.", |
---|
829 | /** |
---|
830 | * @cfg {Boolean} useSplitTips |
---|
831 | * True to display a tooltip when the user hovers over a region's split bar (defaults to false). The tooltip |
---|
832 | * text will be the value of either {@link #splitTip} or {@link #collapsibleSplitTip} as appropriate. |
---|
833 | */ |
---|
834 | useSplitTips : false, |
---|
835 | |
---|
836 | // private |
---|
837 | splitSettings : { |
---|
838 | north : { |
---|
839 | orientation: Ext.SplitBar.VERTICAL, |
---|
840 | placement: Ext.SplitBar.TOP, |
---|
841 | maxFn : 'getVMaxSize', |
---|
842 | minProp: 'minHeight', |
---|
843 | maxProp: 'maxHeight' |
---|
844 | }, |
---|
845 | south : { |
---|
846 | orientation: Ext.SplitBar.VERTICAL, |
---|
847 | placement: Ext.SplitBar.BOTTOM, |
---|
848 | maxFn : 'getVMaxSize', |
---|
849 | minProp: 'minHeight', |
---|
850 | maxProp: 'maxHeight' |
---|
851 | }, |
---|
852 | east : { |
---|
853 | orientation: Ext.SplitBar.HORIZONTAL, |
---|
854 | placement: Ext.SplitBar.RIGHT, |
---|
855 | maxFn : 'getHMaxSize', |
---|
856 | minProp: 'minWidth', |
---|
857 | maxProp: 'maxWidth' |
---|
858 | }, |
---|
859 | west : { |
---|
860 | orientation: Ext.SplitBar.HORIZONTAL, |
---|
861 | placement: Ext.SplitBar.LEFT, |
---|
862 | maxFn : 'getHMaxSize', |
---|
863 | minProp: 'minWidth', |
---|
864 | maxProp: 'maxWidth' |
---|
865 | } |
---|
866 | }, |
---|
867 | |
---|
868 | // private |
---|
869 | applyFns : { |
---|
870 | west : function(box){ |
---|
871 | if(this.isCollapsed){ |
---|
872 | return this.applyLayoutCollapsed(box); |
---|
873 | } |
---|
874 | var sd = this.splitEl.dom, s = sd.style; |
---|
875 | this.panel.setPosition(box.x, box.y); |
---|
876 | var sw = sd.offsetWidth; |
---|
877 | s.left = (box.x+box.width-sw)+'px'; |
---|
878 | s.top = (box.y)+'px'; |
---|
879 | s.height = Math.max(0, box.height)+'px'; |
---|
880 | this.panel.setSize(box.width-sw, box.height); |
---|
881 | }, |
---|
882 | east : function(box){ |
---|
883 | if(this.isCollapsed){ |
---|
884 | return this.applyLayoutCollapsed(box); |
---|
885 | } |
---|
886 | var sd = this.splitEl.dom, s = sd.style; |
---|
887 | var sw = sd.offsetWidth; |
---|
888 | this.panel.setPosition(box.x+sw, box.y); |
---|
889 | s.left = (box.x)+'px'; |
---|
890 | s.top = (box.y)+'px'; |
---|
891 | s.height = Math.max(0, box.height)+'px'; |
---|
892 | this.panel.setSize(box.width-sw, box.height); |
---|
893 | }, |
---|
894 | north : function(box){ |
---|
895 | if(this.isCollapsed){ |
---|
896 | return this.applyLayoutCollapsed(box); |
---|
897 | } |
---|
898 | var sd = this.splitEl.dom, s = sd.style; |
---|
899 | var sh = sd.offsetHeight; |
---|
900 | this.panel.setPosition(box.x, box.y); |
---|
901 | s.left = (box.x)+'px'; |
---|
902 | s.top = (box.y+box.height-sh)+'px'; |
---|
903 | s.width = Math.max(0, box.width)+'px'; |
---|
904 | this.panel.setSize(box.width, box.height-sh); |
---|
905 | }, |
---|
906 | south : function(box){ |
---|
907 | if(this.isCollapsed){ |
---|
908 | return this.applyLayoutCollapsed(box); |
---|
909 | } |
---|
910 | var sd = this.splitEl.dom, s = sd.style; |
---|
911 | var sh = sd.offsetHeight; |
---|
912 | this.panel.setPosition(box.x, box.y+sh); |
---|
913 | s.left = (box.x)+'px'; |
---|
914 | s.top = (box.y)+'px'; |
---|
915 | s.width = Math.max(0, box.width)+'px'; |
---|
916 | this.panel.setSize(box.width, box.height-sh); |
---|
917 | } |
---|
918 | }, |
---|
919 | |
---|
920 | // private |
---|
921 | render : function(ct, p){ |
---|
922 | Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p); |
---|
923 | |
---|
924 | var ps = this.position; |
---|
925 | |
---|
926 | this.splitEl = ct.createChild({ |
---|
927 | cls: "x-layout-split x-layout-split-"+ps, html: " ", |
---|
928 | id: this.panel.id + '-xsplit' |
---|
929 | }); |
---|
930 | |
---|
931 | if(this.collapseMode == 'mini'){ |
---|
932 | this.miniSplitEl = this.splitEl.createChild({ |
---|
933 | cls: "x-layout-mini x-layout-mini-"+ps, html: " " |
---|
934 | }); |
---|
935 | this.miniSplitEl.addClassOnOver('x-layout-mini-over'); |
---|
936 | this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true}); |
---|
937 | } |
---|
938 | |
---|
939 | var s = this.splitSettings[ps]; |
---|
940 | |
---|
941 | this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation); |
---|
942 | this.split.placement = s.placement; |
---|
943 | this.split.getMaximumSize = this[s.maxFn].createDelegate(this); |
---|
944 | this.split.minSize = this.minSize || this[s.minProp]; |
---|
945 | this.split.on("beforeapply", this.onSplitMove, this); |
---|
946 | this.split.useShim = this.useShim === true; |
---|
947 | this.maxSize = this.maxSize || this[s.maxProp]; |
---|
948 | |
---|
949 | if(p.hidden){ |
---|
950 | this.splitEl.hide(); |
---|
951 | } |
---|
952 | |
---|
953 | if(this.useSplitTips){ |
---|
954 | this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip; |
---|
955 | } |
---|
956 | if(this.collapsible){ |
---|
957 | this.splitEl.on("dblclick", this.onCollapseClick, this); |
---|
958 | } |
---|
959 | }, |
---|
960 | |
---|
961 | //docs inherit from superclass |
---|
962 | getSize : function(){ |
---|
963 | if(this.isCollapsed){ |
---|
964 | return this.collapsedEl.getSize(); |
---|
965 | } |
---|
966 | var s = this.panel.getSize(); |
---|
967 | if(this.position == 'north' || this.position == 'south'){ |
---|
968 | s.height += this.splitEl.dom.offsetHeight; |
---|
969 | }else{ |
---|
970 | s.width += this.splitEl.dom.offsetWidth; |
---|
971 | } |
---|
972 | return s; |
---|
973 | }, |
---|
974 | |
---|
975 | // private |
---|
976 | getHMaxSize : function(){ |
---|
977 | var cmax = this.maxSize || 10000; |
---|
978 | var center = this.layout.center; |
---|
979 | return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth()); |
---|
980 | }, |
---|
981 | |
---|
982 | // private |
---|
983 | getVMaxSize : function(){ |
---|
984 | var cmax = this.maxSize || 10000; |
---|
985 | var center = this.layout.center; |
---|
986 | return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight()); |
---|
987 | }, |
---|
988 | |
---|
989 | // private |
---|
990 | onSplitMove : function(split, newSize){ |
---|
991 | var s = this.panel.getSize(); |
---|
992 | this.lastSplitSize = newSize; |
---|
993 | if(this.position == 'north' || this.position == 'south'){ |
---|
994 | this.panel.setSize(s.width, newSize); |
---|
995 | this.state.height = newSize; |
---|
996 | }else{ |
---|
997 | this.panel.setSize(newSize, s.height); |
---|
998 | this.state.width = newSize; |
---|
999 | } |
---|
1000 | this.layout.layout(); |
---|
1001 | this.panel.saveState(); |
---|
1002 | return false; |
---|
1003 | }, |
---|
1004 | |
---|
1005 | /** |
---|
1006 | * Returns a reference to the split bar in use by this region. |
---|
1007 | * @return {Ext.SplitBar} The split bar |
---|
1008 | */ |
---|
1009 | getSplitBar : function(){ |
---|
1010 | return this.split; |
---|
1011 | }, |
---|
1012 | |
---|
1013 | // inherit docs |
---|
1014 | destroy : function() { |
---|
1015 | Ext.destroy( |
---|
1016 | this.miniSplitEl, |
---|
1017 | this.split, |
---|
1018 | this.splitEl |
---|
1019 | ); |
---|
1020 | } |
---|
1021 | }); |
---|
1022 | |
---|
1023 | Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout; |
---|