Ext.Component.override({
    initState : function(config){
        if(Ext.state.Manager){
            var id = this.getStateId();
            if(id){
                var state = Ext.state.Manager.get(id);
                if(state){
                    if(this.fireEvent('beforestaterestore', this, state) !== false){
                        this.applyState(state);
                        this.fireEvent('staterestore', this, state);
                    }
                }
            }
        }
    },
    saveState : function(){
        if(Ext.state.Manager){
            var id = this.getStateId();
            if(id){
                var state = this.getState();
                if(this.fireEvent('beforestatesave', this, state) !== false){
                    Ext.state.Manager.set(id, state);
                    this.fireEvent('statesave', this, state);
                }
            }
        }
    },
    getStateId : function(){
        return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
    }
});

// private
Ext.apply(Date.parseCodes, {
    j: {
        g:1,
        c:"d = parseInt(results[{0}], 10);\n",
        s:"(\\d{1,2})" // day of month without leading zeroes (1 - 31)
    },
    M: function() {
        for (var a = [], i = 0; i < 12; a.push(Date.getShortMonthName(i)), ++i); // get localised short month names
        return Ext.applyIf({
            s:"(" + a.join("|") + ")"
        }, Date.formatCodeToRegex("F"));
    },
    n: {
        g:1,
        c:"m = parseInt(results[{0}], 10) - 1;\n",
        s:"(\\d{1,2})" // month number without leading zeros (1 - 12)
    },
    o: function() {
        return Date.formatCodeToRegex("Y");
    },
    g: function() {
        return Date.formatCodeToRegex("G");
    },
    h: function() {
        return Date.formatCodeToRegex("H");
    },
    P: function() {
      return Ext.applyIf({
        s: "([+\-]\\d{2}:\\d{2})" // GMT offset in hrs and mins (with colon separator)
      }, Date.formatCodeToRegex("O"));
    }
});

// private
Date.formatCodeToRegex = function(character, currentGroup) {
    // Note: currentGroup - position in regex result array (see notes for Date.parseCodes above)
    var p = Date.parseCodes[character];

    if (p) {
      p = Ext.type(p) == 'function'? p() : p;
      Date.parseCodes[character] = p; // reassign function result to prevent repeated execution      
    }

    return p? Ext.applyIf({
      c: p.c? String.format(p.c, currentGroup || "{0}") : p.c
    }, p) : {
        g:0,
        c:null,
        s:Ext.escapeRe(character) // treat unrecognised characters as literals
    }
};

Ext.util.Format.ukMoney = function(v){
    v = (Math.round((v-0)*100))/100;
    v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
    v = String(v);
    var ps = v.split('.');
    var whole = ps[0];
    var sub = ps[1] ? '.'+ ps[1] : '.00';
    var r = /(\d+)(\d{3})/;
    while (r.test(whole)) {
        whole = whole.replace(r, '$1' + ',' + '$2');
    }
    v = whole + sub;
    if(v.charAt(0) == '-'){
        return '-&#0163;' + v.substr(1);
    }
    return '&#0163;' +  v;
};

Ext.override(Ext.layout.AnchorLayout, {
    getAnchorViewSize : function(ct, target){
        var result = target.dom == document.body ?
           target.getViewSize() : target.getStyleSize();
        if ((target.dom.style.overflow == 'auto') || (target.dom.style.overflowY == 'auto')) {
            if (target.dom.scrollHeight > result.height) {
                result.width = target.dom.clientWidth;
            }
        }
        return result;
    }
});

Ext.override(Ext.layout.FormLayout, {
    getAnchorViewSize : function(ct, target){
        var result = target.dom == document.body ?
           target.getViewSize() : target.getStyleSize();
        if ((target.dom.style.overflow == 'auto') || (target.dom.style.overflowY == 'auto')) {
            if (target.dom.scrollHeight > result.height) {
                result.width = target.dom.clientWidth;
            }
        }
        return result;
    }
});

