/ext-4.0.7/docs/source/Lockable.html

https://bitbucket.org/srogerf/javascript · HTML · 733 lines · 634 code · 99 blank · 0 comment · 0 complexity · 3c7601a636189997dfc2fd0da6b274fb MD5 · raw file

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-grid-Lockable'>/**
  19. </span> * @class Ext.grid.Lockable
  20. * @private
  21. *
  22. * Lockable is a private mixin which injects lockable behavior into any
  23. * TablePanel subclass such as GridPanel or TreePanel. TablePanel will
  24. * automatically inject the Ext.grid.Lockable mixin in when one of the
  25. * these conditions are met:
  26. *
  27. * - The TablePanel has the lockable configuration set to true
  28. * - One of the columns in the TablePanel has locked set to true/false
  29. *
  30. * Each TablePanel subclass must register an alias. It should have an array
  31. * of configurations to copy to the 2 separate tablepanel's that will be generated
  32. * to note what configurations should be copied. These are named normalCfgCopy and
  33. * lockedCfgCopy respectively.
  34. *
  35. * Columns which are locked must specify a fixed width. They do NOT support a
  36. * flex width.
  37. *
  38. * Configurations which are specified in this class will be available on any grid or
  39. * tree which is using the lockable functionality.
  40. */
  41. Ext.define('Ext.grid.Lockable', {
  42. requires: ['Ext.grid.LockingView'],
  43. <span id='Ext-grid-Lockable-cfg-syncRowHeight'> /**
  44. </span> * @cfg {Boolean} syncRowHeight Synchronize rowHeight between the normal and
  45. * locked grid view. This is turned on by default. If your grid is guaranteed
  46. * to have rows of all the same height, you should set this to false to
  47. * optimize performance.
  48. */
  49. syncRowHeight: true,
  50. <span id='Ext-grid-Lockable-cfg-subGridXType'> /**
  51. </span> * @cfg {String} subGridXType The xtype of the subgrid to specify. If this is
  52. * not specified lockable will determine the subgrid xtype to create by the
  53. * following rule. Use the superclasses xtype if the superclass is NOT
  54. * tablepanel, otherwise use the xtype itself.
  55. */
  56. <span id='Ext-grid-Lockable-cfg-lockedViewConfig'> /**
  57. </span> * @cfg {Object} lockedViewConfig A view configuration to be applied to the
  58. * locked side of the grid. Any conflicting configurations between lockedViewConfig
  59. * and viewConfig will be overwritten by the lockedViewConfig.
  60. */
  61. <span id='Ext-grid-Lockable-cfg-normalViewConfig'> /**
  62. </span> * @cfg {Object} normalViewConfig A view configuration to be applied to the
  63. * normal/unlocked side of the grid. Any conflicting configurations between normalViewConfig
  64. * and viewConfig will be overwritten by the normalViewConfig.
  65. */
  66. // private variable to track whether or not the spacer is hidden/visible
  67. spacerHidden: true,
  68. headerCounter: 0,
  69. // i8n text
  70. unlockText: 'Unlock',
  71. lockText: 'Lock',
  72. determineXTypeToCreate: function() {
  73. var me = this,
  74. typeToCreate;
  75. if (me.subGridXType) {
  76. typeToCreate = me.subGridXType;
  77. } else {
  78. var xtypes = this.getXTypes().split('/'),
  79. xtypesLn = xtypes.length,
  80. xtype = xtypes[xtypesLn - 1],
  81. superxtype = xtypes[xtypesLn - 2];
  82. if (superxtype !== 'tablepanel') {
  83. typeToCreate = superxtype;
  84. } else {
  85. typeToCreate = xtype;
  86. }
  87. }
  88. return typeToCreate;
  89. },
  90. // injectLockable will be invoked before initComponent's parent class implementation
  91. // is called, so throughout this method this. are configurations
  92. injectLockable: function() {
  93. // ensure lockable is set to true in the TablePanel
  94. this.lockable = true;
  95. // Instruct the TablePanel it already has a view and not to create one.
  96. // We are going to aggregate 2 copies of whatever TablePanel we are using
  97. this.hasView = true;
  98. var me = this,
  99. // xtype of this class, 'treepanel' or 'gridpanel'
  100. // (Note: this makes it a requirement that any subclass that wants to use lockable functionality needs to register an
  101. // alias.)
  102. xtype = me.determineXTypeToCreate(),
  103. // share the selection model
  104. selModel = me.getSelectionModel(),
  105. lockedGrid = {
  106. xtype: xtype,
  107. // Lockable does NOT support animations for Tree
  108. enableAnimations: false,
  109. scroll: false,
  110. scrollerOwner: false,
  111. selModel: selModel,
  112. border: false,
  113. cls: Ext.baseCSSPrefix + 'grid-inner-locked'
  114. },
  115. normalGrid = {
  116. xtype: xtype,
  117. enableAnimations: false,
  118. scrollerOwner: false,
  119. selModel: selModel,
  120. border: false
  121. },
  122. i = 0,
  123. columns,
  124. lockedHeaderCt,
  125. normalHeaderCt;
  126. me.addCls(Ext.baseCSSPrefix + 'grid-locked');
  127. // copy appropriate configurations to the respective
  128. // aggregated tablepanel instances and then delete them
  129. // from the master tablepanel.
  130. Ext.copyTo(normalGrid, me, me.normalCfgCopy);
  131. Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
  132. for (; i &lt; me.normalCfgCopy.length; i++) {
  133. delete me[me.normalCfgCopy[i]];
  134. }
  135. for (i = 0; i &lt; me.lockedCfgCopy.length; i++) {
  136. delete me[me.lockedCfgCopy[i]];
  137. }
  138. me.addEvents(
  139. <span id='Ext-grid-Lockable-event-lockcolumn'> /**
  140. </span> * @event lockcolumn
  141. * Fires when a column is locked.
  142. * @param {Ext.grid.Panel} this The gridpanel.
  143. * @param {Ext.grid.column.Column} column The column being locked.
  144. */
  145. 'lockcolumn',
  146. <span id='Ext-grid-Lockable-event-unlockcolumn'> /**
  147. </span> * @event unlockcolumn
  148. * Fires when a column is unlocked.
  149. * @param {Ext.grid.Panel} this The gridpanel.
  150. * @param {Ext.grid.column.Column} column The column being unlocked.
  151. */
  152. 'unlockcolumn'
  153. );
  154. me.addStateEvents(['lockcolumn', 'unlockcolumn']);
  155. me.lockedHeights = [];
  156. me.normalHeights = [];
  157. columns = me.processColumns(me.columns);
  158. lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0);
  159. lockedGrid.columns = columns.locked;
  160. normalGrid.columns = columns.normal;
  161. me.store = Ext.StoreManager.lookup(me.store);
  162. lockedGrid.store = me.store;
  163. normalGrid.store = me.store;
  164. // normal grid should flex the rest of the width
  165. normalGrid.flex = 1;
  166. lockedGrid.viewConfig = me.lockedViewConfig || {};
  167. lockedGrid.viewConfig.loadingUseMsg = false;
  168. normalGrid.viewConfig = me.normalViewConfig || {};
  169. Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
  170. Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
  171. me.normalGrid = Ext.ComponentManager.create(normalGrid);
  172. me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
  173. me.view = Ext.create('Ext.grid.LockingView', {
  174. locked: me.lockedGrid,
  175. normal: me.normalGrid,
  176. panel: me
  177. });
  178. if (me.syncRowHeight) {
  179. me.lockedGrid.getView().on({
  180. refresh: me.onLockedGridAfterRefresh,
  181. itemupdate: me.onLockedGridAfterUpdate,
  182. scope: me
  183. });
  184. me.normalGrid.getView().on({
  185. refresh: me.onNormalGridAfterRefresh,
  186. itemupdate: me.onNormalGridAfterUpdate,
  187. scope: me
  188. });
  189. }
  190. lockedHeaderCt = me.lockedGrid.headerCt;
  191. normalHeaderCt = me.normalGrid.headerCt;
  192. lockedHeaderCt.lockedCt = true;
  193. lockedHeaderCt.lockableInjected = true;
  194. normalHeaderCt.lockableInjected = true;
  195. lockedHeaderCt.on({
  196. columnshow: me.onLockedHeaderShow,
  197. columnhide: me.onLockedHeaderHide,
  198. columnmove: me.onLockedHeaderMove,
  199. sortchange: me.onLockedHeaderSortChange,
  200. columnresize: me.onLockedHeaderResize,
  201. scope: me
  202. });
  203. normalHeaderCt.on({
  204. columnmove: me.onNormalHeaderMove,
  205. sortchange: me.onNormalHeaderSortChange,
  206. scope: me
  207. });
  208. me.normalGrid.on({
  209. scrollershow: me.onScrollerShow,
  210. scrollerhide: me.onScrollerHide,
  211. scope: me
  212. });
  213. me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
  214. me.modifyHeaderCt();
  215. me.items = [me.lockedGrid, me.normalGrid];
  216. me.relayHeaderCtEvents(lockedHeaderCt);
  217. me.relayHeaderCtEvents(normalHeaderCt);
  218. me.layout = {
  219. type: 'hbox',
  220. align: 'stretch'
  221. };
  222. },
  223. processColumns: function(columns){
  224. // split apart normal and lockedWidths
  225. var i = 0,
  226. len = columns.length,
  227. lockedWidth = 1,
  228. lockedHeaders = [],
  229. normalHeaders = [],
  230. column;
  231. for (; i &lt; len; ++i) {
  232. column = columns[i];
  233. // mark the column as processed so that the locked attribute does not
  234. // trigger trying to aggregate the columns again.
  235. column.processed = true;
  236. if (column.locked) {
  237. // &lt;debug&gt;
  238. if (column.flex) {
  239. Ext.Error.raise(&quot;Columns which are locked do NOT support a flex width. You must set a width on the &quot; + columns[i].text + &quot;column.&quot;);
  240. }
  241. // &lt;/debug&gt;
  242. if (!column.hidden) {
  243. lockedWidth += column.width || Ext.grid.header.Container.prototype.defaultWidth;
  244. }
  245. lockedHeaders.push(column);
  246. } else {
  247. normalHeaders.push(column);
  248. }
  249. if (!column.headerId) {
  250. column.headerId = (column.initialConfig || column).id || ('L' + (++this.headerCounter));
  251. }
  252. }
  253. return {
  254. lockedWidth: lockedWidth,
  255. locked: lockedHeaders,
  256. normal: normalHeaders
  257. };
  258. },
  259. // create a new spacer after the table is refreshed
  260. onLockedGridAfterLayout: function() {
  261. var me = this,
  262. lockedView = me.lockedGrid.getView();
  263. lockedView.on({
  264. beforerefresh: me.destroySpacer,
  265. scope: me
  266. });
  267. },
  268. // trigger a pseudo refresh on the normal side
  269. onLockedHeaderMove: function() {
  270. if (this.syncRowHeight) {
  271. this.onNormalGridAfterRefresh();
  272. }
  273. },
  274. // trigger a pseudo refresh on the locked side
  275. onNormalHeaderMove: function() {
  276. if (this.syncRowHeight) {
  277. this.onLockedGridAfterRefresh();
  278. }
  279. },
  280. // create a spacer in lockedsection and store a reference
  281. // TODO: Should destroy before refreshing content
  282. getSpacerEl: function() {
  283. var me = this,
  284. w,
  285. view,
  286. el;
  287. if (!me.spacerEl) {
  288. // This affects scrolling all the way to the bottom of a locked grid
  289. // additional test, sort a column and make sure it synchronizes
  290. w = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0);
  291. view = me.lockedGrid.getView();
  292. el = view.el;
  293. me.spacerEl = Ext.DomHelper.append(el, {
  294. cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
  295. style: 'height: ' + w + 'px;'
  296. }, true);
  297. }
  298. return me.spacerEl;
  299. },
  300. destroySpacer: function() {
  301. var me = this;
  302. if (me.spacerEl) {
  303. me.spacerEl.destroy();
  304. delete me.spacerEl;
  305. }
  306. },
  307. // cache the heights of all locked rows and sync rowheights
  308. onLockedGridAfterRefresh: function() {
  309. var me = this,
  310. view = me.lockedGrid.getView(),
  311. el = view.el,
  312. rowEls = el.query(view.getItemSelector()),
  313. ln = rowEls.length,
  314. i = 0;
  315. // reset heights each time.
  316. me.lockedHeights = [];
  317. for (; i &lt; ln; i++) {
  318. me.lockedHeights[i] = rowEls[i].clientHeight;
  319. }
  320. me.syncRowHeights();
  321. },
  322. // cache the heights of all normal rows and sync rowheights
  323. onNormalGridAfterRefresh: function() {
  324. var me = this,
  325. view = me.normalGrid.getView(),
  326. el = view.el,
  327. rowEls = el.query(view.getItemSelector()),
  328. ln = rowEls.length,
  329. i = 0;
  330. // reset heights each time.
  331. me.normalHeights = [];
  332. for (; i &lt; ln; i++) {
  333. me.normalHeights[i] = rowEls[i].clientHeight;
  334. }
  335. me.syncRowHeights();
  336. },
  337. // rows can get bigger/smaller
  338. onLockedGridAfterUpdate: function(record, index, node) {
  339. this.lockedHeights[index] = node.clientHeight;
  340. this.syncRowHeights();
  341. },
  342. // rows can get bigger/smaller
  343. onNormalGridAfterUpdate: function(record, index, node) {
  344. this.normalHeights[index] = node.clientHeight;
  345. this.syncRowHeights();
  346. },
  347. // match the rowheights to the biggest rowheight on either
  348. // side
  349. syncRowHeights: function() {
  350. var me = this,
  351. lockedHeights = me.lockedHeights,
  352. normalHeights = me.normalHeights,
  353. calcHeights = [],
  354. ln = lockedHeights.length,
  355. i = 0,
  356. lockedView, normalView,
  357. lockedRowEls, normalRowEls,
  358. vertScroller = me.getVerticalScroller(),
  359. scrollTop;
  360. // ensure there are an equal num of locked and normal
  361. // rows before synchronization
  362. if (lockedHeights.length &amp;&amp; normalHeights.length) {
  363. lockedView = me.lockedGrid.getView();
  364. normalView = me.normalGrid.getView();
  365. lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
  366. normalRowEls = normalView.el.query(normalView.getItemSelector());
  367. // loop thru all of the heights and sync to the other side
  368. for (; i &lt; ln; i++) {
  369. // ensure both are numbers
  370. if (!isNaN(lockedHeights[i]) &amp;&amp; !isNaN(normalHeights[i])) {
  371. if (lockedHeights[i] &gt; normalHeights[i]) {
  372. Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
  373. } else if (lockedHeights[i] &lt; normalHeights[i]) {
  374. Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
  375. }
  376. }
  377. }
  378. // invalidate the scroller and sync the scrollers
  379. me.normalGrid.invalidateScroller();
  380. // synchronize the view with the scroller, if we have a virtualScrollTop
  381. // then the user is using a PagingScroller
  382. if (vertScroller &amp;&amp; vertScroller.setViewScrollTop) {
  383. vertScroller.setViewScrollTop(me.virtualScrollTop);
  384. } else {
  385. // We don't use setScrollTop here because if the scrollTop is
  386. // set to the exact same value some browsers won't fire the scroll
  387. // event. Instead, we directly set the scrollTop.
  388. scrollTop = normalView.el.dom.scrollTop;
  389. normalView.el.dom.scrollTop = scrollTop;
  390. lockedView.el.dom.scrollTop = scrollTop;
  391. }
  392. // reset the heights
  393. me.lockedHeights = [];
  394. me.normalHeights = [];
  395. }
  396. },
  397. // track when scroller is shown
  398. onScrollerShow: function(scroller, direction) {
  399. if (direction === 'horizontal') {
  400. this.spacerHidden = false;
  401. this.getSpacerEl().removeCls(Ext.baseCSSPrefix + 'hidden');
  402. }
  403. },
  404. // track when scroller is hidden
  405. onScrollerHide: function(scroller, direction) {
  406. if (direction === 'horizontal') {
  407. this.spacerHidden = true;
  408. if (this.spacerEl) {
  409. this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
  410. }
  411. }
  412. },
  413. // inject Lock and Unlock text
  414. modifyHeaderCt: function() {
  415. var me = this;
  416. me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
  417. me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
  418. },
  419. onUnlockMenuClick: function() {
  420. this.unlock();
  421. },
  422. onLockMenuClick: function() {
  423. this.lock();
  424. },
  425. getMenuItems: function(locked) {
  426. var me = this,
  427. unlockText = me.unlockText,
  428. lockText = me.lockText,
  429. unlockCls = Ext.baseCSSPrefix + 'hmenu-unlock',
  430. lockCls = Ext.baseCSSPrefix + 'hmenu-lock',
  431. unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
  432. lockHandler = Ext.Function.bind(me.onLockMenuClick, me);
  433. // runs in the scope of headerCt
  434. return function() {
  435. var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
  436. o.push('-',{
  437. cls: unlockCls,
  438. text: unlockText,
  439. handler: unlockHandler,
  440. disabled: !locked
  441. });
  442. o.push({
  443. cls: lockCls,
  444. text: lockText,
  445. handler: lockHandler,
  446. disabled: locked
  447. });
  448. return o;
  449. };
  450. },
  451. // going from unlocked section to locked
  452. <span id='Ext-grid-Lockable-method-lock'> /**
  453. </span> * Locks the activeHeader as determined by which menu is open OR a header
  454. * as specified.
  455. * @param {Ext.grid.column.Column} header (Optional) Header to unlock from the locked section. Defaults to the header which has the menu open currently.
  456. * @param {Number} toIdx (Optional) The index to move the unlocked header to. Defaults to appending as the last item.
  457. * @private
  458. */
  459. lock: function(activeHd, toIdx) {
  460. var me = this,
  461. normalGrid = me.normalGrid,
  462. lockedGrid = me.lockedGrid,
  463. normalHCt = normalGrid.headerCt,
  464. lockedHCt = lockedGrid.headerCt;
  465. activeHd = activeHd || normalHCt.getMenu().activeHeader;
  466. // if column was previously flexed, get/set current width
  467. // and remove the flex
  468. if (activeHd.flex) {
  469. activeHd.width = activeHd.getWidth();
  470. delete activeHd.flex;
  471. }
  472. normalHCt.remove(activeHd, false);
  473. lockedHCt.suspendLayout = true;
  474. activeHd.locked = true;
  475. if (Ext.isDefined(toIdx)) {
  476. lockedHCt.insert(toIdx, activeHd);
  477. } else {
  478. lockedHCt.add(activeHd);
  479. }
  480. lockedHCt.suspendLayout = false;
  481. me.syncLockedSection();
  482. me.fireEvent('lockcolumn', me, activeHd);
  483. },
  484. syncLockedSection: function() {
  485. var me = this;
  486. me.syncLockedWidth();
  487. me.lockedGrid.getView().refresh();
  488. me.normalGrid.getView().refresh();
  489. },
  490. // adjust the locked section to the width of its respective
  491. // headerCt
  492. syncLockedWidth: function() {
  493. var me = this,
  494. width = me.lockedGrid.headerCt.getFullWidth(true);
  495. me.lockedGrid.setWidth(width+1); // +1 for border pixel
  496. me.doComponentLayout();
  497. },
  498. onLockedHeaderResize: function() {
  499. this.syncLockedWidth();
  500. },
  501. onLockedHeaderHide: function() {
  502. this.syncLockedWidth();
  503. },
  504. onLockedHeaderShow: function() {
  505. this.syncLockedWidth();
  506. },
  507. onLockedHeaderSortChange: function(headerCt, header, sortState) {
  508. if (sortState) {
  509. // no real header, and silence the event so we dont get into an
  510. // infinite loop
  511. this.normalGrid.headerCt.clearOtherSortStates(null, true);
  512. }
  513. },
  514. onNormalHeaderSortChange: function(headerCt, header, sortState) {
  515. if (sortState) {
  516. // no real header, and silence the event so we dont get into an
  517. // infinite loop
  518. this.lockedGrid.headerCt.clearOtherSortStates(null, true);
  519. }
  520. },
  521. // going from locked section to unlocked
  522. <span id='Ext-grid-Lockable-method-unlock'> /**
  523. </span> * Unlocks the activeHeader as determined by which menu is open OR a header
  524. * as specified.
  525. * @param {Ext.grid.column.Column} header (Optional) Header to unlock from the locked section. Defaults to the header which has the menu open currently.
  526. * @param {Number} toIdx (Optional) The index to move the unlocked header to. Defaults to 0.
  527. * @private
  528. */
  529. unlock: function(activeHd, toIdx) {
  530. var me = this,
  531. normalGrid = me.normalGrid,
  532. lockedGrid = me.lockedGrid,
  533. normalHCt = normalGrid.headerCt,
  534. lockedHCt = lockedGrid.headerCt;
  535. if (!Ext.isDefined(toIdx)) {
  536. toIdx = 0;
  537. }
  538. activeHd = activeHd || lockedHCt.getMenu().activeHeader;
  539. lockedHCt.remove(activeHd, false);
  540. me.syncLockedWidth();
  541. me.lockedGrid.getView().refresh();
  542. activeHd.locked = false;
  543. normalHCt.insert(toIdx, activeHd);
  544. me.normalGrid.getView().refresh();
  545. me.fireEvent('unlockcolumn', me, activeHd);
  546. },
  547. applyColumnsState: function (columns) {
  548. var me = this,
  549. lockedGrid = me.lockedGrid,
  550. lockedHeaderCt = lockedGrid.headerCt,
  551. normalHeaderCt = me.normalGrid.headerCt,
  552. lockedCols = lockedHeaderCt.items,
  553. normalCols = normalHeaderCt.items,
  554. existing,
  555. locked = [],
  556. normal = [],
  557. lockedDefault,
  558. lockedWidth = 1;
  559. Ext.each(columns, function (col) {
  560. function matches (item) {
  561. return item.headerId == col.id;
  562. }
  563. lockedDefault = true;
  564. if (!(existing = lockedCols.findBy(matches))) {
  565. existing = normalCols.findBy(matches);
  566. lockedDefault = false;
  567. }
  568. if (existing) {
  569. if (existing.applyColumnState) {
  570. existing.applyColumnState(col);
  571. }
  572. if (!Ext.isDefined(existing.locked)) {
  573. existing.locked = lockedDefault;
  574. }
  575. if (existing.locked) {
  576. locked.push(existing);
  577. if (!existing.hidden &amp;&amp; Ext.isNumber(existing.width)) {
  578. lockedWidth += existing.width;
  579. }
  580. } else {
  581. normal.push(existing);
  582. }
  583. }
  584. });
  585. // state and config must have the same columns (compare counts for now):
  586. if (locked.length + normal.length == lockedCols.getCount() + normalCols.getCount()) {
  587. lockedHeaderCt.removeAll(false);
  588. normalHeaderCt.removeAll(false);
  589. lockedHeaderCt.add(locked);
  590. normalHeaderCt.add(normal);
  591. lockedGrid.setWidth(lockedWidth);
  592. }
  593. },
  594. getColumnsState: function () {
  595. var me = this,
  596. locked = me.lockedGrid.headerCt.getColumnsState(),
  597. normal = me.normalGrid.headerCt.getColumnsState();
  598. return locked.concat(normal);
  599. },
  600. // we want to totally override the reconfigure behaviour here, since we're creating 2 sub-grids
  601. reconfigureLockable: function(store, columns) {
  602. var me = this,
  603. lockedGrid = me.lockedGrid,
  604. normalGrid = me.normalGrid;
  605. if (columns) {
  606. lockedGrid.headerCt.suspendLayout = true;
  607. normalGrid.headerCt.suspendLayout = true;
  608. lockedGrid.headerCt.removeAll();
  609. normalGrid.headerCt.removeAll();
  610. columns = me.processColumns(columns);
  611. lockedGrid.setWidth(columns.lockedWidth);
  612. lockedGrid.headerCt.add(columns.locked);
  613. normalGrid.headerCt.add(columns.normal);
  614. }
  615. if (store) {
  616. store = Ext.data.StoreManager.lookup(store);
  617. me.store = store;
  618. lockedGrid.bindStore(store);
  619. normalGrid.bindStore(store);
  620. } else {
  621. lockedGrid.getView().refresh();
  622. normalGrid.getView().refresh();
  623. }
  624. if (columns) {
  625. lockedGrid.headerCt.suspendLayout = false;
  626. normalGrid.headerCt.suspendLayout = false;
  627. lockedGrid.headerCt.forceComponentLayout();
  628. normalGrid.headerCt.forceComponentLayout();
  629. }
  630. }
  631. });
  632. </pre>
  633. </body>
  634. </html>