whole_func_string: function() {
          // ensure lockable is set to true in the TablePanel
          this.lockable = true;
          // Instruct the TablePanel it already has a view and not to create one.
          // We are going to aggregate 2 copies of whatever TablePanel we are using
          this.hasView = true;
  
          var me = this,
              scrollbarHeight = Ext.getScrollbarSize().width,
              store = me.store = Ext.StoreManager.lookup(me.store),
  
              // share the selection model
              selModel = me.getSelectionModel(),
  
              // Hash of {lockedFeatures:[],normalFeatures:[]}
              allFeatures,
  
              // Hash of {topPlugins:[],lockedPlugins:[],normalPlugins:[]}
              allPlugins,
  
              lockedGrid,
              normalGrid,
              i,
              columns,
              lockedHeaderCt,
              normalHeaderCt,
              lockedView,
              normalView,
              listeners;
  
          allFeatures = me.constructLockableFeatures();
  
          // This is just a "shell" Panel which acts as a Container for the two grids and must not use the features
          if (me.features) {
              me.features = null;
          }
  
          // Distribute plugins to whichever Component needs them
          allPlugins = me.constructLockablePlugins();
          me.plugins = allPlugins.topPlugins;
  
          lockedGrid = Ext.apply({
              id: me.id + '-locked',
              ownerLockable: me,
              xtype: me.determineXTypeToCreate(true),
              store: store,
              scrollerOwner: false,
              // Lockable does NOT support animations for Tree
              // Because the right side is just a grid, and the grid view doen't animate bulk insertions/removals
              animate: false,
              // If the OS does not show a space-taking scrollbar, the locked view can be overflow-y:auto
              scroll: scrollbarHeight ? false : 'vertical',
              selModel: selModel,
              border: false,
              cls: me.lockedGridCls,
              isLayoutRoot: function() {
                  return false;
              },
              features: allFeatures.lockedFeatures,
              plugins: allPlugins.lockedPlugins
          }, me.lockedGridConfig);
  
          normalGrid = Ext.apply({
              id: me.id + '-normal',
              ownerLockable: me,
              xtype: me.determineXTypeToCreate(),
              store: store,
              scrollerOwner: false,
              selModel: selModel,
              border: false,
              isLayoutRoot: function() {
                  return false;
              },
              features: allFeatures.normalFeatures,
              plugins: allPlugins.normalPlugins
          }, me.normalGridConfig);
  
          me.addCls(Ext.baseCSSPrefix + 'grid-locked');
  
          // Copy appropriate configurations to the respective aggregated tablepanel instances.
          // Pass 4th param true to NOT exclude those settings on our prototype.
          // Delete them from the master tablepanel.
          Ext.copyTo(normalGrid, me, me.bothCfgCopy, true);
          Ext.copyTo(lockedGrid, me, me.bothCfgCopy, true);
          Ext.copyTo(normalGrid, me, me.normalCfgCopy, true);
          Ext.copyTo(lockedGrid, me, me.lockedCfgCopy, true);
          for (i = 0; i < me.normalCfgCopy.length; i++) {
              delete me[me.normalCfgCopy[i]];
          }
          for (i = 0; i < me.lockedCfgCopy.length; i++) {
              delete me[me.lockedCfgCopy[i]];
          }
  
          me.addEvents(
              /**
               * @event processcolumns
               * Fires when the configured (or **reconfigured**) column set is split into two depending on the {@link Ext.grid.column.Column#locked locked} flag.
               * @param {Ext.grid.column.Column[]} lockedColumns The locked columns.
               * @param {Ext.grid.column.Column[]} normalColumns The normal columns.
               */
              'processcolumns',
  
              /**
               * @event lockcolumn
               * Fires when a column is locked.
               * @param {Ext.grid.Panel} this The gridpanel.
               * @param {Ext.grid.column.Column} column The column being locked.
               */
              'lockcolumn',
  
              /**
               * @event unlockcolumn
               * Fires when a column is unlocked.
               * @param {Ext.grid.Panel} this The gridpanel.
               * @param {Ext.grid.column.Column} column The column being unlocked.
               */
              'unlockcolumn'
          );
  
          me.addStateEvents(['lockcolumn', 'unlockcolumn']);
  
          columns = me.processColumns(me.columns);
  
          // Locked grid has a right border. Locked grid must shrinkwrap columns with no horiontal scroll, so
          // we must increment by the border width: 1px. TODO: Use shrinkWrapDock on the locked grid when it works.
          lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0) + (columns.locked.items.length ? 1 : 0);
          lockedGrid.columns = columns.locked;
          normalGrid.columns = columns.normal;
  
          // normal grid should flex the rest of the width
          normalGrid.flex = 1;
          lockedGrid.viewConfig = me.lockedViewConfig || {};
          lockedGrid.viewConfig.loadingUseMsg = false;
          lockedGrid.viewConfig.loadMask = false;
  
          // Padding below locked grid body only if there are scrollbars on this system
          // This takes the place of any spacer element.
          // Important: The height has to be postprocessed after render to override
          // the inline border styles injected by automatic component border settings.
          if (scrollbarHeight) {
              lockedGrid.viewConfig.style = 'border-bottom:' + scrollbarHeight +
                  'px solid #f6f6f6;' + (lockedGrid.viewConfig.style || '');
          }
  
          normalGrid.viewConfig = me.normalViewConfig || {};
          normalGrid.viewConfig.loadMask = false;
  
          //<debug>
          if (me.viewConfig && me.viewConfig.id) {
              Ext.log.warn('id specified on Lockable viewConfig, it will be shared between both views: "' + me.viewConfig.id + '"');
          }
          //</debug>
  
          Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
          Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
  
          me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
  
          if (me.isTree) {
              // Tree must not animate because the partner grid is unable to animate
              me.lockedGrid.getView().animate = false;
  
              // When this is a locked tree, the normal side is just a gridpanel, so needs the flat NodeStore
              normalGrid.store = me.lockedGrid.view.store;
  
              // To stay in sync with the tree side; trees don't use deferInitialRefresh by default. Overrideable by user config.
              normalGrid.deferRowRender = false;
  
              // Match configs between sides
              normalGrid.viewConfig.stripeRows = me.lockedGrid.view.stripeRows;
              normalGrid.rowLines = me.lockedGrid.rowLines;
          }
  
          // Set up a bidirectional relationship between the two sides of the locked view
          lockedView = me.lockedGrid.getView();
          normalGrid.viewConfig.lockingPartner = lockedView;
          me.normalGrid = Ext.ComponentManager.create(normalGrid);
          lockedView.lockingPartner = normalView = me.normalGrid.getView();
  
          me.view = new Ext.grid.locking.View({
              loadingText: normalView.loadingText,
              loadingCls: normalView.loadingCls,
              loadingUseMsg: normalView.loadingUseMsg,
              loadMask: me.loadMask !== false,
              locked: me.lockedGrid,
              normal: me.normalGrid,
              panel: me
          });
  
          // Set up listeners for the locked view. If its SelModel ever scrolls it, the normal view must sync
          listeners = {
              scroll: {
                  fn: me.onLockedViewScroll,
                  element: 'el',
                  scope: me
              }
          };
  
          // If there are system scrollbars, we have to monitor the mousewheel and fake a scroll
          // Also we need to postprocess the border width because of inline border setting styles.
          // The locked grid needs a bottom border to match with any scrollbar present in the normal grid .
          // Keep locked section's bottom border width synched
          if (scrollbarHeight) {
              me.lockedGrid.on({
                  afterlayout: me.afterLockedViewLayout,
                  scope: me
              });
  
              // Ensure the overflow flags have been calculated from the various overflow configs
              lockedView.getOverflowStyle();
  
              // If the locked view is configured to scoll vertically, force the columns to fit initially.
              if (lockedView.scrollFlags.y) {
                  me.lockedGrid.headerCt.forceFit = true;
              }
              // If the locked view is not configured to scoll vertically, we must listen for mousewheel events to scroll it.
              else {
                  listeners.mousewheel = {
                      fn: me.onLockedViewMouseWheel,
                      element: 'el',
                      scope: me
                  };
              }
          }
          lockedView.on(listeners);
  
          // Set up listeners for the normal view
          listeners = {
              scroll: {
                  fn: me.onNormalViewScroll,
                  element: 'el',
                  scope: me
              },
              scope: me
          };
          normalView.on(listeners);
  
          lockedHeaderCt = me.lockedGrid.headerCt;
          normalHeaderCt = me.normalGrid.headerCt;
  
          // The top grid, and the LockingView both need to have a headerCt which is usable.
          // It is part of their private API that framework code uses when dealing with a grid or grid view
          me.headerCt = me.view.headerCt = new Ext.grid.locking.HeaderContainer(this);
  
          lockedHeaderCt.lockedCt = true;
          lockedHeaderCt.lockableInjected = true;
          normalHeaderCt.lockableInjected = true;
  
          lockedHeaderCt.on({
              // buffer to wait until multiple adds have fired
              add: {
                  buffer: 1,
                  scope: me,
                  fn: me.onLockedHeaderAdd
              },
              columnshow: me.onLockedHeaderShow,
              columnhide: me.onLockedHeaderHide,
              sortchange: me.onLockedHeaderSortChange,
              columnresize: me.onLockedHeaderResize,
              scope: me
          });
  
          normalHeaderCt.on({
              sortchange: me.onNormalHeaderSortChange,
              scope: me
          });
  
          me.modifyHeaderCt();
          me.items = [me.lockedGrid, me.normalGrid];
  
          me.relayHeaderCtEvents(lockedHeaderCt);
          me.relayHeaderCtEvents(normalHeaderCt);
  
          // The top level Lockable container does not get bound to the store, so we need to programatically add the relayer so that
          // The filterchange state event is fired.
          me.storeRelayers = me.relayEvents(store, [
              /**
               * @event filterchange
               * @inheritdoc Ext.data.Store#filterchange
               */
              'filterchange'
          ]);
  
          me.layout = {
              type: 'hbox',
              align: 'stretch'
          };
      }