Ext.override(Ext.form.RadioGroup, {
  getName: function() {
    return this.items.first().getName();
  },

  getValue: function() {
    var v;

    this.items.each(function(item) {
      v = item.getRawValue();
      return !item.getValue();
    });

    return v;
  },

  setValue: function(v) {
    if(this.rendered)
		this.items.each(function(item) {
	      item.setValue(item.getRawValue() == v);
	    });
	else
		for(k in this.items) this.items[k].checked = this.items[k].inputValue == v;
  }
});

Ext.override(Ext.form.Checkbox, {
	getValue : function(){
		if(this.rendered){
			return this.el.dom.checked;
		}
		return this.checked;
	},

	setValue : function(v) {
		var checked = this.checked;
		this.checked = (v === true || v === 'true' || v == '1' || String(v).toLowerCase() == 'on');

		if(this.rendered){
			this.el.dom.checked = this.checked;
			this.el.dom.defaultChecked = this.checked;
			this.wrap[this.checked? 'addClass' : 'removeClass'](this.checkedCls);
		}

		if(checked != this.checked){
			this.fireEvent("check", this, this.checked);
			if(this.handler){
				this.handler.call(this.scope || this, this, this.checked);
			}
		}
	}
});

Ext.override(Ext.ToolTip, {
    onTargetOver : function(e){
        if(this.disabled || e.within(this.target.dom, true)){
            return;
        }
        var t = e.getTarget(this.delegate);
        if (t) {
            this.triggerElement = t;
            this.clearTimer('hide');
            this.targetXY = e.getXY();
            this.delayShow();
        }
    },
    onMouseMove : function(e){
        var t = e.getTarget(this.delegate);
        if (t) {
            this.targetXY = e.getXY();
            if (t === this.triggerElement) {
                if(!this.hidden && this.trackMouse){
                    this.setPagePosition(this.getTargetXY());
                }
            } else {
                this.hide();
                this.lastActive = new Date(0);
                this.onTargetOver(e);
            }
        } else if (!this.closable && this.isVisible()) {
            this.hide();
        }
    },
    hide: function(){
        this.clearTimer('dismiss');
        this.lastActive = new Date();
        delete this.triggerElement;
        Ext.ToolTip.superclass.hide.call(this);
    }
});

Ext.Button.override({
	initButtonEl : function(btn, btnEl){

		this.el = btn;
		btn.addClass("x-btn");

		if(this.icon){
			btnEl.setStyle('background-image', 'url(' +this.icon +')');
		}
		if(this.iconCls){
			btnEl.addClass(this.iconCls);
			if(!this.cls){
				btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
			}
		}
		if(this.tabIndex !== undefined){
			btnEl.dom.tabIndex = this.tabIndex;
		}
		if(this.buttonId !== undefined){
			btnEl.dom.id = this.buttonId;
		}
		if(this.tooltip){
			if(typeof this.tooltip == 'object'){
				Ext.QuickTips.register(Ext.apply({
					  target: btnEl.id
				}, this.tooltip));
			} else {
				btnEl.dom[this.tooltipType] = this.tooltip;
			}
		}

		if(this.pressed){
			this.el.addClass("x-btn-pressed");
		}

		if(this.handleMouseEvents){
			btn.on("mouseover", this.onMouseOver, this);
									btn.on("mousedown", this.onMouseDown, this);
		}

		if(this.menu){
			this.menu.on("show", this.onMenuShow, this);
			this.menu.on("hide", this.onMenuHide, this);
		}

		if(this.id){
			this.el.dom.id = this.el.id = this.id;
		}

		if(this.repeat){
			var repeater = new Ext.util.ClickRepeater(btn,
				typeof this.repeat == "object" ? this.repeat : {}
			);
			repeater.on("click", this.onClick,  this);
		}

		btn.on(this.clickEvent, this.onClick, this);
	}
});