/*
 * ColumnLock v1.7.1 for Ext 3
 */
Ext.ns('Ext.ux.grid');

Ext.ux.grid.LockingGridPanel = Ext.extend(Ext.grid.GridPanel,  {
	initComponent : function(){
		if(!this.cm && !this.colModel && Ext.isArray(this.columns)){
			this.colModel = new Ext.ux.grid.LockingColumnModel(this.columns);
			delete this.columns;
		}
		Ext.ux.grid.LockingGridPanel.superclass.initComponent.call(this);
	},
	getView : function(){
		if(!this.view){
			this.view = new Ext.ux.grid.LockingGridView(this.viewConfig);
		}
		return this.view;
	}
});

Ext.ux.grid.LockingEditorGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
	initComponent : function(){
		if(!this.cm && !this.colModel && Ext.isArray(this.columns)){
			this.colModel = new Ext.ux.grid.LockingColumnModel(this.columns);
			delete this.columns;
		}
		Ext.ux.grid.LockingEditorGridPanel.superclass.initComponent.call(this);
	},
	getView : function(){
		if(!this.view){
			this.view = new Ext.ux.grid.LockingGridView(this.viewConfig);
		}
		return this.view;
	}
});

// Added after Ext 3.0.0
Ext.applyIf(Ext.grid.GridView.prototype, {
	getScrollOffset: function(){
		return Ext.isDefined(this.scrollOffset) ? this.scrollOffset : Ext.getScrollBarWidth();
	}
});