func_code_string: function() {
          // ensure lockable is set to true in the TablePanel
          this.lockable = true;
          // Instruct the TablePanel it already has a view and not to create one.
          // We are going to aggregate 2 copies of whatever TablePanel we are using
          this.hasView = true;
  
          var me = this,
              scrollbarHeight = Ext.getScrollbarSize().width,
              store = me.store = Ext.StoreManager.lookup(me.store),
  
              // share the selection model
              selModel = me.getSelectionModel(),
  
              // Hash of {lockedFeatures:[],normalFeatures:[]}
              allFeatures,
  
              // Hash of {topPlugins:[],lockedPlugins:[],normalPlugins:[]}
              allPlugins,
  
              lockedGrid,
              normalGrid,
              i,
              columns,
              lockedHeaderCt,
              normalHeaderCt,
              lockedView,
              normalView,
              listeners;
  
          allFeatures = me.constructLockableFeatures();
  
          // This is just a "shell" Panel which acts as a Container for the two grids and must not use the features
          if (me.features) {
              me.features = null;
          }
  
          // Distribute plugins to whichever Component needs them
          allPlugins = me.constructLockablePlugins();
          me.plugins = allPlugins.topPlugins;
  
          lockedGrid = Ext.apply({
              id: me.id + '-locked',
              ownerLockable: me,
              xtype: me.determineXTypeToCreate(true),
              store: store,
              scrollerOwner: false,
              // Lockable does NOT support animations for Tree
              // Because the right side is just a grid, and the grid view doen't animate bulk insertions/removals
              animate: false,
              // If the OS does not show a space-taking scrollbar, the locked view can be overflow-y:auto
              scroll: scrollbarHeight ? false : 'vertical',
              selModel: selModel,
              border: false,
              cls: me.lockedGridCls,
              isLayoutRoot: function() {
                  return false;
              },
              features: allFeatures.lockedFeatures,
              plugins: allPlugins.lockedPlugins
          }, me.lockedGridConfig);
  
          normalGrid = Ext.apply({
              id: me.id + '-normal',
              ownerLockable: me,
              xtype: me.determineXTypeToCreate(),
              store: store,
              scrollerOwner: false,
              selModel: selModel,
              border: false,
              isLayoutRoot: function() {
                  return false;
              },
              features: allFeatures.normalFeatures,
              plugins: allPlugins.normalPlugins
          }, me.normalGridConfig);
  
          me.addCls(Ext.baseCSSPrefix + 'grid-locked');
  
          // Copy appropriate configurations to the respective aggregated tablepanel instances.
          // Pass 4th param true to NOT exclude those settings on our prototype.
          // Delete them from the master tablepanel.
          Ext.copyTo(normalGrid, me, me.bothCfgCopy, true);
          Ext.copyTo(lockedGrid, me, me.bothCfgCopy, true);
          Ext.copyTo(normalGrid, me, me.normalCfgCopy, true);
          Ext.copyTo(lockedGrid, me, me.lockedCfgCopy, true);
          for (i = 0; i < me.normalCfgCopy.length; i++) {
              delete me[me.normalCfgCopy[i]];
          }
          for (i = 0; i < me.lockedCfgCopy.length; i++) {
              delete me[me.lockedCfgCopy[i]];
          }
  
          me.addEvents(
              /**
               * @event processcolumns
               * Fires when the configured (or **reconfigured**) column set is split into two depending on the {@link Ext.grid.column.Column#locked locked} flag.
               * @param {Ext.grid.column.Column[]} lockedColumns The locked columns.
               * @param {Ext.grid.column.Column[]} normalColumns The normal columns.
               */
              'processcolumns',
  
              /**
               * @event lockcolumn
               * Fires when a column is locked.
               * @param {Ext.grid.Panel} this The gridpanel.
               * @param {Ext.grid.column.Column} column The column being locked.
               */
              'lockcolumn',
  
              /**
               * @event unlockcolumn
               * Fires when a column is unlocked.
               * @param {Ext.grid.Panel} this The gridpanel.
               * @param {Ext.grid.column.Column} column The column being unlocked.
               */
              'unlockcolumn'
          );
  
          me.addStateEvents(['lockcolumn', 'unlockcolumn']);
  
          columns = me.processColumns(me.columns);
  
          // Locked grid has a right border. Locked grid must shrinkwrap columns with no horiontal scroll, so
          // we must increment by the border width: 1px. TODO: Use shrinkWrapDock on the locked grid when it works.
          lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0) + (columns.locked.items.length ? 1 : 0);
          lockedGrid.columns = columns.locked;
          normalGrid.columns = columns.normal;
  
          // normal grid should flex the rest of the width
          normalGrid.flex = 1;
          lockedGrid.viewConfig = me.lockedViewConfig || {};
          lockedGrid.viewConfig.loadingUseMsg = false;
          lockedGrid.viewConfig.loadMask = false;
  
          // Padding below locked grid body only if there are scrollbars on this system
          // This takes the place of any spacer element.
          // Important: The height has to be postprocessed after render to override
          // the inline border styles injected by automatic component border settings.
          if (scrollbarHeight) {
              lockedGrid.viewConfig.style = 'border-bottom:' + scrollbarHeight +
                  'px solid #f6f6f6;' + (lockedGrid.viewConfig.style || '');
          }
  
          normalGrid.viewConfig = me.normalViewConfig || {};
          normalGrid.viewConfig.loadMask = false;
  
          //<debug>
          if (me.viewConfig && me.viewConfig.id) {
              Ext.log.warn('id specified on Lockable viewConfig, it will be shared between both views: "' + me.viewConfig.id + '"');
          }
          //</debug>
  
          Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
          Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
  
          me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
  
          if (me.isTree) {
              // Tree must not animate because the partner grid is unable to animate
              me.lockedGrid.getView().animate = false;
  
              // When this is a locked tree, the normal side is just a gridpanel, so needs the flat NodeStore
              normalGrid.store = me.lockedGrid.view.store;
  
              // To stay in sync with the tree side; trees don't use deferInitialRefresh by default. Overrideable by user config.
              normalGrid.deferRowRender = false;
  
              // Match configs between sides
              normalGrid.viewConfig.stripeRows = me.lockedGrid.view.stripeRows;
              normalGrid.rowLines = me.lockedGrid.rowLines;
          }
  
          // Set up a bidirectional relationship between the two sides of the locked view
          lockedView = me.lockedGrid.getView();
          normalGrid.viewConfig.lockingPartner = lockedView;
          me.normalGrid = Ext.ComponentManager.create(normalGrid);
          lockedView.lockingPartner = normalView = me.normalGrid.getView();
  
          me.view = new Ext.grid.locking.View({
              loadingText: normalView.loadingText,
              loadingCls: normalView.loadingCls,
              loadingUseMsg: normalView.loadingUseMsg,
              loadMask: me.loadMask !== false,
              locked: me.lockedGrid,
              normal: me.normalGrid,
              panel: me
          });
  
          // Set up listeners for the locked view. If its SelModel ever scrolls it, the normal view must sync
          listeners = {
              scroll: {
                  fn: me.onLockedViewScroll,
                  element: 'el',
                  scope: me
              }
          };
  
          // If there are system scrollbars, we have to monitor the mousewheel and fake a scroll
          // Also we need to postprocess the border width because of inline border setting styles.
          // The locked grid needs a bottom border to match with any scrollbar present in the normal grid .
          // Keep locked section's bottom border width synched
          if (scrollbarHeight) {
              me.lockedGrid.on({
                  afterlayout: me.afterLockedViewLayout,
                  scope: me
              });
  
              // Ensure the overflow flags have been calculated from the various overflow configs
              lockedView.getOverflowStyle();
  
              // If the locked view is configured to scoll vertically, force the columns to fit initially.
              if (lockedView.scrollFlags.y) {
                  me.lockedGrid.headerCt.forceFit = true;
              }
              // If the locked view is not configured to scoll vertically, we must listen for mousewheel events to scroll it.
              else {
                  listeners.mousewheel = {
                      fn: me.onLockedViewMouseWheel,
                      element: 'el',
                      scope: me
                  };
              }
          }
          lockedView.on(listeners);
  
          // Set up listeners for the normal view
          listeners = {
              scroll: {
                  fn: me.onNormalViewScroll,
                  element: 'el',
                  scope: me
              },
              scope: me
          };
          normalView.on(listeners);
  
          lockedHeaderCt = me.lockedGrid.headerCt;
          normalHeaderCt = me.normalGrid.headerCt;
  
          // The top grid, and the LockingView both need to have a headerCt which is usable.
          // It is part of their private API that framework code uses when dealing with a grid or grid view
          me.headerCt = me.view.headerCt = new Ext.grid.locking.HeaderContainer(this);
  
          lockedHeaderCt.lockedCt = true;
          lockedHeaderCt.lockableInjected = true;
          normalHeaderCt.lockableInjected = true;
  
          lockedHeaderCt.on({
              // buffer to wait until multiple adds have fired
              add: {
                  buffer: 1,
                  scope: me,
                  fn: me.onLockedHeaderAdd
              },
              columnshow: me.onLockedHeaderShow,
              columnhide: me.onLockedHeaderHide,
              sortchange: me.onLockedHeaderSortChange,
              columnresize: me.onLockedHeaderResize,
              scope: me
          });
  
          normalHeaderCt.on({
              sortchange: me.onNormalHeaderSortChange,
              scope: me
          });
  
          me.modifyHeaderCt();
          me.items = [me.lockedGrid, me.normalGrid];
  
          me.relayHeaderCtEvents(lockedHeaderCt);
          me.relayHeaderCtEvents(normalHeaderCt);
  
          // The top level Lockable container does not get bound to the store, so we need to programatically add the relayer so that
          // The filterchange state event is fired.
          me.storeRelayers = me.relayEvents(store, [
              /**
               * @event filterchange
               * @inheritdoc Ext.data.Store#filterchange
               */
              'filterchange'
          ]);
  
          me.layout = {
              type: 'hbox',
              align: 'stretch'
          };
      }
func_documentation_string: injectLockable will be invoked before initComponent's parent class implementation is called, so throughout this method this. are configurations