4896edc6179a5e189b56a5fdbda283aca7f5b78b.svn-base 28 KB

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