Ext.ux.grid.LockingGridView = Ext.extend(Ext.grid.GridView, {
	lockText : 'Lock',
	unlockText : 'Unlock',
	rowBorderWidth : 1,
	lockedBorderWidth : 1,
	initTemplates : function(){
		var ts = this.templates || {};
		if(!ts.master){
			ts.master = new Ext.Template(
				'<div class="x-grid3" hidefocus="true">',
					'<div class="x-grid3-locked">',
						'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{lstyle}">{lockedHeader}</div></div><div class="x-clear"></div></div>',
						'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{lstyle}">{lockedBody}</div><div class="x-grid3-scroll-spacer"></div></div>',
					'</div>',
					'<div class="x-grid3-viewport x-grid3-unlocked">',
						'<div class="x-grid3-header"><div class="x-grid3-header-inner"><div class="x-grid3-header-offset" style="{ostyle}">{header}</div></div><div class="x-clear"></div></div>',
						'<div class="x-grid3-scroller"><div class="x-grid3-body" style="{bstyle}">{body}</div><a href="#" class="x-grid3-focus" tabIndex="-1"></a></div>',
					'</div>',
					'<div class="x-grid3-resize-marker">&#160;</div>',
					'<div class="x-grid3-resize-proxy">&#160;</div>',
				'</div>'
			);
		}
		this.templates = ts;
		Ext.ux.grid.LockingGridView.superclass.initTemplates.call(this);
	},
	getEditorParent : function(ed){
		return this.el.dom;
	},
	initElements : function(){
		var E = Ext.Element;
		var el = this.grid.getGridEl().dom.firstChild;
		var cs = el.childNodes;
		this.el = new E(el);
		this.lockedWrap = new E(cs[0]);
		this.lockedHd = new E(this.lockedWrap.dom.firstChild);
		this.lockedInnerHd = this.lockedHd.dom.firstChild;
		this.lockedScroller = new E(this.lockedWrap.dom.childNodes[1]);
		this.lockedBody = new E(this.lockedScroller.dom.firstChild);
		this.mainWrap = new E(cs[1]);
		this.mainHd = new E(this.mainWrap.dom.firstChild);
		if(this.grid.hideHeaders){
			this.lockedHd.setDisplayed(false);
			this.mainHd.setDisplayed(false);
		}
		this.innerHd = this.mainHd.dom.firstChild;
		this.scroller = new E(this.mainWrap.dom.childNodes[1]);
		if(this.forceFit){
			this.scroller.setStyle('overflow-x', 'hidden');
		}
		this.mainBody = new E(this.scroller.dom.firstChild);
		this.focusEl = new E(this.scroller.dom.childNodes[1]);
		this.focusEl.swallowEvent('click', true);
		this.resizeMarker = new E(cs[2]);
		this.resizeProxy = new E(cs[3]);
	},
	getLockedRows : function(){
		return this.hasRows() ? this.lockedBody.dom.childNodes : [];
	},
	getLockedRow : function(row){
		return this.getLockedRows()[row];
	},
	getCell : function(row, col){
		var llen = this.cm.getLockedCount();
		if(col < llen){
			return this.getLockedRow(row).getElementsByTagName('td')[col];
		}
		return Ext.ux.grid.LockingGridView.superclass.getCell.call(this, row, col - llen);
	},
	getHeaderCell : function(index){
		var llen = this.cm.getLockedCount();
		if(index < llen){
			return this.lockedHd.dom.getElementsByTagName('td')[index];
		}
		return Ext.ux.grid.LockingGridView.superclass.getHeaderCell.call(this, index - llen);
	},
	addRowClass : function(row, cls){
		var r = this.getLockedRow(row);
		if(r){
			this.fly(r).addClass(cls);
		}
		Ext.ux.grid.LockingGridView.superclass.addRowClass.call(this, row, cls);
	},
	removeRowClass : function(row, cls){
		var r = this.getLockedRow(row);
		if(r){
			this.fly(r).removeClass(cls);
		}
		Ext.ux.grid.LockingGridView.superclass.removeRowClass.call(this, row, cls);
	},
	removeRow : function(row) {
		Ext.removeNode(this.getLockedRow(row));
		Ext.ux.grid.LockingGridView.superclass.removeRow.call(this, row);
	},
	removeRows : function(firstRow, lastRow){
		var bd = this.lockedBody.dom;
		for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
			Ext.removeNode(bd.childNodes[firstRow]);
		}
		Ext.ux.grid.LockingGridView.superclass.removeRows.call(this, firstRow, lastRow);
	},
	syncScroll : function(e){
		var mb = this.scroller.dom;
		this.lockedScroller.dom.scrollTop = mb.scrollTop;
		Ext.ux.grid.LockingGridView.superclass.syncScroll.call(this, e);
	},
	updateSortIcon : function(col, dir){
		var sc = this.sortClasses,
			lhds = this.lockedHd.select('td').removeClass(sc),
			hds = this.mainHd.select('td').removeClass(sc),
			llen = this.cm.getLockedCount();
		if(col < llen){
			lhds.item(col).addClass(sc[dir == 'DESC' ? 1 : 0]);
		}else{
			hds.item(col - llen).addClass(sc[dir == 'DESC' ? 1 : 0]);
		}
	},
	updateAllColumnWidths : function(){
		var tw = this.getTotalWidth(),
			clen = this.cm.getColumnCount(),
			lw = this.getLockedWidth(),
			llen = this.cm.getLockedCount(),
			ws = [], len, i;
		this.updateLockedWidth();
		for(i = 0; i < clen; i++){
			ws[i] = this.getColumnWidth(i);
			var hd = this.getHeaderCell(i);
			hd.style.width = ws[i];
		}
		var lns = this.getLockedRows(), ns = this.getRows(), row, trow, j;
		for(i = 0, len = ns.length; i < len; i++){
			row = lns[i];
			row.style.width = lw;
			if(row.firstChild){
				row.firstChild.style.width = lw;
				trow = row.firstChild.rows[0];
				for (j = 0; j < llen; j++) {
				   trow.childNodes[j].style.width = ws[j];
				}
			}
			row = ns[i];
			row.style.width = tw;
			if(row.firstChild){
				row.firstChild.style.width = tw;
				trow = row.firstChild.rows[0];
				for (j = llen; j < clen; j++) {
				   trow.childNodes[j - llen].style.width = ws[j];
				}
			}
		}
		this.onAllColumnWidthsUpdated(ws, tw);
		this.syncHeaderHeight();
	},
	updateColumnWidth : function(col, width){
		var w = this.getColumnWidth(col),
			llen = this.cm.getLockedCount(),
			ns, rw, c, row;
		this.updateLockedWidth();
		if(col < llen){
			ns = this.getLockedRows();
			rw = this.getLockedWidth();
			c = col;
		}else{
			ns = this.getRows();
			rw = this.getTotalWidth();
			c = col - llen;
		}
		var hd = this.getHeaderCell(col);
		hd.style.width = w;
		for(var i = 0, len = ns.length; i < len; i++){
			row = ns[i];
			row.style.width = rw;
			if(row.firstChild){
				row.firstChild.style.width = rw;
				row.firstChild.rows[0].childNodes[c].style.width = w;
			}
		}
		this.onColumnWidthUpdated(col, w, this.getTotalWidth());
		this.syncHeaderHeight();
	},
	updateColumnHidden : function(col, hidden){
		var llen = this.cm.getLockedCount(),
			ns, rw, c, row,
			display = hidden ? 'none' : '';
		this.updateLockedWidth();
		if(col < llen){
			ns = this.getLockedRows();
			rw = this.getLockedWidth();
			c = col;
		}else{
			ns = this.getRows();
			rw = this.getTotalWidth();
			c = col - llen;
		}
		var hd = this.getHeaderCell(col);
		hd.style.display = display;
		for(var i = 0, len = ns.length; i < len; i++){
			row = ns[i];
			row.style.width = rw;
			if(row.firstChild){
				row.firstChild.style.width = rw;
				row.firstChild.rows[0].childNodes[c].style.display = display;
			}
		}
		this.onColumnHiddenUpdated(col, hidden, this.getTotalWidth());
		delete this.lastViewWidth;
		this.layout();
	},
	doRender : function(cs, rs, ds, startRow, colCount, stripe){
		var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1,
			tstyle = 'width:'+this.getTotalWidth()+';',
			lstyle = 'width:'+this.getLockedWidth()+';',
			buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r;
		for(var j = 0, len = rs.length; j < len; j++){
			r = rs[j]; cb = []; lcb = [];
			var rowIndex = (j+startRow);
			for(var i = 0; i < colCount; i++){
				c = cs[i];
				p.id = c.id;
				p.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
                    (this.cm.config[i].cellCls ? ' ' + this.cm.config[i].cellCls : '');
				p.attr = p.cellAttr = '';
				p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
				p.style = c.style;
				if(Ext.isEmpty(p.value)){
					p.value = '&#160;';
				}
				if(this.markDirty && r.dirty && Ext.isDefined(r.modified[c.name])){
					p.css += ' x-grid3-dirty-cell';
				}
				if(c.locked){
					lcb[lcb.length] = ct.apply(p);
				}else{
					cb[cb.length] = ct.apply(p);
				}
			}
			var alt = [];
			if(stripe && ((rowIndex+1) % 2 === 0)){
				alt[0] = 'x-grid3-row-alt';
			}
			if(r.dirty){
				alt[1] = ' x-grid3-dirty-row';
			}
			rp.cols = colCount;
			if(this.getRowClass){
				alt[2] = this.getRowClass(r, rowIndex, rp, ds);
			}
			rp.alt = alt.join(' ');
			rp.cells = cb.join('');
			rp.tstyle = tstyle;
			buf[buf.length] = rt.apply(rp);
			rp.cells = lcb.join('');
			rp.tstyle = lstyle;
			lbuf[lbuf.length] = rt.apply(rp);
		}
		return [buf.join(''), lbuf.join('')];
	},
	processRows : function(startRow, skipStripe){
		if(!this.ds || this.ds.getCount() < 1){
			return;
		}
		var rows = this.getRows(),
			lrows = this.getLockedRows();
		skipStripe = skipStripe || !this.grid.stripeRows;
		startRow = startRow || 0;
		Ext.each(rows, function(row, idx){
			var lrow = lrows[idx];
			row.rowIndex = idx;
			lrow.rowIndex = idx;
			if (!skipStripe && (idx + 1) % 2 === 0) {
				row.className = row.className.replace(this.rowClsRe, ' ');
				lrow.className = lrow.className.replace(this.rowClsRe, ' ');
				row.className += ' x-grid3-row-alt';
				lrow.className += ' x-grid3-row-alt';
			}
		}, this);
		if(startRow === 0){
			Ext.fly(rows[0]).addClass(this.firstRowCls);
			Ext.fly(lrows[0]).addClass(this.firstRowCls);
		}
		Ext.fly(rows[rows.length - 1]).addClass(this.lastRowCls);
		Ext.fly(lrows[lrows.length - 1]).addClass(this.lastRowCls);
	},
	afterRender : function(){
		if(!this.ds || !this.cm){
			return;
		}
		var bd = this.renderRows() || ['&#160;', '&#160;'];
		this.mainBody.dom.innerHTML = bd[0];
		this.lockedBody.dom.innerHTML = bd[1];
		this.processRows(0, true);
		if(this.deferEmptyText !== true){
			this.applyEmptyText();
		}
	},
	renderUI : function(){
		var header = this.renderHeaders();
		var body = this.templates.body.apply({rows:'&#160;'});
		var html = this.templates.master.apply({
			body: body,
			header: header[0],
			ostyle: 'width:'+this.getOffsetWidth()+';',
			bstyle: 'width:'+this.getTotalWidth()+';',
			lockedBody: body,
			lockedHeader: header[1],
			lstyle: 'width:'+this.getLockedWidth()+';'
		});
		var g = this.grid;
		g.getGridEl().dom.innerHTML = html;
		this.initElements();
		Ext.fly(this.innerHd).on('click', this.handleHdDown, this);
		Ext.fly(this.lockedInnerHd).on('click', this.handleHdDown, this);
		this.mainHd.on({
			scope: this,
			mouseover: this.handleHdOver,
			mouseout: this.handleHdOut,
			mousemove: this.handleHdMove
		});
		this.lockedHd.on({
			scope: this,
			mouseover: this.handleHdOver,
			mouseout: this.handleHdOut,
			mousemove: this.handleHdMove
		});
		this.scroller.on('scroll', this.syncScroll,  this);
		if(g.enableColumnResize !== false){
			this.splitZone = new Ext.grid.GridView.SplitDragZone(g, this.mainHd.dom);
			this.splitZone.setOuterHandleElId(Ext.id(this.lockedHd.dom));
			this.splitZone.setOuterHandleElId(Ext.id(this.mainHd.dom));
		}
		if(g.enableColumnMove){
			this.columnDrag = new Ext.grid.GridView.ColumnDragZone(g, this.innerHd);
			this.columnDrag.setOuterHandleElId(Ext.id(this.lockedInnerHd));
			this.columnDrag.setOuterHandleElId(Ext.id(this.innerHd));
			this.columnDrop = new Ext.grid.HeaderDropZone(g, this.mainHd.dom);
		}
		if(g.enableHdMenu !== false){
			this.hmenu = new Ext.menu.Menu({id: g.id + '-hctx'});
			this.hmenu.add(
				{itemId: 'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
				{itemId: 'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
			);
			if(this.grid.enableColLock !== false){
				this.hmenu.add('-',
					{itemId: 'lock', text: this.lockText, cls: 'xg-hmenu-lock'},
					{itemId: 'unlock', text: this.unlockText, cls: 'xg-hmenu-unlock'}
				);
			}
			if(g.enableColumnHide !== false){
				this.colMenu = new Ext.menu.Menu({id:g.id + '-hcols-menu'});
				this.colMenu.on({
					scope: this,
					beforeshow: this.beforeColMenuShow,
					itemclick: this.handleHdMenuClick
				});
				this.hmenu.add('-', {
					itemId:'columns',
					hideOnClick: false,
					text: this.columnsText,
					menu: this.colMenu,
					iconCls: 'x-cols-icon'
				});
			}
			this.hmenu.on('itemclick', this.handleHdMenuClick, this);
		}
		if(g.trackMouseOver){
			this.mainBody.on({
				scope: this,
				mouseover: this.onRowOver,
				mouseout: this.onRowOut
			});
			this.lockedBody.on({
				scope: this,
				mouseover: this.onRowOver,
				mouseout: this.onRowOut
			});
		}
		if(g.enableDragDrop || g.enableDrag){
			this.dragZone = new Ext.grid.GridDragZone(g, {
				ddGroup : g.ddGroup || 'GridDD'
			});
		}
		this.updateHeaderSortState();
	},
	layout : function(){
		if(!this.mainBody){
			return;
		}
		var g = this.grid;
		var c = g.getGridEl();
		var csize = c.getSize(true);
		var vw = csize.width;
		if(!g.hideHeaders && (vw < 20 || csize.height < 20)){
			return;
		}
		this.syncHeaderHeight();
		if(g.autoHeight){
			this.scroller.dom.style.overflow = 'visible';
			this.lockedScroller.dom.style.overflow = 'visible';
			if(Ext.isWebKit){
				this.scroller.dom.style.position = 'static';
				this.lockedScroller.dom.style.position = 'static';
			}
		}else{
			this.el.setSize(csize.width, csize.height);
			var hdHeight = this.mainHd.getHeight();
			var vh = csize.height - (hdHeight);
		}
		this.updateLockedWidth();
		if(this.forceFit){
			if(this.lastViewWidth != vw){
				this.fitColumns(false, false);
				this.lastViewWidth = vw;
			}
		}else {
			this.autoExpand();
			this.syncHeaderScroll();
		}
		this.onLayout(vw, vh);
	},
	getOffsetWidth : function() {
		return (this.cm.getTotalWidth() - this.cm.getTotalLockedWidth() + this.getScrollOffset()) + 'px';
	},
	renderHeaders : function(){
		var cm = this.cm,
			ts = this.templates,
			ct = ts.hcell,
			cb = [], lcb = [],
			p = {},
			len = cm.getColumnCount(),
			last = len - 1;
		for(var i = 0; i < len; i++){
			p.id = cm.getColumnId(i);
			p.value = cm.getColumnHeader(i) || '';
			p.style = this.getColumnStyle(i, true);
			p.tooltip = this.getColumnTooltip(i);
			p.css = (i === 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '')) +
                (cm.config[i].headerCls ? ' ' + cm.config[i].headerCls : '');
			if(cm.config[i].align == 'right'){
				p.istyle = 'padding-right:16px';
			} else {
				delete p.istyle;
			}
			if(cm.isLocked(i)){
				lcb[lcb.length] = ct.apply(p);
			}else{
				cb[cb.length] = ct.apply(p);
			}
		}
		return [ts.header.apply({cells: cb.join(''), tstyle:'width:'+this.getTotalWidth()+';'}),
				ts.header.apply({cells: lcb.join(''), tstyle:'width:'+this.getLockedWidth()+';'})];
	},
	updateHeaders : function(){
		var hd = this.renderHeaders();
		this.innerHd.firstChild.innerHTML = hd[0];
		this.innerHd.firstChild.style.width = this.getOffsetWidth();
		this.innerHd.firstChild.firstChild.style.width = this.getTotalWidth();
		this.lockedInnerHd.firstChild.innerHTML = hd[1];
		var lw = this.getLockedWidth();
		this.lockedInnerHd.firstChild.style.width = lw;
		this.lockedInnerHd.firstChild.firstChild.style.width = lw;
	},
	getResolvedXY : function(resolved){
		if(!resolved){
			return null;
		}
		var c = resolved.cell, r = resolved.row;
		return c ? Ext.fly(c).getXY() : [this.scroller.getX(), Ext.fly(r).getY()];
	},
	syncFocusEl : function(row, col, hscroll){
		Ext.ux.grid.LockingGridView.superclass.syncFocusEl.call(this, row, col, col < this.cm.getLockedCount() ? false : hscroll);
	},
	ensureVisible : function(row, col, hscroll){
		return Ext.ux.grid.LockingGridView.superclass.ensureVisible.call(this, row, col, col < this.cm.getLockedCount() ? false : hscroll);
	},
	insertRows : function(dm, firstRow, lastRow, isUpdate){
		var last = dm.getCount() - 1;
		if(!isUpdate && firstRow === 0 && lastRow >= last){
			this.refresh();
		}else{
			if(!isUpdate){
				this.fireEvent('beforerowsinserted', this, firstRow, lastRow);
			}
			var html = this.renderRows(firstRow, lastRow),
				before = this.getRow(firstRow);
			if(before){
				if(firstRow === 0){
					this.removeRowClass(0, this.firstRowCls);
				}
				Ext.DomHelper.insertHtml('beforeBegin', before, html[0]);
				before = this.getLockedRow(firstRow);
				Ext.DomHelper.insertHtml('beforeBegin', before, html[1]);
			}else{
				this.removeRowClass(last - 1, this.lastRowCls);
				Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html[0]);
				Ext.DomHelper.insertHtml('beforeEnd', this.lockedBody.dom, html[1]);
			}
			if(!isUpdate){
				this.fireEvent('rowsinserted', this, firstRow, lastRow);
				this.processRows(firstRow);
			}else if(firstRow === 0 || firstRow >= last){
				this.addRowClass(firstRow, firstRow === 0 ? this.firstRowCls : this.lastRowCls);
			}
		}
		this.syncFocusEl(firstRow);
	},
    getColumnStyle : function(col, isHeader){
        var style = !isHeader ? this.cm.config[col].cellStyle || this.cm.config[col].css || '' : this.cm.config[col].headerStyle || '';
        style += 'width:'+this.getColumnWidth(col)+';';
        if(this.cm.isHidden(col)){
            style += 'display:none;';
        }
        var align = this.cm.config[col].align;
        if(align){
            style += 'text-align:'+align+';';
        }
        return style;
    },
	getLockedWidth : function() {
		return this.cm.getTotalLockedWidth() + 'px';
	},
	getTotalWidth : function() {
		return (this.cm.getTotalWidth() - this.cm.getTotalLockedWidth()) + 'px';
	},
	getColumnData : function(){
		var cs = [], cm = this.cm, colCount = cm.getColumnCount();
		for(var i = 0; i < colCount; i++){
			var name = cm.getDataIndex(i);
			cs[i] = {
				name : (!Ext.isDefined(name) ? this.ds.fields.get(i).name : name),
				renderer : cm.getRenderer(i),
				id : cm.getColumnId(i),
				style : this.getColumnStyle(i),
				locked : cm.isLocked(i)
			};
		}
		return cs;
	},
	renderBody : function(){
		var markup = this.renderRows() || ['&#160;', '&#160;'];
		return [this.templates.body.apply({rows: markup[0]}), this.templates.body.apply({rows: markup[1]})];
	},
	refreshRow : function(record){
		Ext.ux.grid.LockingGridView.superclass.refreshRow.call(this, record);
		var index = Ext.isNumber(record) ? record : this.ds.indexOf(record);
		this.getLockedRow(index).rowIndex = index;
	},
	refresh : function(headersToo){
		this.fireEvent('beforerefresh', this);
		this.grid.stopEditing(true);
		var result = this.renderBody();
		this.mainBody.update(result[0]).setWidth(this.getTotalWidth());
		this.lockedBody.update(result[1]).setWidth(this.getLockedWidth());
		if(headersToo === true){
			this.updateHeaders();
			this.updateHeaderSortState();
		}
		this.processRows(0, true);
		this.layout();
		this.applyEmptyText();
		this.fireEvent('refresh', this);
	},
	onDenyColumnLock : function(){

	},
	initData : function(ds, cm){
		if(this.cm){
			this.cm.un('columnlockchange', this.onColumnLock, this);
		}
		Ext.ux.grid.LockingGridView.superclass.initData.call(this, ds, cm);
		if(this.cm){
			this.cm.on('columnlockchange', this.onColumnLock, this);
		}
	},
	onColumnLock : function(){
		this.refresh(true);
	},
	handleHdMenuClick : function(item){
		var index = this.hdCtxIndex,
			cm = this.cm,
			id = item.getItemId(),
			llen = cm.getLockedCount();
		switch(id){
			case 'lock':
				if(cm.getColumnCount(true) <= llen + 1){
					this.onDenyColumnLock();
					return;
				}
				if(llen != index){
					cm.setLocked(index, true, true);
					cm.moveColumn(index, llen);
					this.grid.fireEvent('columnmove', index, llen);
				}else{
					cm.setLocked(index, true);
				}
			break;
			case 'unlock':
				if(llen - 1 != index){
					cm.setLocked(index, false, true);
					cm.moveColumn(index, llen - 1);
					this.grid.fireEvent('columnmove', index, llen - 1);
				}else{
					cm.setLocked(index, false);
				}
			break;
			default:
				return Ext.ux.grid.LockingGridView.superclass.handleHdMenuClick.call(this, item);
		}
		return true;
	},
	handleHdDown : function(e, t){
		Ext.ux.grid.LockingGridView.superclass.handleHdDown.call(this, e, t);
		if(this.grid.enableColLock !== false){
			if(Ext.fly(t).hasClass('x-grid3-hd-btn')){
				var hd = this.findHeaderCell(t),
					index = this.getCellIndex(hd),
					ms = this.hmenu.items, cm = this.cm;
				ms.get('lock').setDisabled(cm.isLocked(index));
				ms.get('unlock').setDisabled(!cm.isLocked(index));
			}
		}
	},
	syncHeaderHeight: function(){
		this.innerHd.firstChild.firstChild.style.height = 'auto';
		this.lockedInnerHd.firstChild.firstChild.style.height = 'auto';
		var	hd = this.innerHd.firstChild.firstChild.offsetHeight,
			lhd = this.lockedInnerHd.firstChild.firstChild.offsetHeight,
			height = (lhd > hd ? lhd : hd) + 'px';
		this.innerHd.firstChild.firstChild.style.height = height;
		this.lockedInnerHd.firstChild.firstChild.style.height = height;
	},
	updateLockedWidth: function(){
		var lw = this.cm.getTotalLockedWidth(),
			tw = this.cm.getTotalWidth() - lw,
			csize = this.grid.getGridEl().getSize(true),
			lp = Ext.isBorderBox ? 0 : this.lockedBorderWidth,
			rp = Ext.isBorderBox ? 0 : this.rowBorderWidth,
			vw = (csize.width - lw - lp - rp) + 'px',
			so = this.getScrollOffset();
		if(!this.grid.autoHeight){
			var vh = (csize.height - this.mainHd.getHeight()) + 'px';
			this.lockedScroller.dom.style.height = vh;
			this.scroller.dom.style.height = vh;
		}
		this.lockedWrap.dom.style.width = (lw + rp) + 'px';
		this.scroller.dom.style.width = vw;
		this.mainWrap.dom.style.left = (lw + lp + rp) + 'px';
		if(this.innerHd){
			this.lockedInnerHd.firstChild.style.width = lw + 'px';
			this.lockedInnerHd.firstChild.firstChild.style.width = lw + 'px';
			this.innerHd.style.width = vw;
			this.innerHd.firstChild.style.width = (tw + rp + so) + 'px';
			this.innerHd.firstChild.firstChild.style.width = tw + 'px';
		}
		if(this.mainBody){
			this.lockedBody.dom.style.width = (lw + rp) + 'px';
			this.mainBody.dom.style.width = (tw + rp) + 'px';
		}
	}
});

Ext.ux.grid.LockingColumnModel = Ext.extend(Ext.grid.ColumnModel, {
	isLocked : function(colIndex){
		return this.config[colIndex].locked === true;
	},
	setLocked : function(colIndex, value, suppressEvent){
		if(this.isLocked(colIndex) == value){
			return;
		}
		this.config[colIndex].locked = value;
		if(!suppressEvent){
			this.fireEvent('columnlockchange', this, colIndex, value);
		}
	},
	getTotalLockedWidth : function(){
		var totalWidth = 0;
		for(var i = 0, len = this.config.length; i < len; i++){
			if(this.isLocked(i) && !this.isHidden(i)){
				totalWidth += this.getColumnWidth(i);
			}
		}
		return totalWidth;
	},
	getLockedCount : function(){
		for(var i = 0, len = this.config.length; i < len; i++){
			if(!this.isLocked(i)){
				return i;
			}
		}
	},
	moveColumn : function(oldIndex, newIndex){
		if(oldIndex < newIndex && this.isLocked(oldIndex) && !this.isLocked(newIndex)){
			this.setLocked(oldIndex, false, true);
		}else if(oldIndex > newIndex && !this.isLocked(oldIndex) && this.isLocked(newIndex)){
			this.setLocked(oldIndex, true, true);
		}
		Ext.ux.grid.LockingColumnModel.superclass.moveColumn.apply(this, arguments);
	}
});

