jsgtk_min.js

Summary

No overview generated for 'jsgtk_min.js'


Class Summary
gtk.Adjustment  
gtk.Bin  
gtk.Box  
gtk.Buildable  
gtk.Button  
gtk.CellRenderer  
gtk.CellRendererText  
gtk.CheckButton  
gtk.Combo  
gtk.ComboBox  
gtk.ComboBoxController  
gtk.ComboBoxEntry  
gtk.Container  
gtk.Contents  
gtk.Dom  
gtk.Entry  
gtk.Frame  
gtk.HBox  
gtk.HPaned  
gtk.Image  
gtk.Item  
gtk.Label  
gtk.ListStore  
gtk.Menu  
gtk.MenuItem  
gtk.MenuShell  
gtk.Misc  
gtk.NoteBook  
gtk.Paned  
gtk.Panel  
gtk.ProgressBar  
gtk.RadioButton  
gtk.ScrolledWindow  
gtk.SeparatorToolItem  
gtk.Slider  
gtk.SmartEntry  
gtk.Table  
gtk.Tabs  
gtk.TextBuffer  
gtk.TextTag  
gtk.TextTagTable  
gtk.TextView  
gtk.ToggleButton  
gtk.Toolbar  
gtk.ToolButton  
gtk.ToolItem  
gtk.TreeIter  
gtk.TreeStore  
gtk.TreeView  
gtk.TreeViewColumn  
gtk.VBox  
gtk.Viewport  
gtk.VPaned  
gtk.Widget  
gtk.Window  
UUID  

/** @namespace gtk name space */
gtk = {};


/** @namespace jsgtk name space */
jsgtk = {};

/**
* Drag Object : make dom object draggable by www.youngpup.net
*/
jsgtk.domDrag = {

	obj : null,

	/**
	* init() method 				: The initalization function for the drag object
	* @param {object} o 			: The element to act as the drag handle
	* @param {object} oRoot 		: The element to be dragged, if not specified, the handle will be the element dragged.
	* @param {integer} minX 		: min x of coordinate allowed for the element
	* @param {integer} maxX 		: max x of coordinate allowed for the element
	* @param {integer} minY 		: min y of coordinate allowed for the element
	* @param {integer} maxY 		: max y of coordinate allowed for the element
	* @param {boolean} bSwapHorzRef : Toggle the horizontal coordinate system
	* @param {boolean} bSwapVertRef : Toggle the vertical coordinate system
	* @param {function} fxMapper	: Functions for mapping x and y coordinates to others
	* @param {function} fyMapper 	: Functions for mapping x and y coordinates to others
	*/
	init : function(o, oRoot, minX, maxX, minY, maxY, hDisable, vDisable, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper){

		o.onmousedown = jsgtk.domDrag.start;

		o.hmode	= bSwapHorzRef ? false : true ;
		o.vmode	= bSwapVertRef ? false : true ;

		o.root = oRoot && oRoot != null ? oRoot : o ;

		if (o.hmode  && isNaN(parseInt(o.root.style.left  ))) o.root.style.left   = "0px";
		if (o.vmode  && isNaN(parseInt(o.root.style.top   ))) o.root.style.top    = "0px";
		if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right  = "0px";
		if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";

		o.minX	= typeof minX != 'undefined' ? minX : null;
		o.minY	= typeof minY != 'undefined' ? minY : null;
		o.maxX	= typeof maxX != 'undefined' ? maxX : null;
		o.maxY	= typeof maxY != 'undefined' ? maxY : null;

		o.minX	= hDisable ? 0 : o.minX;
		o.maxX	= hDisable ? 0 : o.maxX;
		o.minY	= vDisable ? 0 : o.minY;
		o.maxY	= vDisable ? 0 : o.maxY;

		o.xMapper = fXMapper ? fXMapper : null;
		o.yMapper = fYMapper ? fYMapper : null;

		o.root.onDragStart	= new Function();
		o.root.onDragEnd	= new Function();
		o.root.onDrag		= new Function();
	},

	start : function(e){

		var o = jsgtk.domDrag.obj = this;

		e = jsgtk.domDrag.fixE(e);

		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );

		o.root.onDragStart(x, y);

		o.lastMouseX	= e.clientX;
		o.lastMouseY	= e.clientY;

		if (o.hmode) {

			if (o.minX != null)	o.minMouseX	= e.clientX - x + o.minX;
			if (o.maxX != null)	o.maxMouseX	= o.minMouseX + o.maxX - o.minX;

		} else {
			if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
			if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
		}

		if (o.vmode) {

			if (o.minY != null)	o.minMouseY	= e.clientY - y + o.minY;
			if (o.maxY != null)	o.maxMouseY	= o.minMouseY + o.maxY - o.minY;

		} else {
			if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
			if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
		}

		document.onmousemove	= jsgtk.domDrag.drag;
		document.onmouseup		= jsgtk.domDrag.end;

		return false;
	},

	drag : function(e){

		e = jsgtk.domDrag.fixE(e);

		var o = jsgtk.domDrag.obj;

		var ey	= e.clientY;
		var ex	= e.clientX;

		var y = parseInt(o.vmode ? o.root.style.top  : o.root.style.bottom);
		var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
		var nx, ny;

		if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);

		if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);

		if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);

		if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);

		nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
		ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));

		if (o.xMapper) nx = o.xMapper(y)
		else if (o.yMapper)	ny = o.yMapper(x)

		jsgtk.domDrag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
		jsgtk.domDrag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";

		jsgtk.domDrag.obj.lastMouseX	= ex;
		jsgtk.domDrag.obj.lastMouseY	= ey;

		jsgtk.domDrag.obj.root.onDrag(nx, ny);
		return false;
	},

	end : function(){

		document.onmousemove = null;
		document.onmouseup   = null;

		jsgtk.domDrag.obj.root.onDragEnd(
			parseInt(jsgtk.domDrag.obj.root.style[jsgtk.domDrag.obj.hmode ? "left" : "right"]),
			parseInt(jsgtk.domDrag.obj.root.style[jsgtk.domDrag.obj.vmode ? "top" : "bottom"])
		);

		jsgtk.domDrag.obj = null;
	},

	fixE : function(e){

		if (typeof e == 'undefined') e = window.event;

		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
		return e;
	}
}
/*

uuid.js - Version 0.3
JavaScript Class to create a UUID like identifier

Copyright (C) 2006-2008, Erik Giberti (AF-Design), All rights reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA

The latest version of this file can be downloaded from
http://www.af-design.com/resources/javascript_uuid.php

HISTORY:
6/5/06 	- Initial Release
5/22/08 - Updated code to run faster, removed randrange(min,max) in favor of
          a simpler rand(max) function. Reduced overhead by using getTime()
          method of date class (suggestion by James Hall).
9/5/08	- Fixed a bug with rand(max) and additional efficiencies pointed out
	  by Robert Kieffer http://broofa.com/

KNOWN ISSUES:
- Still no way to get MAC address in JavaScript
- Research into other versions of UUID show promising possibilities
  (more research needed)
- Documentation needs improvement

*/

function UUID(){
	this.id = this.createUUID();
}

UUID.prototype.valueOf = function(){ return this.id; }
UUID.prototype.toString = function(){ return this.id; }


UUID.prototype.createUUID = function(){
	var dg = new Date(1582, 10, 15, 0, 0, 0, 0);
	var dc = new Date();
	var t = dc.getTime() - dg.getTime();
	var h = '-';
	var tl = UUID.getIntegerBits(t,0,31);
	var tm = UUID.getIntegerBits(t,32,47);
	var thv = UUID.getIntegerBits(t,48,59) + '1'; // version 1, security version is 2
	var csar = UUID.getIntegerBits(UUID.rand(4095),0,7);
	var csl = UUID.getIntegerBits(UUID.rand(4095),0,7);

	var n = UUID.getIntegerBits(UUID.rand(8191),0,7) +
			UUID.getIntegerBits(UUID.rand(8191),8,15) +
			UUID.getIntegerBits(UUID.rand(8191),0,7) +
			UUID.getIntegerBits(UUID.rand(8191),8,15) +
			UUID.getIntegerBits(UUID.rand(8191),0,15); // this last number is two octets long
	return tl + h + tm + h + thv + h + csar + csl + h + n;
}




UUID.getIntegerBits = function(val,start,end){
	var base16 = UUID.returnBase(val,16);
	var quadArray = new Array();
	var quadString = '';
	var i = 0;
	for(i=0;i<base16.length;i++){
		quadArray.push(base16.substring(i,i+1));
	}
	for(i=Math.floor(start/4);i<=Math.floor(end/4);i++){
		if(!quadArray[i] || quadArray[i] == '') quadString += '0';
		else quadString += quadArray[i];
	}
	return quadString;
}

UUID.returnBase = function(number, base){
	return (number).toString(base).toUpperCase();
}

UUID.rand = function(max){
	return Math.floor(Math.random() * (max + 1));
}


jsgtk.Dom = {
		ie: (function(){ return (window.opera === undefined && (navigator.userAgent.indexOf('Internet Explorer') >= 0 || navigator.userAgent.indexOf("MSIE") >= 0)) ? true : false; })(),
		ie6or7: (function() { return (window.opera === undefined && (navigator.userAgent.indexOf("MSIE 6.0") >= 0 || navigator.userAgent.indexOf("MSIE 7.0") >= 0)) ? true : false; })(),
		doc: document,
		create: function(args){
		    if(!args.tag){ return null; }
		    var tag;
		    if((args.name || args.type) && this.ie) {
		      var name = (args.name) ? "name='" + args.name + "'" : "";
		      var type = (args.type) ? "type='" + args.type + "'" : "";
		      var html = '<' + args.tag + ' ' + name + ' '+ type +' />';
		      tag = this.doc.createElement(html);
		      delete args.name;
		    }
		    else {
		        tag = this.doc.createElement(args.tag);
	        }
		    delete args.tag;

		    if(args.append) {
		      args.append.appendChild(tag);
		      delete args.append;
		    }

		    args.edit = tag;
		    tag = this.edit(args);

		    return tag;
	    },
	    edit: function(args){
		    var tag = args.edit;
		    delete args.edit;

		    if(args.text) {
		      tag.appendChild(this.doc.createTextNode(args.text));
		      delete args.text;
		    }

		    if(args.className){
			    tag.className = args.className;
			    delete args.className;
		    }

			    var style = args.style;
		    if (style && this.ie) {
			    var styleCollections = style.split(";"), len = styleCollections.length;
			    for (var i=styleCollections.length; i--;) {
				    var styleString = styleCollections[i].replace(/ /g, '');
				    if (styleString) {
                        var styleKeyValue = styleString.split(":");
                        tag.style[this._camelize(styleKeyValue[0])] = styleKeyValue[1];
				    }
			    }

			    delete style ;
		    }

		    for(property in args){
		      tag.setAttribute(property, args[property]);
		    }
		    return tag;
	    },
	    _camelize: function(string) {
		    var parts = string.split('-'), len = parts.length;
		    if (len == 1){ return parts[0]; }

		    var camelized = string.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1): parts[0];

		    for (var i = 1; i < len; i++){
		      camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
            }

		    return camelized;
	    },

		/*
		* Return the width and height of given text
		* @param {string} - text to be measured
		* @return {array} - widht and height of text
		*/
		getTextSize: function(text){
			var span = jsgtk.Dom.create({'tag': 'span', 'text': text});
			document.body.appendChild(span);
			var size = [span.offsetWidth, span.offsetHeight];
			document.body.removeChild(span);
			return size;
		},

		/*
		* addDomEventListener() method : Add browser event to a dom
		* @param {object} dom          : dom object that recieve the event
		* @param {string} type         : event
		* @param {function} callBack   : callBack function
		* @param {boolean} isBubling   : resolve to true if allow event bubling
		*/
		addDomEventListener: function(dom, type, callBack, bubble){
			jsgtk.Dom.ie ? dom.attachEvent('on' + type, callBack) : dom.addEventListener(type, callBack, bubble);
		},

		/*
		* removeDomEventListener() method : remove browser event from a dom
		* @param {object} dom    	 	  : dom object that recieve the event
		* @param {string} type   	 	  : event
		* @param {function} callBack 	  :  callBack function
		* @param {boolean} isBubling 	  : resolve to true if allow event bubling
		*/
		removeDomEventListener: function(dom, type, callBack, bubble){
			jsgtk.Dom.ie ? dom.detachEvent('on' + type, callBack) : dom.removeEventListener(type, callBack, bubble);
		},

		/**
		* cancelBubble() method : cancel bubbling phase of event
		* @param {object} e  	: event object
		*/
		cancelBubble: function(e){
			e = (e)?e:((event)?event:null);
			e.cancelBubble = true;
			e.returnValue = false;
			if (e.stopPropogation) {
			    e.stopPropogation();
			}
			if (e.preventDefault) {
			    e.preventDefault();
			}
			return false;
		},

		/**
		* showElement() method
		* @param {object} dom  : dom object
		*/
		showElement: function(element){
			element.style.display = "";
		},

		/**
		* showElement() method
		* @param {object} dom  : dom object
		*/
		hideElement: function(element){
			element.style.display = "none";
		},
		hilightCell: function(element, style){
		    for(el in style){
		        element.style[el] = style[el];
		    }
		},
		vDragInit: function(domObj, minY, maxY){
			jsgtk.domDrag.init(domObj, null, null, null, minY, maxY,true);
		},
		hDragInit: function(domObj, minX, maxX){
			jsgtk.domDrag.init(domObj, null, minX, maxX, null, null, false, true);
		},
		dragInit: function(domObj, minX, maxX, minY, maxY){
		    jsgtk.domDrag.init(domObj, null, minX, maxX, minY, maxY, false, false);
		}
};
jsgtk.Event = {

	/**
	 * Add a new event listener to a dom object The event will be fired when the browser event occurs.
	 * @param {object} domObj
	 * @param {String} type
	 * @param {Function} callback
	 * @return {object} - handle used to remove listeners
	 */
	addDomListener: function(domObj, type, callback){
		if(domObj.addEventListener){
			domObj.addEventListener(type, callback, false);
		} else {
			domObj.attachEvent("on" + type, callback);
		}
		var handler = {
			obj: domObj,
			type: type,
			callback: callback
		};

		return handler;
	},
	/**
	 * Remove an event listener which was added using addListener or addDomListener.
	 * @param {object} handler
	 */
	removeListener: function(handler){
		if(handler.obj.removeEventListener){
			handler.obj.removeEventListener(handler.type, handler.callback, false);
		} else {
			handler.obj.detachEvent("on" + handler.type, handler.callback);
		}
	},

	/**
	* Cancell bubbling phase of event
	* @param {object} e - event object
	*/
	stopBubble: function(e){
        if ( e && e.stopPropagation ) e.stopPropagation();
        else window.event.cancelBubble = true;
	}
};
jsgtk.Util = {
    windowHeight: function(){
        var de = document.documentElement;
        return self.innerHeight || ( de && de.clientHeight ) || document.body.clientHeight;
    },

    windowWidth: function(){
        var de = document.documentElement;
        return self.innerWidth || ( de && de.clientWidth ) || document.body.clientWidth;
    },

    getWindowHeight: function(){
        return jsgtk.Util.windowHeight();
    },

    getWindowWidth: function(){
        return jsgtk.Util.windowWidth();
    },
    calculateTextWidthHeight: function(text){
        var span = jsgtk.Dom.create({"append": document.body, "tag": "span", "style" : "position:absolute;"});
	    var text = jsgtk.Dom.create({"append": span, "tag": "text", "text": text});
	    var width = span.clientWidth;
	    var height = span.clientHeight;
	    document.body.removeChild(span);
	    return [width, height];
    },
    getTextFromTop : function(parentHeight, childHeight){
        return (parentHeight / 2) - (childHeight / 2);
    },

    fullHeight: function(elem) {
        var height;
        document.body.appendChild(elem);
        if ( this.getStyle( elem, 'display' ) != 'none' ){
            height = elem.offsetHeight || this.getHeight(elem);
            document.body.removeChild(elem);
            return height;
        }
        var old = this.resetCSS(elem, {
                display: '',
                visibility: 'hidden',
                position: 'absolute'
            });
        height = elem.clientHeight || this.getHeight(elem);
        this.restoreCSS(elem, old);
        document.body.removeChild(elem);

        return height;
    },

    fullWidth: function(elem) {
        var width;
        document.body.appendChild(elem);
        if (this.getStyle(elem, 'display') != 'none' ){
            width = elem.offsetWidth || this.getWidth( elem );
            document.body.removeChild(elem);
            return width;
        }
        var old = this.resetCSS( elem, {
            display: '',
            visibility: 'hidden',
            position: 'absolute'
        });

        width = elem.clientWidth || this.getWidth( elem );
        this.restoreCSS( elem, old );
        document.body.removeChild(elem);
        return width;
    },

    getStyle: function(elem, name){
        if (elem.style[name])
            return elem.style[name];
        else if (elem.currentStyle)
            return elem.currentStyle[name];
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            name = name.replace(/([A-Z])/g,"-$1");
            name = name.toLowerCase();
            var s = document.defaultView.getComputedStyle(elem,"");
            return s && s.getPropertyValue(name);
        } else
            return null;
    },

    getHeight: function(elem) {
        return parseInt( this.getStyle( elem, 'height' ) );
    },

    getWidth: function(elem){
        return parseInt( this.getStyle( elem, 'width' ) );
    },

	pageX: function(elem) {
        return elem.offsetParent ? elem.offsetLeft + this.pageX(elem.offsetParent) : elem.offsetLeft;
    },

    pageY: function(elem) {
        return elem.offsetParent ? elem.offsetTop + this.pageY(elem.offsetParent) : elem.offsetTop;
    },

    getPageSize: function() {
        var x, y, b = document.body, wi = window.innerHeight, ws = window.scrollMaxY;
        if (wi && ws) {
            x = b.scrollWidth;
            y = wi + ws;
        } else if (b.scrollHeight > b.offsetHeight) {
            x = b.scrollWidth;
            y = b.scrollHeight;
        } else {
            x = b.offsetWidth;
            y = b.offsetHeight;
        }
        var w, h, d = document.documentElement;
        if (self.innerHeight) {
            w = self.innerWidth;
            h = self.innerHeight;
        } else if (d && d.clientHeight) {
            w = d.clientWidth;
            h = d.clientHeight;
        } else if (b) {
            w = b.clientWidth;
            h = b.clientHeight;
        }
        var pH = (y < h) ? h : y, pW = (x < w) ? w : x;

        return [pW, pH, w, h];
    },

    resetCSS: function(elem, prop) {
        var old = {};
        for ( var i in prop ) {
            old[i] = elem.style[i];
            elem.style[i] = prop[i];
        }
        return old;
    },

    restoreCSS: function(elem, prop) {
        for ( var i in prop )
            elem.style[i] = prop[i];
    }
};
pango = {};
pango._scriptName = "jsgtk_min.js";

pango.Path = {
	/**
	 * Returns the path of Pango.js
	 * @return {String}
	 */
    getRootPath: function () {
        var scriptLocation = "";
        var scriptName = pango._scriptName;

        var scripts = document.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
            var src = scripts[i].getAttribute('src');
            if (src) {
                var index = src.lastIndexOf(scriptName);

                if ((index > -1) && (index + scriptName.length == src.length)) {
                    scriptLocation = src.slice(0, -scriptName.length);
                    break;
                }
            }
        }

        return scriptLocation;
     }
}
pango.STOCK_COLLAPSE = "treeview_row_collapsed.gif";//16
pango.STOCK_EXPANDED = "treeview_row_expanded.gif";//16
pango.STOCK_ZOOM = "stock_zoom.png";	//16
pango.STOCK_DIALOG_ERROR = "stock_dialog_error_48.png";
pango.STOCK_DIALOG_INFO = "stock_dialog_info_48.png";
pango.STOCK_DIALOG_QUESTION = "stock_dialog_question_48.png";
pango.STOCK_DIALOG_WARNING = "stock_dialog_warning_48.png";
pango.STOCK_ZOOM_IN = "zoom-in.png";		//22
pango.STOCK_SAVE_TEMPLATE = "stock_save-template.png"; //24
pango.STOCK_ZOOM_FIT_BEST = "zoom-fit-best.png"; //32

pango.ICON_SIZE_MENU = "16x16";
pango.ICON_SIZE_SMALL_TOOLBAR = "22x22";
pango.ICON_SIZE_LARGE_TOOLBAR = "24x24"
pango.ICON_SIZE_BUTTON = "32x32";
pango.ICON_SIZE_DND = "48x48";
pango.ICON_SIZE_DIALOG = "scalable";

pango.BUTTON_CLOSE = "gtk-close.png"
/**
 * Store all attributes to make up text
 * @property {Object} o which store all attributes such as font_family, color, background_color, font_size, font_weight, text_decoration.
 */
pango.Attribute = function(o){
	this.o = o || {};
	this.fontFamily = this.o.fontFamily || "Arial";
	this.color = this.o.color || "white";
	this.backgroundColor = this.o.backgroundColor || "white";
	this.fontSize = this.o.fontSize ? this.o.fontSize + "px" : "12px";
	this.fontWeight	= this.o.fontWeight || "normal";
	this.textDecoration = this.o.textDecoration || "none";
}
gtk.PACK_START = "PACK_START";
gtk.PACK_END = "PACK_END";

gtk.PROGRESS_LEFT_TO_RIGHT = "leftToRight";
gtk.PROGRESS_RIGHT_TO_LEFT = "rightToLeft";
gtk.PROGRESS_TOP_TO_BOTTOM = "topToBottom";
gtk.PROGRESS_BOTTOM_TO_TOP = "bottomToTop";

gtk.POS_LEFT = "leftPosition";
gtk.POS_RIGHT = "rightPosition";
gtk.POS_TOP = "topPosition";
gtk.POS_BOTTOM = "bottomPosition";

gtk.CELLRENDERER_WIDTH = 400;
gtk.CELLRENDERER_HEIGHT = 200;
gtk.CELL_HEIGHT = 20;
gtk.CELL_WIDTH = gtk.CELLRENDERER_WIDTH;
gtk.LISTSTORE = "LIST_STORE";
gtk.TREESTORE = "TREE_STORE";

gtk.WINDOW_TOPLEVEL = "WINDOW_TOPLEVEL";
gtk.WINDOW_POPUP = "WINDOW_POPUP";
gtk.WIN_POS_CENTER = "WIN_POS_CENTER";

gtk.WIN_POS_CENTER = "center";

gtk.JUSTIFY_LEFT   = "left";
gtk.JUSTIFY_RIGHT  = "right";
gtk.JUSTIFY_TOP    = "TOP";
gtk.JUSTIFY_BOTTOM = "BOTTOM";
gtk.JUSTIFY_CENTER = "center";
gtk.JUSTIFY_FILL   = "justify";

gtk.ENTER_KEY = 13;
gtk.UP_ARROW_KEY = 38;
gtk.DOWN_ARROW_KEY = 40;
gtk.DELETE_KEY = 46;
gtk.TAB_KEY = 9;
gtk.BACKSPACE_KEY = 8;
gtk.A_KEY = 97;
gtk.CAP_A_KEY = 65;
gobject = {
	TYPE_STRING: 'string',
	TYPE_INT: 'number',

	_signals: [],

	_signalCount: 0,

	/**
	* The gobject.signalNew() function registers a signal with the specified signal_name for the specified object type
	* @param  {string}  signalName  : a string containing the name of the signal
    * @param  {object}  type 		: the object type that the signal is associated with
    * @param  {}        flags       : the signal flags
    * @param  {object}  returnType  : the return type of the signal handler
    * @param  {object}  paramTypes  : the parameter types passed to the signal handler
	* @return {integer} signalId    :a unique integer signal ID
	*/
	signalNew: function(signalName, type, flags, returnType, paramTypes) {
		var signal = {};
		if(this.signalLookup(signalName, type)) throw("RuntimeError: this signal is already binned to the type");
		this._signalCount++;
		signal[signalName] = {'type': type, 'flags': flags, 'returnType': returnType, 'paramTypes': paramTypes, 'id': this._signalCount};
		this._signals.push(signal);
		return this._signalCount;
	},

	/**
	* function returns the id of the signal with the name specified by
	* name that is supported by the GObject specified specified bytype
	* @param {string} name       : the name of a signal for type
	* @param {object} type       : a GObject type or an instance of GObject type
    * @return {iteger} or {null} : the integer id of a signal supported by type or 0.
	*/
	signalLookup: function(name, type) {
		for(var i = this._signals.length; i--;){
			if(this._signals[i][name] && this._signals[i][name].type === type ) return this._signals[i][name].id;
			if(this._signals[i][name] && type instanceof this._signals[i][name].type ) return this._signals[i][name].id;
		}
		return null;
	},

	/**
	 * It works as setInterval
	 * @param {Function} method
	 * @param {Integer} timeInterval
	 */
	timeoutAdd: function(method, timeInterval) {
		setInterval(method, timeInterval);
	}
};
gobject.GObject = function(){

	this.props = {};
	this._signalHandlers = {};
	var self = this;

	this.getProperty = function(propertyName){ return this.props[propertyName]; };

	this.getProperties = function(){
		var properties = [];
		for(var i=0; i<arguments.length; i++) properties.push(this.props[arguments[i]]);
		return properties;
	};

	this.setProperty = function(propertyName, value){ this.props[propertyName] = value };

	this.setProperties = function(propertyNameValuePairs){
		for(propertyName in propertyNameValuePairs) this.setProperty(propertyName, propertyNameValuePairs[propertyName]);
	};

	this.emit = function(detailedSignal){
		if(this._signalHandlers[detailedSignal]){
			var args = [];
			for(var i=1; i<arguments.length; i++) args.push(arguments[i]);
			for(var i=0; i<this._signalHandlers[detailedSignal].length; i++){
				this._signalHandlers[detailedSignal][i].handler.apply(this, args.concat(this._signalHandlers[detailedSignal][i].args));
			}
		}
	};

	this.connect = function(detailedSignal, handler){
		this._signalCheck(detailedSignal);
		if(!this._signalHandlers[detailedSignal]){
			this._signalHandlers[detailedSignal] = [];
			this._handlerId++;
		}
		var args = [];
		var handlerId = new UUID();
		for(var i=2; i<arguments.length; i++) args.push(arguments[i]);
		this._signalHandlers[detailedSignal].push({'handler': handler, 'args': args, id: handlerId});
		return handlerId;
	};

	this.disconnect = function(handlerId){

		for(var el in this._signalHandlers){
			var handlers = this._signalHandlers[el];
			for(var i = 0, len = handlers.length; i < len; i++){
				if(handlers[i].id === handlerId) {
					handlers.splice(i, 1);
					break;
				}
			}
		}
	};

	this._signalCheck = function(detailedSignal){
		var signal = gobject.signalLookup(detailedSignal, this);
		if(signal) return signal;
		throw("Undefined signal name: " + detailedSignal);
	};

	this._removeSignal = function(handlerId){
		for (var el in this._signalHandlers){
			if(el == handlerId) delete this._signalHandlers.handlerId;
		}
	};
};
gtk.Object = function() {
	gobject.GObject.apply(this);
};
gobject.signalNew('capture', gtk.Object, [], null, null);
gobject.signalNew('bubble', gtk.Object, [], null, null);
/**
* gtk.Widget class : the base class of all widget
*/
gtk.Widget = function() {
	gtk.Object.apply(this);
    var self = this;
	this._domObj;
	this._minWidth = 16;
	this._minHeight = 16;
	this._width = this._minWidth;
	this._height = this._minHeight;
	this._isMinWidthChanged = false;
	this._isMinHeightChanged = false;
	this._activated = false;
	this._domObj;
	this._signalName = "";
	this._render = function(){
		this._domObj = jsgtk.Dom.create({tag: "div", className: "gtk_widget"});
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this._domObj.style.boder = "1px";
        this._domObj.style.position = "relative";
	};

	this._render();

	jsgtk.Event.addDomListener(this._domObj, "click", function(){
	    self.emit("buttonpressevent");
	}, false);

	jsgtk.Event.addDomListener(this._domObj, "mouseover", function(){
	    self.emit("enternotifyevent");
	}, false);

	jsgtk.Event.addDomListener(this._domObj, "mouseout", function(){
	    self.emit("leavenotifyevent");
	}, false);

	this.connect("bubble", function(width, height){
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
	});
};

gtk.Widget.prototype = new gtk.Object();
gtk.Widget.prototype.constructor = gtk.Widget;

/**
* setBoldTitle() method : option bold title
* @param boolen
*/
gtk.Widget.prototype.setBoldTitle = function(bold){
	if(bold){
		this._domTitle.style.fontWeight = "bold";
	} else 	this._domTitle.style.fontWeight = "normal";
};

gtk.Widget.prototype.getNode = function(){
	return this._domObj;
};

/**
* show() method : turn the widget on
*/
gtk.Widget.prototype.show = function(){
	this._domObj.style.display = "";
};

/**
* show() method : turn the widget off
*/
gtk.Widget.prototype.hide = function(){
	this._domObj.style.display = "none";
};

/**
* The activate() method emits the "activate" signal on the widget that activates it (if it can be activated).
* @return True if the widget was activatable.
*/

gtk.Widget.prototype.activate = function(){
	var signal = this.getActivateSignal();

	if(signal){
		this._activated = true;
		this.emit(signal);
	}
	else this._activated = false;

	return this._activated;
};
/**
* The get_activate_signal() method returns the name of the signal that is emitted when the widget is activated.
* @return a signal name
*/
gtk.Widget.prototype.setActivateSignal = function(signal){
	this._signalName = signal;
};

/**
* The get_activate_signal() method returns the name of the signal that is emitted when the widget is activated.
* @return a signal name
*/
gtk.Widget.prototype.getActivateSignal = function(){
	return this._signalName;
};

/**
* setSizeRequest() method : reset the min width and min height of widget
*						  : and emit 'sizerequest' signal
* @param {integer} width  : new width of widget
* @param {integer} height : new height of widget
*/
gtk.Widget.prototype.setSizeRequest = function(width, height){
	this._isMinWidthChanged = width ? true : false;
	this._isMinHeightChanged = height ? true : false;

	this._minHeight = height;
	this._minWidth = width;
	this.emit('sizerequest', this._width, this._height);
};

/**
* setSize() method 		  : set the width and height of widget and emit signal 'bubble'
*                    		signal 'bubble' will inform this widget's parent about it new size
* @param {integer} width  : new width of widget
* @param {integer} height : new height of widget
*/
gtk.Widget.prototype.setSize = function(width, height){
	this._height = height;
	this._width = width;
	this.emit('bubble', this._width, this._height);
};

/**
* setWidth() method      : set new width to widget
* @param {integer} width : new width of widget
*/
gtk.Widget.prototype.setWidth = function(width){
	this._width = width;
};

/**
* getWidth() method       : return the current width to widget
* @return {integer} width : width of widget
*/
gtk.Widget.prototype.getWidth = function(){
	return this._width;
};

/**
* setHeight() method      : set new height to widget
* @param {integer} height : the height of widget
*/
gtk.Widget.prototype.setHeight = function(height){
	this._height = height;
};

/**
* getHeight() method       : return the current height to widget
* @return {integer} height : the height of widget
*/
gtk.Widget.prototype.getHeight = function(){
	return this._height;
};

/**
* getSizeRequest() method : return the min widht and min height of widget
* @return {array} size	  : array of min width and min height
*/
gtk.Widget.prototype.getSizeRequest = function(){
	return [this._minWidth, this._minHeight];
};

gtk.Widget.prototype.sizeRequest = function(){
	return [
		this._width,
		this._height
	];
};

/**
* getSize() method    : return an array of current width and height
* @param {array} size : array of width and height
*/
gtk.Widget.prototype.getSize = function(){
	return [
		this._width,
		this._height
	];
};

/**
* _resizeHeight() method  : Resize the height of widget's dom object and height
* @param {integer} height : the new of height of widget
*/
gtk.Widget.prototype._resizeHeight = function(height){
	this._domObj.style.height = height + 'px';
	this._height = height;
};

/**
* _resizeWidth() method   : Resize the width of widget's dom object and width
* @param {integer} height : the new of height of widget
*/
gtk.Widget.prototype._resizeWidth = function(width){
	this._domObj.style.width = width + 'px';
	this._width = width;
};

gtk.Widget.prototype.getMinWidthComposite = function(){
	return this._minWidth;
};

gtk.Widget.prototype.getMinHeightComposite = function(){
	return this._minHeight;
};

gtk.Widget.prototype.resizeWidthComposite = function(width){
	this._width = width;
	this._domObj.style.width = this._width + 'px';
};

gtk.Widget.prototype.resizeHeightComposite = function(height){
	this._height = height;
	this._domObj.style.height = this._height + 'px';
};

gtk.Widget.prototype.resetHeightComposite = function(){
	var minSize = this.getSizeRequest();
	this.setHeight(minSize[1]);
};

gtk.Widget.prototype.resetWidthComposite = function(){
	var minSize = this.getSizeRequest();
	this.setWidth(minSize[0]);
};

gobject.signalNew('bubble', gtk.Widget, [], null, null);
gobject.signalNew('capture', gtk.Widget, [], null, null);
gobject.signalNew('sizerequest', gtk.Widget, [], null, null);
gobject.signalNew('resize', gtk.Widget, [], null, null);
gobject.signalNew('buttonpressevent', gtk.Widget, [], null, null);
gobject.signalNew('enternotifyevent', gtk.Widget, [], null, null);
gobject.signalNew('leavenotifyevent', gtk.Widget, [], null, null);
gtk.Misc = function() {
	gtk.Widget.apply(this);
	this._render = function(){
		this._domObj.className += " gtk_misc";
		this.hide();
	};

	/**
	 * Render
	 */
	this._render();
};

gtk.Misc.prototype = new gtk.Widget();
gtk.Misc.prototype.constructor = gtk.Misc;
gtk.Container = function() {
	gtk.Widget.apply(this);
	this._child = null;
	this.borderWidth = 2 ;

	this._render = function(){
		this._domObj.className += " gtk_container";
		this.hide();
	};

	this._render();
};

gtk.Container.prototype = new gtk.Widget();
gtk.Container.prototype.constructor = gtk.Container;

gtk.Container.prototype.add = function(widget){
	if(!this._child){
		this._child = widget;
		if(widget._domObj) this._domObj.appendChild(widget._domObj); //Save testing headache
	}else{
	}
};

gtk.Container.prototype.remove = function(widget){
	if(this._child === widget){
		this._child = null;
		if(widget._domObj) this._domObj.removeChild(widget._domObj); //Save testing headache
	}else{
	}
};

gtk.Container.prototype.getBorderWidth = function(){
	return this.borderWidth;
};

gtk.Container.prototype.setBorderWidth = function(value){
	this.borderWidth = value;
	this._domObj.style.padding = value + "px";
};

gobject.signalNew('add', gtk.Container, [], null, null);
gtk.Bin = function(){
	gtk.Container.apply(this);
	this.child = null;

	this.getChild = function(){ return this.child; }

	this._render = function(){
		this._domObj.className += ' bin';
	}

	this._render();
};

gtk.Bin.prototype = new gtk.Container();
gtk.Bin.prototype.constructor = gtk.Bin;
/**
*	Class gtk.Window - Create a horizontal box
*/
gtk.Window = function(type) {

	gtk.Bin.apply(this);

	var self = this;
	this._minWidth = this._width = 100;
	this._minHeight = this._height = 100;
	this._top = 0;
	this._child = null;
	this._headerHeight = 27;
	this._bodyHeight = this._height - this._headerHeight;
	this._bodyWidth = this._width - 2

	this._render = function(){
        this._domObj.className += " gtk_window";
        this._domObj.style.position = "absolute";
            this._topLeftBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_top_left_border"});
            this._topBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_top_border"});
            this._topRightBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_top_right_border"});
            this._leftBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_left_border"});
            this._bottomLeftBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_bottom_left_border"});
            this._bottomBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_bottom_border"});
            this._bottomRightBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_bottom_right_border"});
            this._rightBorder = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_right_border"});

            this._header = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_header"});
                var headerGradient = jsgtk.Dom.create({"append": this._header, "tag":"div"});
                    this._domTitle = jsgtk.Dom.create({"append":this._header, "tag":"span", "className": "gtk_window_title"});
                    this._minimizeButton = jsgtk.Dom.create({"append": this._header, "tag": "div","className" : "gtk_window_header_minimize_button"});
                    this._closeButton = jsgtk.Dom.create({"append": this._header, "tag": "div","className" : "gtk_window_header_close_button"});

            this._body = jsgtk.Dom.create({"append": this._domObj, "tag":"div", "className": "gtk_window_body"});
            this._body.style.width = this._bodyWidth + 'px';
            this._body.style.height = this._bodyHeight + 'px';

        this._domObj.style.width = this._width + "px";
        this._domObj.style.height = this._height + "px";
        this._arrangeBorder();
        this._createGhostWindow();
	    this._moveWindow();
	    this._windowTopResize();
	    this._windowBottomResize();
	    this._windowLeftResize();
	    this._windowRightResize();
	    this._windowTopLeftResize();
	    this._windowTopRightResize();
	    this._windowBottomLeftResize();
	    this._windowBottomRightResize();

	}

	this._render();

	jsgtk.Event.addDomListener(this._closeButton, "mousedown", function(e){
        self._domObj.parentNode.removeChild(self._domObj);
        self._ghostWindow.parentNode.removeChild(self._ghostWindow);
        self._domObj = null;
        jsgtk.Event.stopBubble(e);
    });

    jsgtk.Event.addDomListener(this._minimizeButton, "mousedown", function(e){
        var _self = self;
        var minimizeWindow = self._header.cloneNode(true);
        minimizeWindow.className = "gtk_window_minimize";
        minimizeWindow.removeAttribute("style");
        self._domObj.style.display = "none";
        var id = "gtk_minimized_widget_holder";
        var holder = document.getElementById(id);
        if(!holder) var holder = jsgtk.Dom.create({"append": document.body, "tag": "div", "id": id});

        holder.appendChild(minimizeWindow);

        var restoreButton = minimizeWindow.childNodes[2];
        jsgtk.Event.addDomListener(restoreButton, "click", function(){
            self._domObj.style.display = "";
            minimizeWindow.parentNode.removeChild(minimizeWindow);
        });

        var closeButton = minimizeWindow.childNodes[3];
        jsgtk.Event.addDomListener(closeButton, "click", function(){
            self._domObj.parentNode.removeChild(self._domObj);
            self._ghostWindow.parentNode.removeChild(self._ghostWindow);
            self._domObj = null;
            minimizeWindow.parentNode.removeChild(minimizeWindow);
        });

        jsgtk.Event.stopBubble(e);
    });
};

gtk.Window.prototype = new gtk.Bin();
gtk.Window.prototype.constructor = gtk.Window;

gtk.Window.prototype._arrangeBorder = function(){
    this._bottomBorder.style.top = this._height + "px";
    this._bottomBorder.style.left = 4 + "px";
    this._bottomBorder.style.width = this._width - 3 + "px";
    this._rightBorder.style.top =  4 + "px";
    this._rightBorder.style.left = this._width + 4 +"px";
    this._rightBorder.style.height = this._height - 4 + "px";
    this._topBorder.style.width = this._width + "px";
    this._topRightBorder.style.left = this._width + 3 + "px";
    this._leftBorder.style.height = this._height - 8 + "px";
    this._bottomLeftBorder.style.top = this._height + "px";
    this._bottomRightBorder.style.top = this._height + "px";
    this._bottomRightBorder.style.left = this._width + 2 + "px";
}

gtk.Window.prototype.setTitle = function(title){
    this._domTitle.innerHTML = title;
};

gtk.Window.prototype.move = function(left, top){
    this._domObj.style.top = top + "px";
    this._domObj.style.left = left + "px";
};

gtk.Window.prototype.setPosition = function(position){
    if(position == "center"){
        var left = (jsgtk.Util.windowWidth() - this._width )/2;
        var top = (jsgtk.Util.windowHeight() - this._height )/2;
        if(top < 0) top = 0;
        this.move(left,top);
    }
}

gtk.Window.prototype._moveWindow = function(){
    var self = this;
    var left = 0;
    var top  = 0;


    jsgtk.Dom.dragInit(this._header, left, jsgtk.Util.getWindowWidth() - this._width, top, jsgtk.Util.getWindowHeight() - this._height);

    this._header.onDragStart = function(){
		self._showGhostWindow();
	};

	this._header.onDrag = function(x, y){
	     self._moveGhostWindow(x, y);

	};

	this._header.onDragEnd = function(x, y){
	     self._domObj.style.left = x + "px";
	     self._domObj.style.top = y + "px";
	     self._hideGhostWindow();
	     self._resetResizeEvent();
	};
};

gtk.Window.prototype._windowTopResize = function(){
    var self = this;
    var top = 0 - parseInt(this._domObj.style.top) || 0;
    var maxY = this._child ? (this._height - this._child.getMinHeightComposite()) - this._headerHeight : this._minHeight;

    jsgtk.Dom.vDragInit(this._topBorder, top, maxY);
    this._topBorder.style.left = "";
	this._topBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._topBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._topBorder.onDrag = function(x, y){
	    self._topResizeGhostWindow(x, y);
	};

	this._topBorder.onDragEnd = function(x, y){
	    var height = parseInt(self._ghostWindow.style.height)
	    self._domObj.style.top = parseInt(self._ghostWindow.style.top) + "px";
	    self.resizeHeightComposite(height);
	    self._domObj.removeChild(self.x)
        self._hideGhostWindow();
        self._topBorder.style.top = "0px";
        self._arrangeBorder();
        self._resetResizeEvent();
	};

};

gtk.Window.prototype._windowBottomResize = function(){
    var self = this;
    var top = 0 - parseInt(this._domObj.style.top) || 0;
    var maxY = jsgtk.Util.getWindowHeight() + top - 5;
    var minY = this._child ? this._child.getMinHeightComposite() : this._minHeight;

    jsgtk.Dom.vDragInit(this._bottomBorder, minY + this._headerHeight, maxY);
	self._bottomBorder.style.left = "";
	this._bottomBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._bottomBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._bottomBorder.onDrag = function(x, y){
	    self._bottomResizeGhostWindow(x, y);
	};

	this._bottomBorder.onDragEnd = function(x, y){
	    var height = parseInt(self._ghostWindow.style.height)
	    self._domObj.style.top = parseInt(self._ghostWindow.style.top) + "px";
	    self.resizeHeightComposite(height);
	    self._domObj.removeChild(self.x);
	    self._arrangeBorder();
        self._hideGhostWindow();
        self._resetResizeEvent();
	};
};

gtk.Window.prototype._windowLeftResize = function(){
    var self = this;
    var left = 0 - parseInt(this._domObj.style.left) || 0;
    var maxX = this._child ? this._width - this._child.getMinWidthComposite() : this._minWidth;
    jsgtk.Dom.hDragInit(this._leftBorder, left, maxX);

	this._leftBorder.style.top = "";

	this._leftBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._leftBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._leftBorder.onDrag = function(x, y){
	    self._leftResizeGhostWindow(x, y);
	};

	this._leftBorder.onDragEnd = function(x, y){
	    var width = parseInt(self._ghostWindow.style.width);
        self._domObj.style.left = parseInt(self._ghostWindow.style.left) + "px";
        self.resizeWidthComposite(width);

	    self._domObj.removeChild(self.x)
        self._hideGhostWindow();
        self._leftBorder.style.left = "0px";
   	    self._arrangeBorder();
        self._resetResizeEvent();
	};
}

gtk.Window.prototype._windowRightResize = function(){
    var self = this;
    var left = 0 - parseInt(this._domObj.style.left) || 0;
    var maxX = jsgtk.Util.getWindowWidth() + left - 5;
    var minX = this._child ? this._child.getMinWidthComposite() : this._minWidth;
    jsgtk.Dom.hDragInit(this._rightBorder, minX, maxX);
	this._rightBorder.style.top = "";
	this._rightBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._rightBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._rightBorder.onDrag = function(x, y){
	    self._rightResizeGhostWindow(x, y);
	};

	this._rightBorder.onDragEnd = function(x, y){
	    var width = parseInt(self._ghostWindow.style.width);
        self._domObj.style.left = parseInt(self._ghostWindow.style.left) + "px";
        self.resizeWidthComposite(width);
	    self._domObj.removeChild(self.x);
	    self._arrangeBorder();
        self._hideGhostWindow();
        self._resetResizeEvent();
	};
};

gtk.Window.prototype._windowTopLeftResize = function(){
    var self = this;

    var left = 0 - parseInt(this._domObj.style.left) || 0;
    var maxX = this._child ? this._width - this._child.getMinWidthComposite() : this._minWidth;

    var top = 0 - parseInt(this._domObj.style.top) || 0;
    var maxY = this._child ? (this._height - this._child.getMinHeightComposite()) - this._headerHeight : this._minHeight;

    jsgtk.Dom.dragInit(this._topLeftBorder, left, maxX, top, maxY);
    this._topLeftBorder.style.left = "0px";
    this._topLeftBorder.style.top = "0px";

	this._topLeftBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._topLeftBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	    self._ghostWindow.style.cursor = "nw-resize";
	};

	this._topLeftBorder.onDrag = function(x, y){
	    self._topLeftResizeGhostWindow(x, y);
	};

	this._topLeftBorder.onDragEnd = function(x, y){
	    var width = parseInt(self._ghostWindow.style.width);
        self._domObj.style.left = parseInt(self._ghostWindow.style.left) + "px";

        var height = parseInt(self._ghostWindow.style.height)
	    self._domObj.style.top = parseInt(self._ghostWindow.style.top) + "px";

	    self.resizeWidthHeightComposite(width, height);

	    self._domObj.removeChild(self.x)
        self._hideGhostWindow();
        self._topBorder.style.top = "0px";
        self._arrangeBorder();
        self._resetResizeEvent();
	};
};

gtk.Window.prototype._windowTopRightResize = function(){
    var self = this;

    var top = 0 - parseInt(this._domObj.style.top) || 0;
    var maxY = this._child ? (this._height - this._child.getMinHeightComposite()) - this._headerHeight : this._minHeight;

    var left = 0 - parseInt(this._domObj.style.left) || 0;
    var maxX = jsgtk.Util.getWindowWidth() + left - 5;
    var minX = this._child ? this._child.getMinWidthComposite() : this._minWidth;

    jsgtk.Dom.dragInit(this._topRightBorder, minX, maxX, top, maxY);

	this._topRightBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._topRightBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._topRightBorder.onDrag = function(x, y){
	    self._topRightResizeGhostWindow(x, y);
	};

	this._topRightBorder.onDragEnd = function(x, y){

	    var width = parseInt(self._ghostWindow.style.width);
        self._domObj.style.left = parseInt(self._ghostWindow.style.left) + "px";

	    var height = parseInt(self._ghostWindow.style.height)
	    self._domObj.style.top = parseInt(self._ghostWindow.style.top) + "px";

        self.resizeWidthHeightComposite(width, height);

	    self._domObj.removeChild(self.x)
        self._hideGhostWindow();
        self._arrangeBorder();
        self._topRightBorder.style.top = "0px";
        self._resetResizeEvent();
	};

};

gtk.Window.prototype._windowBottomLeftResize = function(){
    var self = this;

    var top = 0 - parseInt(this._domObj.style.top) || 0;
    var maxY = jsgtk.Util.getWindowHeight() + top - 5;
    var minY = this._child ? this._child.getMinHeightComposite() : this._minHeight;

    var left = 0 - parseInt(this._domObj.style.left) || 0;
    var maxX = this._child ? this._width - this._child.getMinWidthComposite() : this._minWidth;

    jsgtk.Dom.dragInit(this._bottomLeftBorder, left, maxX, minY + this._headerHeight, maxY);

	this._bottomLeftBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._bottomLeftBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._bottomLeftBorder.onDrag = function(x, y){
	    self._bottomLeftResizeGhostWindow(x, y);
	};

	this._bottomLeftBorder.onDragEnd = function(x, y){
        var width = parseInt(self._ghostWindow.style.width);
        self._domObj.style.left = parseInt(self._ghostWindow.style.left) + "px";

	    var height = parseInt(self._ghostWindow.style.height)
	    self._domObj.style.top = parseInt(self._ghostWindow.style.top) + "px";

	    self.resizeWidthHeightComposite(width, height);

	    self._domObj.removeChild(self.x);

	    self._hideGhostWindow();
	    self._arrangeBorder();
	    self._bottomLeftBorder.style.left = "0px";
        self._resetResizeEvent();
	};
};

gtk.Window.prototype._windowBottomRightResize = function(){
    var self = this;

    var top = 0 - parseInt(this._domObj.style.top) || 0;
    var maxY = jsgtk.Util.getWindowHeight() + top - 5;
    var minY = this._child ? this._child.getMinHeightComposite() : this._minHeight;

    var left = 0 - parseInt(this._domObj.style.left) || 0;
    var maxX = jsgtk.Util.getWindowWidth() + left - 5;
    var minX = this._child ? this._child.getMinWidthComposite() : this._minWidth;

    jsgtk.Dom.dragInit(this._bottomRightBorder, minX, maxX, minY + this._headerHeight, maxY);

	this._bottomRightBorder.onDragStart = function(){
	    self._showGhostWindow();
	    self.x = self._bottomRightBorder.cloneNode(true);
	    self._domObj.appendChild(self.x);
	};

	this._bottomRightBorder.onDrag = function(x, y){
	    self._bottomRightResizeGhostWindow(x, y);
	};

	this._bottomRightBorder.onDragEnd = function(x, y){
	    var width = parseInt(self._ghostWindow.style.width);
        self._domObj.style.left = parseInt(self._ghostWindow.style.left) + "px";

	    var height = parseInt(self._ghostWindow.style.height)
	    self._domObj.style.top = parseInt(self._ghostWindow.style.top) + "px";

	    self.resizeWidthHeightComposite(width, height);

        self._domObj.removeChild(self.x);
	    self._hideGhostWindow();
	    self._arrangeBorder();
        self._resetResizeEvent();
	};
}

gtk.Window.prototype._resetResizeEvent = function(){
    this._updateGhostWindow();
    this._moveWindow();
    this._windowTopResize();
    this._windowBottomResize();
    this._windowLeftResize();
    this._windowRightResize();
    this._windowTopLeftResize();
    this._windowTopRightResize();
    this._windowBottomLeftResize();
    this._windowBottomRightResize();
}

gtk.Window.prototype._createGhostWindow = function(){
    this._ghostWindow = jsgtk.Dom.create({"append": document.body, "tag": "div"});
    this._ghostWindow.className = "gtk_window_ghost";
}

gtk.Window.prototype._showGhostWindow = function(){
    this._updateGhostWindow();
    this._ghostWindow.style.display = "block";
};

gtk.Window.prototype._updateGhostWindow = function(){
    this._ghostWindow.style.height = this._domObj.style.height;
    this._ghostWindow.style.width = this._domObj.style.width;
    this._ghostWindow.style.left = this._domObj.style.left || "0px";
    this._ghostWindow.style.top = this._domObj.style.top || "0px";
    this._ghostWindow.style.border = "1px solid #bdd3f0";
}

gtk.Window.prototype._moveGhostWindow = function(x, y){
    this._ghostWindow.style.left = x + "px";
    this._ghostWindow.style.top = y + "px";
};

gtk.Window.prototype._topResizeGhostWindow = function(x, y){
    this._ghostWindow.style.height = parseInt(this._domObj.style.height) - y + "px";
    this._ghostWindow.style.top = parseInt(this._domObj.style.top) + y + "px";
};

gtk.Window.prototype._bottomResizeGhostWindow = function(x, y){
    this._ghostWindow.style.height =  y + "px";
};

gtk.Window.prototype._leftResizeGhostWindow = function(x, y){
    this._ghostWindow.style.width =  parseInt(this._domObj.style.width) - x + "px";
    this._ghostWindow.style.left = parseInt(this._domObj.style.left) + x + "px";
};

gtk.Window.prototype._rightResizeGhostWindow = function(x, y){
    this._ghostWindow.style.width =  x + "px";
};

gtk.Window.prototype._topLeftResizeGhostWindow = function(x, y){
    this._ghostWindow.style.height = parseInt(this._domObj.style.height) - y + "px";
    this._ghostWindow.style.top = parseInt(this._domObj.style.top) + y + "px";
    this._ghostWindow.style.width =  parseInt(this._domObj.style.width) - x + "px";
    this._ghostWindow.style.left = parseInt(this._domObj.style.left) + x + "px";
};

gtk.Window.prototype._topRightResizeGhostWindow = function(x,y){
    this._ghostWindow.style.height = parseInt(this._domObj.style.height) - y + "px";
    this._ghostWindow.style.top = parseInt(this._domObj.style.top) + y + "px";
    this._ghostWindow.style.width =  x + "px";
};

gtk.Window.prototype._bottomLeftResizeGhostWindow = function(x, y){
    this._ghostWindow.style.height =  y + "px";
    this._ghostWindow.style.width =  parseInt(this._domObj.style.width) - x + "px";
    this._ghostWindow.style.left = parseInt(this._domObj.style.left) + x + "px";
};

gtk.Window.prototype._bottomRightResizeGhostWindow = function(x, y){
    this._ghostWindow.style.width =  x + "px";
    this._ghostWindow.style.height =  y + "px";
};

gtk.Window.prototype._hideGhostWindow = function(){
    this._ghostWindow.style.display = "none";
};

gtk.Window.prototype.add = function(widget){
	if(!this._child){
		this._child = widget;
		this._body.appendChild(widget._domObj);

        var width  = this._width  > widget.getMinWidthComposite() ? this._width : widget.getMinWidthComposite();
        var height = this._height - this._headerHeight > widget.getMinHeightComposite()? this._height : widget.getMinHeightComposite() + this._headerHeight;
		this.resizeWidthComposite(width);
		this.resizeHeightComposite(height);
		this._arrangeBorder();
		this.emit("add");
	}else{
	}
};


gtk.Window.prototype._resizeHeight = function(height){
    this._height = height + 2;
    this._domObj.style.height = height + 7 + "px";
        this._body.style.height = height - this._headerHeight + 'px';
        this._body.style.top = "1px";
        this._bodyHeight = height - this._headerHeight;
};

gtk.Window.prototype._resizeWidth = function(width){
    this._width = width + 3 ;
    this._domObj.style.width = width + 10 + "px";
        this._bodyWidth = width - 2;
        this._body.style.width = this._bodyWidth + 'px';
        this._body.style.left = "5px";

};

gtk.Window.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
    this._child.resizeWidthComposite(width);
    this._child.resizeHeightComposite(height - this._headerHeight);
    this._resetResizeEvent();
};

gtk.Window.prototype.getMinHeightComposite = function(){
    var height = this._minHeight;
    var childHeight = this._child.getMinHeightComposite();
    height = height > childHeight ? height : childHeight ;
    return height;
};

gtk.Window.prototype.getMinWidthComposite = function(){
    var width = this._minWidth;
    var childWidth = this._child.getMinWidthComposite();
    width = width > childWidth ? width : childWidth ;
    return width;
};

gtk.Window.prototype.resizeWidthComposite = function(width){

	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	this.resize(minWidth, this._height);
};

gtk.Window.prototype.resizeHeightComposite = function(height){

	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this.resize(this._width, minHeight);
};

gtk.Window.prototype.resizeWidthHeightComposite = function(width, height){

    var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this.resize(minWidth, minHeight);
};
gtk.Box = function(homogeneous, spacing) {
	gtk.Container.apply(this);

	/* This properties to be inherited by gtk.VBox and gtk.HBox */
	this._homogeneous = (homogeneous === undefined) ? false : homogeneous;
	this._spacing = (spacing === undefined || spacing == 0) ? 0 : spacing;
	this._children = [];
	this._minWidth = 20;
	this._minHeight = 10;
	this._width = this._minWidth;
	this._height = this._minHeight;

	this._render = function(){
	    var domObj = this._domObj
		domObj.className += " box";
		domObj.style.width = this._width + 'px';
		domObj.style.height = this._height + 'px';

		this.hide();
	};

	this._render();
};

gtk.Box.prototype = new gtk.Container();
gtk.Box.prototype.constructor = gtk.Box;



/**
*	Packed with reference to the start of box. The child is packed after any other child packed with reference to the start of box.
*	@param {object} child-widgets 	: [{child, expand, fill, padding, packType}, ...]
*									  - child   : a widget
*									  - expaned : make the space given to a child widget expand to fill the vbox available space
*									  - padding : the size of top and bottom padding of a widget
*									  - packType: type of packing the child to vbox eg. gtk.PACK_START or gtk.PACK_END
*/
gtk.Box.prototype.packChildren = function(children) {

		for(var i = 0, len = children.length; i < len; i++){
			var child = children[i];

			child['packType'] = child['packType'] === undefined ? gtk.PACK_START : child['packType'];
			child['expand'] = child['expand'] === undefined ? true : child['expand'];
			child['padding'] = child['padding'] === undefined ? 0 : child['padding'];
			child['fill'] = child['fill'] === undefined ? true : child['fill'];
			child['width'] = child.child.getWidth();
			child['height'] = child.child.getHeight();

			var element = this._createElement(child.packType);

			var space = this._createSpace();

			child['element'] = element;
			child['space'] = space;
			this._children.push(child);

			this._appendPackChild(element, space);
		}

		this.resize(this._width, this._height);

};

/**
* Packed with reference to the start of box. The child is packed after any other child packed with reference to the start of box.
* @param {gtk.Widget} child The widget to be added to the box
* @param {Boolean} expand True if child is to be given extra space allocated to box. The extra space will be divided evenly between all children of box that use this option
* @param {boolean} fill True if space given to child by the expand option is actually allocated to child, rather than just padding it. This parameter has no effect if expand is set to False. A child is always allocated the full height of a gtk.HBox and the full width of a gtk.VBox
* @param {integer} padding Extra space in pixels to put between child and its neighbors, over and above the global amount specified by spacing in gtk.Box. If child is a widget at one of the reference ends of box, then padding pixels are also put between child and the reference edge of box.
*/
gtk.Box.prototype.packStart = function(child, expand, fill, padding) {
	this._packChild(child, expand, fill, padding, gtk.PACK_START);
};

/**
* Adds child to the box, packed with reference to the end of the box. The child is packed after (away from end of) any other child packed with reference to the end of the box.
* @param {gtk.Widget} The widget to be added to the box
* @param {boolean} expand True if child is to be given extra space allocated to box. The extra space will be divided evenly between all children of box that use this option.
* @param {boolean} fill True if space given to child by the expand option is actually allocated to child, rather than just padding it. This parameter has no effect if expand is set to False. A child is always allocated the full height of a gtk.HBox and the full width of a gtk.VBox. This option affects the other dimension.
* @param {integer} padding Extra space in pixels to put between child and its neighbors, over and above the global amount specified by spacing in gtk.Box. If child is a widget at one of the reference ends of box, then padding pixels are also put between child and the reference edge of box.
*/
gtk.Box.prototype.packEnd = function(child, expand, fill, padding) {
	this._packChild(child, expand, fill, padding, gtk.PACK_END);
};

/*
* Sets the number of pixels to place between children of the box
* @param {integer} spacing the number of pixels to put between children
*/
gtk.Box.prototype.setSpace = function(spacing) {
	this._spacing = spacing;
	if(this._children.length > 1 ) this.resize(this._width, height);
};

/**
* returns the number of pixels used as padding between children as set by the set_spacing()
* @return {integer} The spacing in pixels between children
*/
gtk.Box.prototype.getSpace = function() {
	return this._spacing;
};

/**
* Queray child information, contains: expand, fill, padding and packtype
* @param{gtk.Widget} child The child widget to be queried for its packing information
*/
gtk.Box.prototype.queryChildPacking = function(child){
	var children = this._children;
	for(var i = 0, len = children.length; i < len; i++){
		if(children[i].child === child) return children[i];
	}
};

/**
* Pack the child from top to bottom widht default expend: true, fill: true, padding: 0
* @param{gtk.Widget} child The widget to be added to the box
*/
gtk.Box.prototype.packStartDefaults = function(child) {
	this.packStart(child);
};

/**
* Pack the child from bottom to top widht default expend: true, fill: true, padding: 0
* @param{gtk.Widget} child The widget to be added to the box
*/
gtk.Box.prototype.packEndDefaults = function(child) {
	this.packEnd(child);
};

/**
*	Sets the homogeneous (all children are allocated the same space) property of the box.
*	@param{boolean} homogeneuous If True the box is homogeneous i.e. all children are allocated the same space otherwise the allocations vary for each child.
*/
gtk.Box.prototype.setHomogeneous = function(homogeneous){
	this._homogeneous = homogeneous;
	this.resize(this._width, this._height);
};

/**
*	Returns whether the box is homogeneous (all children are allocated the same space)
*	@return {boolean} True if the box is homogeneous.
*/
gtk.Box.prototype.getHomogeneous = function(){
	return this._homogeneous;
};

/**
* Reorder child to new position of same packtype
* @param{gtk.Widget} childDom The child widget to move
* @param{integer} position The new position for child in the children list of the box starting from 0. If negative, indicates the end of the list
*/
gtk.Box.prototype.reorderChild = function(childDom, position) {

	var child  = this._isChild(childDom._domObj.parentNode.parentNode);

	var targetChild = this._isChild(this._getChildDomByPos(position, child.packType));
	if(child.packType != targetChild.packType) return;
	if(child === targetChild) return;

	var node1 = jsgtk.Dom.create({append: this._domObj, tag: 'div'});
	var node2 = jsgtk.Dom.create({append: this._domObj,tag: 'div'});

	this._domObj.replaceChild(node2, targetChild.element);
	this._domObj.replaceChild(node1, child.element);

	this._domObj.appendChild(child.element);
	this._domObj.appendChild(targetChild.element);

	this._domObj.replaceChild(child.element, node2);
	this._domObj.replaceChild(targetChild.element, node1);
};


gtk.Box.prototype.setSize = function(width, height){

	this._height = height;
	this._width = width;

	if(this._children.length > 0){
		this.resize(this._width, this._height);
	}
};


gtk.Box.prototype._packChild = function(child, expand, fill, padding, packType){

	var element = this._createElement(packType);

	var space = this._createSpace();

	this._appendPackChild(element, space);

	this._children.push({
		"element": element,
		"child": child,
		"space": space,
		"expand": (expand === undefined) ? true : expand,
		"fill": fill = (fill === undefined) ? true : fill,
		"padding": (padding === undefined) ? 0 : padding,
		"packType": packType,
		"width": child.getWidth(),
		"height": child.getHeight()
	});

	this.resize(this._width, this._height);

	this.emit('bubble', this._width, this._height);

	this._connectChildrenSignal();
};

gtk.Box.prototype._connectChildrenSignal = function(){
    var children = this._children, len = children.length;
    var self = this;
    for(var i = len; i--;){
        children[i].child.connect("bubble", function(width, height){
        	self.resize(self._width, self._height);
        	self.emit('bubble', self._width, self._height);
        	self.setSize( parseInt(self._domObj.style.width), parseInt(self._domObj.style.height) );
        });
    }
};

gtk.Box.prototype._appendPackChild = function(element, space){
	var lastPackEnd = this._getLastPackEndChild();
	var domObj = this._domObj;
	if(lastPackEnd){
		domObj.insertBefore(element, lastPackEnd.element);
		domObj.insertBefore(space, lastPackEnd.element);
	}else{
		domObj.appendChild(element);
		domObj.appendChild(space);
	}
};

gtk.Box.prototype._isChild = function(dom){
	var children = this._children, child;
	for(var i = children.length; i-- ;){
		if(children[i].element === dom) return children[i];
	}
	return false;
};

gtk.Box.prototype._getChildDomByPos = function(pos, packType){
	var childNodes = this._domObj.childNodes, children = [], packEndChildren = [];
	for(var i = 0, len = childNodes.length; i < len; i++){
		if(i % 2 === 0) children.push(childNodes[i]);
	}
	for(var i = 0, len = children.length; i < len; i++){
		if(children[i]['className'] === gtk.PACK_END) packEndChildren.push(children[i]);
	}
	return (packType === gtk.PACK_END) ? packEndChildren[len - 1 - pos] : children[pos];
};

gtk.Box.prototype._getLastPackEndChild = function(){
	var children = this._children, child, packEndChildren = [];
	for(var i = 0, len = children.length; i < len; i++){
		child = children[i];
		if(child.packType === gtk.PACK_END) packEndChildren.push(child);
	}
	return packEndChildren[packEndChildren.length - 1];
};

gtk.Box.prototype._hideLastSpace = function(){
	var childNodes = this._domObj.childNodes;
	var lastSpace = childNodes[childNodes.length - 1];
	jsgtk.Dom.hideElement(lastSpace);
};

gtk.Box.prototype.getMinWidth = function(){
	return this._minWidth;
};

gtk.Box.prototype.getMinHeight = function(){
	return this._minHeight;
};


gtk.Box.prototype.resize = function(width, height){

	this._resizeHeight(height);
	this._resizeWidth( width);
	this._homogeneous ? this._handleH() : this._handleNH();

	var children = this._children, len = children.length;
	for(var i = len; i--;){
	    var child = children[i].child;
        child.resizeHeightComposite(children[i].height);
        child.resizeWidthComposite(children[i].width);
    }
};

gtk.Box.prototype.resetWidthComposite = function(){

	var minSize = this.getSizeRequest();
	this.setWidth(minSize[0]);

	var children = this._children;
	for(var i = children.length; i--;){
		children[i]['child'].resetWidthComposite();
	}
};

gtk.Box.prototype.resetHeightComposite = function(){

	var minSize = this.getSizeRequest();
	this.setHeight(minSize[1]);

	var children = this._children;
	for(var i = children.length; i--;){
		children[i]['child'].resetHeightComposite();
	}
};
/**
*	Class gtk.HBox - Create a horizontal box
*	@param {boolean} homogeneous - resovle to true will divide hbox into equally height small hboxs
*	@param {integer} spacing - number of pixel of space height between hboxs
*/
gtk.HBox = function(homogeneous, spacing) {
	gtk.Box.apply(this, arguments);

	this._domObj.className += " gtk_hbox";
};

gtk.HBox.prototype = new gtk.Box();
gtk.HBox.prototype.constructor = gtk.HBox;

gtk.HBox.prototype._getChildWidth = function(child){
	return (child.child.getMinWidthComposite()) + ( 2 * child.padding );
};

gtk.HBox.prototype._resizeElement = function(element, domObj, width, height, padding){

	var leftPadding = element.childNodes[0];
	var body = element.childNodes[1];
	var rightPadding = element.childNodes[2];
	var bodyWidth = width - ( 2 * padding );

    var leftPaddingClone = leftPadding.cloneNode(true);
	leftPaddingClone.style.width = padding + 'px';
	leftPaddingClone.style.height = height + 'px';
	leftPadding.parentNode.replaceChild(leftPaddingClone, leftPadding);

	body.style.width = bodyWidth + 'px';
	body.style.height = height + 'px';

	body.appendChild(domObj);

    var rightPaddingClone = rightPadding.cloneNode(true);
	rightPaddingClone.style.width = padding + 'px';
	rightPaddingClone.style.height = height + 'px';
	rightPadding.parentNode.replaceChild(rightPaddingClone, rightPadding);
};

gtk.HBox.prototype._createElement = function(packType) {
	var divElement = jsgtk.Dom.create({tag: 'div', 'class': packType, style: 'float: left;'});
		var divLeftPadding = jsgtk.Dom.create({append: divElement ,tag: 'div', style: "float: left;"});
		var divChild = jsgtk.Dom.create({append: divElement ,tag: 'div', style: "float: left;"});
		var divRightPadding = jsgtk.Dom.create({append: divElement ,tag: 'div', style: "float: left;"});

	return divElement;
};

gtk.HBox.prototype._createSpace = function(){
	var divSpace = jsgtk.Dom.create({tag: 'div', style: "background-color: #fff; float: left"});
	return divSpace;
};



gtk.HBox.prototype._handleH = function(){
	var length = this._children.length;

	var size = this._getMaxChildSize();
	var totalWidth = ( size[0] * length ) + ( (length - 1) * this._spacing );
	this._resizeWidth(totalWidth);
	this._resizeHeight(size[1]);

	this._resizeWidgetsHomo(size[0], size[1]);
};

gtk.HBox.prototype._getMaxChildSize = function(){
	var children = this._children;
	var len = children.length;
	var totalSpaceWidth = ( len > 1 ) ? (len - 1) * this._spacing : 0;
	var width =  (parseInt(this._domObj.style.width) - totalSpaceWidth) / len;
	var maxWidth = width, maxHeight = parseInt(this._domObj.style.height);
	for(var i = 0; i < len; i++){
		var width = this._getChildWidth(children[i]);
		if(width > maxWidth) maxWidth = width;

		var height = parseInt(children[i].child.sizeRequest()[1]);
        if( height > maxHeight) maxHeight = height;
	}
	return [maxWidth, maxHeight];
};

gtk.HBox.prototype._resizeWidgetsHomo = function(wi, hi){
	var children = this._children, child, len = children.length;
	for(var i = 0; i < len; i++){
		child = children[i];
		child.height = hi;
		child.element.style.height = hi + 'px';
		child.element.style.width = wi + 'px';

		if(child.fill){
			child.width = wi - (2 * child.padding);
			this._resizeElement(child.element, child.child._domObj, wi, hi, child.padding);
		}else{
		    var minWidthComposite = child.child.getMinWidthComposite();
			var padding = ( wi - minWidthComposite ) / 2;
			child.width = minWidthComposite;
			this._resizeElement(child.element, child.child._domObj, wi, hi, padding);
		}

		var lastSpace = children[i].space;
		lastSpace.style.width = this._spacing + "px";
		lastSpace.style.height = hi + "px";
		jsgtk.Dom.showElement(lastSpace)
	}

	this._hideLastSpace();
};


gtk.HBox.prototype._handleNH = function(){

	var size = this._getWidgetsSizeNoHomo();

	this._resizeHeight(size[1]);
	this._resizeWidth(size[0]);

	this._resizeWidgetsNoHomo(size[0], size[1]);
};

gtk.HBox.prototype._getWidgetsSizeNoHomo = function(){
	var children = this._children, len = children.length;
	var child;
	var totalWidth = 0, maxHeight = parseInt(this._domObj.style.height);
	for(var i = 0; i < len; i++){
		child = children[i];
		totalWidth += this._getChildWidth(child);

		var height = children[i].child.sizeRequest()[1];
        if( height > maxHeight) maxHeight = height;
	}
	totalWidth = totalWidth + ( (children.length - 1) * this._spacing);
	if( totalWidth < parseInt(this._domObj.style.width) ) totalWidth = parseInt(this._domObj.style.width);
	return [totalWidth, maxHeight];
};

gtk.HBox.prototype._resizeWidgetsNoHomo = function(containerWidth, containerHeight){
	var children = this._children, len = children.length;
	var child, subTotalWidth = 0, expandElements = 0;
	var height = containerHeight;

	for(var i = 0; i < len; i++){
		child = children[i];
		if(child.expand) expandElements += 1;
		subTotalWidth += this._getChildWidth(child);
	}

	var extraExpandedWidth = (containerWidth - (subTotalWidth + (len - 1) * this._spacing) ) / expandElements;
    for(var i = 0; i < len; i++){
	    child = children[i];
	    child.height = height;

	    if(child.expand){
	        var width = this._getChildWidth(child)+ extraExpandedWidth;
		    child.element.style.height = height + 'px';
		    child.element.style.width = width + 'px';
		    child.element.appendChild(child.child._domObj);
		    if(child.fill){
		    	child.width = width - (2 * child.padding);
			    this._resizeElement(child.element, child.child._domObj, width, height, child.padding);
		    }else{
		    	child.width = child.child.getMinWidthComposite();
			    var padding = ( width - parseInt(child.width) ) / 2;
			    this._resizeElement(child.element, child.child._domObj, width, height, padding);
		    }
	    }else{
	    	child.width = child.child.getMinWidthComposite();
	        var width = this._getChildWidth(child);
		    child.element.style.height = height + 'px';
		    child.element.style.width = width + 'px';
		    this._resizeElement(child.element, child.child._domObj, width, height, child.padding);
	    }
		var lastSpace = children[i].space;
	    lastSpace.style.width = this._spacing + "px";
	    lastSpace.style.height = height + "px";
		jsgtk.Dom.showElement(lastSpace)
    }

	this._hideLastSpace();
};


gtk.HBox.prototype.getMinWidthCompositeNH = function(){
    var children = this._children, minWidth;
    var minWidth = 0;
    for(var i = children.length; i--;){
	    var child  = children[i];


	    minWidth += child['child'].getMinWidthComposite() + (child.padding * 2);
    }

    minWidth = minWidth + this._spacing * (children.length -1);
    return minWidth;
};

gtk.HBox.prototype.getMinWidthCompositeH = function(){
    var children = this._children, minWidth;
    var minWidth = 0;
    for(var i = children.length; i--;){
	    var child  = children[i];
        var childWidth = child['child'].getMinWidthComposite() + (child.padding * 2);
	    minWidth = minWidth < childWidth ? childWidth : minWidth;
    }

    minWidth = ( minWidth * children.length ) + ( this._spacing * (children.length -1) );
    return minWidth;
};

gtk.HBox.prototype.getMinWidthComposite = function(){
	minWidth = this._homogeneous ? this.getMinWidthCompositeH() : this.getMinWidthCompositeNH();;
	return minWidth;
};

gtk.HBox.prototype.getMinHeightComposite = function(){
	var children = this._children;
	if(children.length > 0){
		var minHeight = 1;
		for(var i = children.length; i--;){
			var height = children[i].child.getMinHeightComposite();
			if( height > minHeight & height != undefined) minHeight = height;
		}
		this._minHeight = minHeight;
		return this._minHeight;
	}
	return this._minHeight;
};

gtk.HBox.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	this.setSizeRequest(minWidthComposite, this._minHeight);

	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	this.resetWidthComposite();

	this.setWidth(minWidth);

	this.resize(this._width, this._height);
};

gtk.HBox.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this.setHeight(minHeight);

	var children = this._children;
	if(children.length > 0){
		for(var i = children.length; i--;){
			var child  = children[i]['child'];
			child.resizeHeightComposite(minHeight);
		}
	}
	this.resize(this._width, this._height);
};
/**
*	Class gtk.VBox 				 : Create a vertical box
*	@param {boolean} homogeneous : resovle to true will divide vbox into equally height small vboxs
*	@param {integer} spacing 	 : number of pixel of space height between vboxs
*/
gtk.VBox = function(homogeneous, spacing) {

	gtk.Box.apply(this, arguments);

	this._domObj.className += " gtk_vbox";
};

gtk.VBox.prototype = new gtk.Box();
gtk.VBox.prototype.constructor = gtk.VBox;

/***********************************************************************************
 *								PRIVATE METHODS									   *
 ***********************************************************************************

/**
* get child's height plus its top and bottom padding
*/
gtk.VBox.prototype._getChildHeight = function(child){
	return (child.child.getMinHeightComposite()) + ( 2 * child.padding );
};

/**
* _resizeElement() method : resize the element which hold the widget that have added into vbox
* @param {object} element : the element that hold the widget that has been added to vbox
* @param {object} domObj  : the dom object of widget that has been added to vbox
* @param {integer} width  : width of element and widget
* @param {integer} height : height of widget
* @param {integer} padding: padding to be added as an extra height of widget to make it fill the element
*/
gtk.VBox.prototype._resizeElement = function(element, domObj, width, height, padding){

	var topPadding = element.childNodes[0];
	var body = element.childNodes[1];
	var bottomPadding = element.childNodes[2];
	var bodyHi = height - ( 2 * padding );

    var topPaddingClone = topPadding.cloneNode(true);
	topPaddingClone.style.height = padding + 'px';
	topPaddingClone.style.width = width + 'px';
	topPadding.parentNode.replaceChild(topPaddingClone, topPadding);

	body.appendChild(domObj);

    body.style.height = bodyHi + 'px';
	body.style.width = width + 'px';

    var bottomPaddingClone = bottomPadding.cloneNode(true);
	bottomPaddingClone.style.height = padding + 'px';
	bottomPaddingClone.style.width = width + 'px';
	bottomPadding.parentNode.replaceChild(bottomPaddingClone, bottomPadding);
};

gtk.VBox.prototype._createElement = function(packType) {
	var divElement = jsgtk.Dom.create({tag: 'div', 'class': packType, style: 'display: block;'});//background-color: #8B6914;
		var divTopPadding = jsgtk.Dom.create({append: divElement ,tag: 'div', style: "display: block;"});// background-color: gray;
		var divChild = jsgtk.Dom.create({append: divElement ,tag: 'div', style: "display: block;"});//background-color: silver;
		var divBottomPadding = jsgtk.Dom.create({append: divElement ,tag: 'div', style: "display: block;"});//background-color: gray;

	return divElement;
};

gtk.VBox.prototype._createSpace = function(){
	var divSpace = jsgtk.Dom.create({tag: 'div', style: "background-color: #fff;"});
	return divSpace;
};


gtk.VBox.prototype._handleH = function(){
	var length = this._children.length;

	var size = this._getMaxChildSize();
	var totalHi = ( size[1] * length ) + ( (length -1) * this._spacing );

	this._resizeHeight(totalHi);
	this._resizeWidth(size[0]);

	this._resizeWidgetsHomo(size[0], size[1]);
};

gtk.VBox.prototype._getMaxChildSize = function(){
    var domObj = this._domObj;
	var children = this._children;
	var len = children.length;
	var totalSpaceHi = ( len > 1 ) ? (len - 1) * this._spacing : 0;
	var hi =  (parseInt(domObj.style.height) - totalSpaceHi) / len;
	var maxHi = hi, maxWi = parseInt(domObj.style.width);
	for(var i = children.length; i--;){
		var height = this._getChildHeight(children[i]);
		if(height > maxHi) maxHi = height;

		var width = children[i].child.getMinWidthComposite();
        if( width > maxWi) maxWi = width;
	}
	return [maxWi, maxHi];
};

gtk.VBox.prototype._resizeWidgetsHomo = function(wi, hi){
	var children = this._children;
	var child;
	for(var i = children.length; i--;){
		child = children[i];
		var childElement = child.element;
		child.width = wi;

		childElement.style.height = hi + 'px';
		childElement.style.width = wi + 'px';

		if(child.fill){
			child.height = hi - (2 * child.padding);
			this._resizeElement(childElement, child.child._domObj, wi, hi, child.padding);
		}else{
			var padding = ( hi - child.child.getHeight() ) / 2;
			child.height = child.child.getHeight();
			this._resizeElement(childElement, child.child._domObj, wi, hi, padding);
		}

		var lastSpace = children[i].space;
		lastSpace.style.height = this._spacing + "px";
		lastSpace.style.width = wi + "px";
		jsgtk.Dom.showElement(lastSpace)
	}

	this._hideLastSpace();
};


gtk.VBox.prototype._handleNH = function(){
	var size = this._getWidgetsSizeNoHomo();

	this._resizeHeight(size[1]);
	this._resizeWidth(size[0]);

	this._resizeWidgetsNoHomo(size[0], size[1]);
};

gtk.VBox.prototype._getWidgetsSizeNoHomo = function(){
	var children = this._children;
	var domObj = this._domObj;
	var child;
	var totalHi = 0, maxWi = parseInt(domObj.style.width);
	for(var i = children.length; i--;){
		child = children[i];
		totalHi += this._getChildHeight(child);

		var width = children[i].child.getMinWidthComposite();
        if( width > maxWi) maxWi = width;
	}
	totalHi = totalHi + ( (children.length - 1) * this._spacing);
	if( totalHi < parseInt(domObj.style.height) ) totalHi = parseInt(domObj.style.height);
	return [maxWi, totalHi];
};

gtk.VBox.prototype._resizeWidgetsNoHomo = function(containerWidth, containerHeight){
	var children = this._children;
	var child, subTotalHi = 0, expandElements = 0;
	var width = containerWidth;

	for(var i = children.length; i--;){
		child = children[i];
		if(child.expand) expandElements += 1;
		subTotalHi += this._getChildHeight(child);
	}

	var extraExpandedHi = (containerHeight - (subTotalHi + (children.length - 1) * this._spacing) ) / expandElements;
	for(var i = children.length; i--;){
	    child = children[i];
	    child.width = width;
	    var childElement = child.element;
	    if(child.expand){
	        var hi = this._getChildHeight(child)+ extraExpandedHi;
		    childElement.style.height = hi + 'px';
		    childElement.style.width  = width + 'px';
		    if(child.fill){
		    	child.height = hi - (2 * child.padding);
			    this._resizeElement(childElement, child.child._domObj, width, hi, child.padding);
		    }else{
		    	child.height = child.child.getHeight();
			    var padding = ( hi - parseInt(child.height) ) / 2;
			    this._resizeElement(childElement, child.child._domObj, width, hi, padding);
		    }
	    }else{
	    	child.height = child.child.getHeight();
	        var height = this._getChildHeight(child);

		    childElement.style.height = height + 'px';
		    childElement.style.width  = width + 'px';
		    this._resizeElement(childElement, child.child._domObj, width, height, child.padding);
	    }
		var lastSpace = children[i].space;
		lastSpace.style.height = this._spacing + "px";
		lastSpace.style.width = width + "px";
		jsgtk.Dom.showElement(lastSpace)
    }

	this._hideLastSpace();
};


/**
* getMinWidthComposite() composite method : get the min width of vbox.
*								  			if it has children then the min width of children,
*								  			else the min width of vbox itself.
* @return {integer} minWidth			  : the min width to be used when need decrease the width of vbox
*								  			thus the decreasing can't go smaller then the minWidth
*/
gtk.VBox.prototype.getMinWidthComposite = function(){
	var children = this._children;
	if(children.length > 0){
		var minWidth = 1;
		for(var i = children.length; i--;){
			var width = children[i].child.getMinWidthComposite();
			if( width > minWidth & width != undefined) minWidth = width;
		}
		this._minWidth = minWidth;
		return this._minWidth;
	}
	return this._minWidth;
};

gtk.VBox.prototype.getMinHeightCompositeNH = function(){
    var children = this._children, minHeight;
    var minHeight = 0;
    for(var i = children.length; i--;){
	    var child  = children[i];

	    minHeight += child['child'].getMinHeightComposite() + (child.padding * 2);
    }

    minHeight = minHeight + this._spacing * (children.length -1);
    return minHeight;
};

gtk.VBox.prototype.getMinHeightCompositeH = function(){
    var children = this._children, minHeight;
    var minHeight = 0;
    for(var i = children.length; i--;){
	    var child  = children[i];
        var childHeight = child['child'].getMinHeightComposite() + (child.padding * 2);
	    minHeight = minHeight < childHeight ? childHeight : minHeight;
    }

    minHeight = ( minHeight * children.length ) + ( this._spacing * (children.length -1) );
    return minHeight;
};

/**
* getMinHeightComposite() composite method : get the min height of vbox.
*								  			 if it has children then the min height of children,
*								  			 else the min height of vbox itself.
* @return {integer} minWidth			   : the min height to be used when need decrease the height of vbox
*								  			 thus the decreasing can't go smaller then the minHeight
*/
gtk.VBox.prototype.getMinHeightComposite = function(){
	minHeight = this._homogeneous ? this.getMinHeightCompositeH() : this.getMinHeightCompositeNH();;
	return minHeight;
};

/**
* resizeWidthComposite() composite method : decrease the width of vbox.
*											  decrease vbox's width and all the composite children
*
*/
gtk.VBox.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	this.setWidth(minWidth);

	var children = this._children;
	if(children.length > 0){
		for(var i = children.length; i--;){
			var child  = children[i]['child'];
			child.resizeWidthComposite(minWidth);
		}
	}
	this.resize(this._width, this._height);
};

/**
* resizeHeightComposite() composite method : decrease the height of vbox.
*											   decrease vbox's height and all the composite children
*
*/
gtk.VBox.prototype.resizeHeightComposite = function(height){

	var minHeightComposite = this.getMinHeightComposite();
	this.setSizeRequest(this._minWidth, minHeightComposite);

	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this.resetHeightComposite();

	this.setHeight(minHeight);

	this.resize(this._width, this._height);
};
/**
* The base class for widgets with two panes, arranged either horizontally (gtk.HPaned) or vertically (gtk.VPaned)
*/
gtk.Paned = function(){
	gtk.Container.apply(this);

	this._minWidth = 200;
	this._minHeight = 200;
	this._width = this._minWidth;
	this._height = this._minHeight;

	this._render = function(){
		this._domObj.className += " gtk_paned";
		this.hide();
	};

	this._render();
};

gtk.Paned.prototype = new gtk.Container();
gtk.Paned.prototype.constructor = gtk.Paned;

/**
* Adds the widget specified by child to the top or left pane with the parameters specified by resize and shrink
* @param {gtk.Widget} widget  The widget to add
* @param {boolean} resize If True child should resize when the paned is resized
* @param {boolean} shrink If True child can be made smaller than its minimum size request
*/
gtk.Paned.prototype.pack1 = function(widget, resize, shrink){
    var self = this;
	this._widget1 = widget;
	this._shrink1 = (shrink === undefined) ? true : shrink;

	this._paned1.appendChild(this._widget1._domObj);
	this._resizePaned1(true);
	this.emit('bubble', this._width, this._height);

	this._widget1.connect("bubble", function(width){
	    self._resizePaned1(true);
	    self._resizePaned2(true);
   	    self.emit('bubble', self._width, self._height);
	});
};

/**
* Adds the widget specified by child to the bottom or right pane with the parameters specified by resize and shrink
* @param {gtk.Widget} widget The widget to add
* @param {boolean} resize If True child should resize when the paned is resized
* @param {boolean} shrink If True child can be made smaller than its minimum size request
*/
gtk.Paned.prototype.pack2 = function(widget, resize, shrink){
	this._widget2 = widget;
	var self = this;
	this._shrink2 = (shrink === undefined) ? true : shrink;

	this._paned2.appendChild(this._widget2._domObj);
	this._resizePaned2(true);
	this.emit('bubble', this._width, this._height);

	this._widget2.connect("bubble", function(){
        self._resizePaned1(true);
	    self._resizePaned2(true);
	    self.emit('bubble', self._width, self._height)
	});
};

gtk.Paned.prototype.resize = function(width, height){
	this._resizePaned1(false);
	this._resizePaned2(false);
};

gtk.Paned.prototype._resizePaned1 = function(isInit){
	this._resizePaned1Width(isInit);
	this._resizePaned1Height(isInit);
};

gtk.Paned.prototype._resizePaned2 = function(isInit){
	this._resizePaned2Width(isInit);
	this._resizePaned2Height(isInit);
};

gtk.Paned.prototype._showGhostDivider = function(){
	this._ghostDivider.style.backgroundColor = "#838B8B";
	this._ghostDivider.style.opacity = 1;
};

gtk.Paned.prototype._hideGhostDivider = function(){
	this._ghostDivider.style.disply = "none";
	this._ghostDivider.style.opacity = 0.1;
};
gobject.signalNew("childrendminimize", gtk.Paned, null, null, []);
gobject.signalNew("childrestore", gtk.Paned, null, null, []);
/**
 * Class VPaned
 * @param {Integer} width Width of domObj which contain the widget
 * @param {Integer} height Height of domObj which contain the widget
 */
gtk.VPaned = function() {

	gtk.Paned.apply(this);
	this._dividerHeight = 4;
	this._paned1Height = (this._height / 2) - (this._dividerHeight / 2);
	this._paned2Height = (this._height / 2) - (this._dividerHeight / 2);
	this._isPaned1Restore = true;
	this._isPaned2Restore = true;

	this._render = function(){
		this._domObj.className += " gtk_vPaned";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this._domObj.style.position = 'relative';

			this._paned1 = jsgtk.Dom.create({'tag': 'div', 'class': 'gtk_paned1'});
			this._paned1.style.width = this._width + 'px';
			this._paned1.style.height = this._paned1Height + 'px'

			this._domDivider = jsgtk.Dom.create({'tag': 'div', 'class': 'gtk_dom_divider'});
				this._dom = jsgtk.Dom.create({'append': this._domDivider, 'tag': "div", 'class': 'gtk_paned_divider_image'});

			this._domDivider.style.width = this._width + 'px';
			this._domDivider.style.height = this._dividerHeight + "px";
			this._domDivider.style.top = this._paned1Height + 'px';

			this._ghostDivider = this._domDivider.cloneNode(true);
			this._ghostDivider.className = "gtk_paned_ghost_divider";

			this._paned2 = jsgtk.Dom.create({'tag': 'div', 'class': 'gtk_paned2'});
			this._paned2.style.width = this._width + 'px';
			this._paned2.style.height = this._paned1Height + 'px';

		this._domObj.appendChild(this._paned1);
		this._domObj.appendChild(this._domDivider);
		this._domObj.appendChild(this._paned2);
		this._domObj.appendChild(this._ghostDivider);

		this.hide();
	};

	/**
	 * Render
	 */
	this._render();

	this._vBehaviour(0, this._height - this._dividerHeight);
};

gtk.VPaned.prototype = new gtk.Paned();
gtk.VPaned.prototype.constructor = gtk.VPaned;

gtk.VPaned.prototype.setPosition = function(position){
    this._paned1Height = (this._widget1.getMinHeightComposite() < position)? position : this._widget1.getMinHeightComposite();
    this._paned2Height = this._height - this._paned1Height - this._dividerHeight;
    if(this._paned2Height < this._widget2.getMinHeightComposite()){
        this._paned2Height = this._widget2.getMinHeightComposite();
        this._paned1Height = this._height - this._paned2Height - this._dividerHeight;
    }
    this._resizePaned1Height();
    this._resizePaned2Height();
};

gtk.VPaned.prototype.autoResize = function(widget){
	var paned1 = this._paned1;
	var paned2 = this._paned2;
	this._originalPaned1Height = paned1.style.height;
	this._originalPaned1ChildHeight = paned1.childNodes[0].style.height;
	this._originalPaned2Height= paned2.style.height;
	this._originalPaned2ChildHeight = paned2.childNodes[0].style.height;

	if(widget._domObj.parentNode.className == "gtk_paned1" ){
		this._widget2.resizeHeightComposite(this._height);
		paned1.style.height = '0px';
		this._isPaned1Restore = false;
	}

	if(widget._domObj.parentNode.className == "gtk_paned2" ){
		this._widget1.resizeHeightComposite(this._height);
		paned2.style.height = '0px';
		this._isPaned2Restore = false;
	}
	this._domDivider.style.display = 'none';
	this._ghostDivider.style.display = 'none';

	if(!this._isPaned1Restore && !this._isPaned2Restore){
		this.emit('childrendminimize');
	}

};

gtk.VPaned.prototype.restorStatuse = function(widget){
	if(widget === this._widget1){
		if(this._isPaned2Restore){
			this._paned1.style.height = this._paned1Height + "px";
			this._widget1.resizeHeightComposite(this._paned1Height);

			this._paned2.style.height = this._paned2Height + "px";
			this._widget2.resizeHeightComposite(this._paned2Height);

			this._domDivider.style.display = 'block';
			this._ghostDivider.style.display = 'block';

		}else{
			this._paned1.style.height = this._height + "px";
			this._widget1.resizeHeightComposite(this._height);
		}
		this._isPaned1Restore = true;
	};

	if(widget === this._widget2){
		if(this._isPaned1Restore){
			this._paned2.style.height = this._paned2Height + "px";
			this._widget2.resizeHeightComposite(this._paned2Height);

			this._paned1.style.height = this._paned1Height + "px";
			this._widget1.resizeHeightComposite(this._paned1Height);

			this._domDivider.style.display = 'block';
			this._ghostDivider.style.display = 'block';
		}else{
			this._paned2.style.height = this._height + "px";
			this._widget2.resizeHeightComposite(this._height);
		}
		this._isPaned2Restore = true;
	};

	if(this._isPaned1Restore || this._isPaned2Restore) {
		this.emit('childrestore');
	}
};

/**
* _resizePaned1Width : resize the width of paned1 or top paned
*/
gtk.VPaned.prototype._resizePaned1Width = function(){
	if(this._width > this._widget1.getWidth())
		this._widget1.resizeWidthComposite(this._width);
	else this._resizeWidth(this._widget1.getWidth());
};

/**
* _resizePaned1Height : resize the height of paned1 or top paned
*/
gtk.VPaned.prototype._resizePaned1Height = function(isInit){

	if(isInit) this._initModifyPaned1Height();
	else this._modifyPaned1Height();

	this._resizeHeight(this._paned1Height, this._paned2Height);
	this._topMinY = this._shrink1 ? 0 : this._widget1.getMinHeightComposite();

	this._vBehaviour( this._topMinY, this._height - this._dividerHeight);
};

/**
* _resizePaned1Width : resize the width of paned2 or bottom paned
*/
gtk.VPaned.prototype._resizePaned2Width = function(){
	if(this._width > this._widget2.getWidth())
		this._widget2.resizeWidthComposite(this._width);
	else{
		this._resizeWidth(this._widget2.getWidth());
		this._widget1.resizeWidthComposite(this._widget2.getWidth());
	}
};

/**
* _resizePaned1Height : resize the height of paned2 or bottom paned
*/
gtk.VPaned.prototype._resizePaned2Height = function(isInit){

	if(isInit) this._initModifyPaned2Height();
	else this._modifyPaned2Height();

	this._resizeHeight(this._paned1Height, this._paned2Height);
	this._bottomMinY = this._shrink2 ? 0 : this._widget2.getMinHeightComposite();
	var maxY = this._height - this._dividerHeight - this._bottomMinY;

	this._vBehaviour( this._topMinY, maxY);
};

gtk.VPaned.prototype._initModifyPaned1Height = function(){
	if(this._paned1Height > this._widget1.getHeight())
		this._widget1.resizeHeightComposite(this._paned1Height);
	else{
		this._paned1Height = this._widget1.getHeight();
	}
};

gtk.VPaned.prototype._initModifyPaned2Height = function(){
	if(this._paned2Height > this._widget2.getHeight())
		this._widget2.resizeHeightComposite(this._paned2Height);
	else
		this._paned2Height = this._widget2.getHeight();
};

gtk.VPaned.prototype._modifyPaned1Height = function(){
	this._widget1.resizeHeightComposite(this._paned1Height);
	this._paned1Height = this._widget1.getHeight();
};

gtk.VPaned.prototype._modifyPaned2Height = function(){
	this._widget2.resizeHeightComposite(this._paned2Height);
	this._paned2Height = this._widget2.getHeight();
};

/**
* _vBehaviour() method  : make ghostDivider draggable
* @param {integer} minY : left bound of dragging area
* @param {integer} maxY : right bound of dragging area
*/
gtk.VPaned.prototype._vBehaviour = function(minY, maxY){
	var self = this;
	jsgtk.Dom.vDragInit(this._ghostDivider, minY, maxY);

	this._ghostDivider.onDragStart = function(){
		self._showGhostDivider();
	};

	this._ghostDivider.onDragEnd = function(x, y){
		self._hideGhostDivider();

		var topHeight = y;
		var bottomHeight = self._height - topHeight - self._dividerHeight;

		self._resizePaned12Dom(topHeight, bottomHeight);

		self._widget1.resizeHeightComposite(topHeight);
		self._widget2.resizeHeightComposite(bottomHeight);
	};
};

gtk.VPaned.prototype._resizePaned12Dom = function(topHeight, bottomHeight){
	this._paned1Height = topHeight;
	this._paned2Height = bottomHeight;
	this._paned1.style.height = topHeight + 'px';
	this._paned2.style.height = bottomHeight + 'px';
};

gtk.VPaned.prototype._resizeWidth = function(width){
	this._width = width;
	this._domObj.style.width = this._width + 'px';
		this._paned1.style.width = this._width + 'px';
		this._domDivider.style.width = this._width + 'px';
		this._ghostDivider.style.width = this._width + 'px';
		this._paned2.style.width = this._width + 'px';
};

gtk.VPaned.prototype._resizeHeight = function(paned1Height, paned2Height){
	this._height = paned1Height + paned2Height + this._dividerHeight;
	this._domObj.style.height = this._height + 'px';
		this._paned1.style.height = paned1Height + 'px';
		this._ghostDivider.style.top = paned1Height + 'px';
		this._paned2.style.height = paned2Height + 'px';
};

gtk.VPaned.prototype.getMinWidthComposite = function(){
	var widget1Width = this._widget1.getMinWidthComposite();
	var widget2Width = this._widget2.getMinWidthComposite();
	var minWidth = this.getSizeRequest()[0] > widget1Width ? this.getSizeRequest()[0] : widget1Width;
	minWidth = minWidth > widget2Width ? minWidth : widget2Width;

	return minWidth;
};

gtk.VPaned.prototype.getMinHeightComposite = function(){
	var widget1Height = this._widget1.getMinHeightComposite();
	var widget2Height = this._widget2.getMinHeightComposite();
	var minHeight = widget1Height + widget2Height;
	minHeight = minHeight > this.getSizeRequest()[1] ? minHeight : this.getSizeRequest()[1];

	return minHeight + 5;
};

gtk.VPaned.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	this._resizeWidth(minWidth);

	this._widget1.resizeWidthComposite(minWidth);
	this._widget2.resizeWidthComposite(minWidth);

	if(this._isPaned1Restore && this._isPaned2Restore) {
        this.resize();
	}
};

gtk.VPaned.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	var offsetHeight = (minHeight - this.getHeight()) / 2 ;

	this._resizeHeight(minHeight);

	var height1 = this._paned1Height + offsetHeight;
	var height2 = this._paned2Height + offsetHeight;

	if(
		this._paned2Height === this._widget2.getMinHeightComposite() ||
		this._paned1Height === this._widget1.getMinHeightComposite() ||
		height1 			<  this._widget1.getMinHeightComposite() ||
		height2   			<  this._widget2.getMinHeightComposite()
	){
		if(this._paned2Height === this._widget2.getMinHeightComposite() ||
		   height2 			   <  this._widget2.getMinHeightComposite()
		){
		    this._paned1Height = this._paned1Height + offsetHeight * 2;
		    this._paned2Height = this._widget2.getMinHeightComposite();
		}

		if(this._paned1Height === this._widget1.getMinHeightComposite() ||
		   height1 			   <  this._widget1.getMinHeightComposite()
		){
		    this._paned2Height = this._paned2Height + offsetHeight * 2;
   		    this._paned1Height = this._widget1.getMinHeightComposite();
		}

	}else{
		this._paned1Height = height1;
		this._paned2Height = height2;
	}

	if(this._isPaned1Restore && this._isPaned2Restore) {
        this.resize();
	}
};
/**
 * Class HPaned
 * @param {Integer} width Width of domObj which contain the widget
 * @param {Integer} height Height of domObj which contain the widget
 */
gtk.HPaned = function() {

	gtk.Paned.apply(this);
    var self = this;
	this._dividerWidth    = 4;
	this._paned1Width     = (this._width / 2) - (this._dividerWidth / 2);
	this._paned2Width     = (this._width / 2) - (this._dividerWidth / 2);
	this._isPaned1Restore = true;
	this._isPaned2Restore = true;
	this._isDrawer        = false;
	this._drawerWidth     = 10;
	this._isDrawed        = false;
	this._isDrawedToLeft  = false;

	this._render = function(){
		this._domObj.className += " gtk_hPaned";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';

			this._paned1 = jsgtk.Dom.create({'tag': 'div', 'class': 'gtk_paned1'});
			this._paned1.style.width = this._paned1Width + 'px';
			this._paned1.style.height = this._height + 'px'

			this._domDivider = jsgtk.Dom.create({'tag': 'div', 'class': 'gtk_dom_divider'});
			    this._dom = jsgtk.Dom.create({'append': this._domDivider, 'tag': "div", 'class': 'gtk_paned_divider_image'});

			this._drawer = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_hPaned_drawer"});
			    this._restoreButton = jsgtk.Dom.create({"append": this._drawer, "tag": "div", "class": "gtk_hPaned_drawer_restore_icon"});
			this._drawer.style.width = this._drawerWidth + "px";
			this._drawer.style.height= this._height + "px";
			jsgtk.Dom.hideElement(this._drawer);

			this._draw = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_hPaned_draw"});
			jsgtk.Dom.hideElement(this._draw);


			this._domDivider.style.width = this._dividerWidth + 'px';
			this._domDivider.style.height =  this._height+ "px";
			this._domDivider.style.left = this._paned1Width + 'px';

			this._ghostDivider = this._domDivider.cloneNode(true);
			this._ghostDivider.className = "gtk_paned_ghost_divider";

			this._paned2 = jsgtk.Dom.create({'tag': 'div', 'class': 'gtk_paned2'});
			this._paned2.style.width = this._paned1Width + 'px';
			this._paned2.style.height = this._height + 'px';

		this._domObj.appendChild(this._paned1);
		this._domObj.appendChild(this._domDivider);
		this._domObj.appendChild(this._paned2);
		this._domObj.appendChild(this._ghostDivider);
		this.hide();
	};

	/**
	 * Render
	 */
	this._render();

	this._hBehaviour(0, this._width - this._dividerWidth);

/* Do not remove this
	jsgtk.Event.addDomListener(this._drawer, "mousedown", function(e){
	    self._isDrawed = self._isDrawed ? false : true;
	    self._draw.style.height = self._height + "px";
	    jsgtk.Dom.showElement(self._draw);
	    self._draw.innerHTML = "";
	    if(self._isDrawedToLeft){
    	    self._widget1.show();
	        self._draw.appendChild(self._widget1.getNode());
	        self._draw.style.width  = self._paned1Width + "px";

            self._animateDrawLeft();
	    }else{
    	    self._widget2.show();
	        self._draw.appendChild(self._widget2.getNode());
	        self._draw.style.width  = self._paned2Width + "px";

            self._animateDrawRight();
	    }

	    jsgtk.Event.stopBubble(e);
	}, false);
*/
	jsgtk.Event.addDomListener(this._drawer, "click", function(e){
        if(self._isDrawedToLeft){
            self._widget1.show();
            self._paned1.appendChild(self._widget1.getNode());
            self.restorStatuse(self._widget1, true);
        }else{
            self._widget2.show();
            self._paned2.appendChild(self._widget2.getNode());
            self.restorStatuse(self._widget2, true);
        }

        jsgtk.Dom.hideElement(self._drawer);
	});
};

gtk.HPaned.prototype = new gtk.Paned();
gtk.HPaned.prototype.constructor = gtk.HPaned;

gtk.HPaned.prototype.setPosition = function(position){
    var width1 = this._widget1.getMinWidthComposite();
    var width2 = this._widget2.getMinWidthComposite();
    this._paned1Width = (width1 < position)? position : width1;
    this._paned2Width = this._width - this._paned1Width - this._dividerWidth;
    if(this._paned2Width < width2){
        this._paned2Width = width2;
        this._paned1Width = this._width - this._paned2Width - this._dividerWidth;
    }
    this._resizePaned1Width();
    this._resizePaned2Width();
};

gtk.HPaned.prototype.enableDrawerRight = function(){
    this._enableDrawer(this._widget2, "gtk_enabled_drawer_right");
};

gtk.HPaned.prototype.enableDrawerLeft = function(){
    this._enableDrawer(this._widget1, "gtk_enabled_drawer_left");
};

gtk.HPaned.prototype._enableDrawer = function(widget, className){
    var self = this;
    this._dividerWidth = 10;
    this._domDivider.className += " gtk_dom_divider_drawer";
    this._domDivider.style.width = this._dividerWidth + "px";

    this._dom.className = className;
    jsgtk.Dom.hideElement(this._ghostDivider);

    jsgtk.Event.addDomListener(this._domDivider, "click", function(e){
        self.autoResize(widget, true);
        jsgtk.Event.stopBubble(e);
    });

    this.resize();
};

gtk.HPaned.prototype.autoResize = function(widget, isDrawer){
	var paned1     = this._paned1;
	var paned2     = this._paned2;
	this._isDrawer = isDrawer === undefined ? false : isDrawer;
	var width = this._width - this._drawerWidth;

	this._originalPaned1Width = paned1.style.width;
	this._originalPaned1ChildWidth = paned1.childNodes[0].style.width;
	this._originalPaned2Width = paned2.style.width;
	this._originalPaned2ChildWidth = paned2.childNodes[0].style.width;

	if(widget._domObj.parentNode.className == "gtk_paned1" ){
	    if(this._isDrawer){
            this._widget2.resizeWidthComposite(width);
            this._widget1.hide();

            paned1.style.width = this._drawerWidth + "px";
            paned2.style.width = width + "px";

            this._animateDrawerLeft();
            this._isDrawedToLeft = true;

            this._restoreButton.className += " draw_left";
            jsgtk.Dom.showElement(this._drawer);
	    }else{
            this._widget2.resizeWidthComposite(this._width);
            this._widget1.hide();
            paned1.style.width = '0px';
	    }
		this._isPaned1Restore = false;
	}

	if(widget._domObj.parentNode.className == "gtk_paned2" ){
	    if(this._isDrawer){
	        this._widget1.resizeWidthComposite(this._width - this._drawerWidth);
		    this._widget2.hide();

	        paned2.style.width = this._drawerWidth + "px";
            paned1.style.width = width + "px";

            this._drawer.style.right = "0px";
            this._animateDrawerRight();
            this._isDrawedToLeft = false;

            this._restoreButton.className += " draw_right";
            jsgtk.Dom.showElement(this._drawer);
	    }else{
	        this._widget1.resizeWidthComposite(this._width);
		    this._widget2.hide();
		    paned2.style.width = '0px';
	    }
		this._isPaned2Restore = false;
	}
	this._domDivider.style.display = 'none';
	this._ghostDivider.style.display = 'none';

	if(!this._isPaned1Restore && !this._isPaned2Restore){
		this.emit('childrendminimize', this);
	}
};

gtk.HPaned.prototype._animateDrawLeft = function(){
    var self = this;
    if(!this._isDrawed){
        var left = self._drawerWidth;
        var intervalID = window.setInterval(function(){
            self._draw.style.left = left + "px";
            left -= 20;
            if(left <= -self._paned1Width){
                self._draw.style.left = -self._paned1Width + "px";
                clearInterval(intervalID);
            }
        }, 15);
    }else{
        var left = -this._paned1Width;
        var intervalID = window.setInterval(function(){
            self._draw.style.left = left + "px";
            left += 20;
            if(left >= self._drawerWidth){
                self._draw.style.left = self._drawerWidth + "px";
                clearInterval(intervalID);
            }
        }, 15);
    }
};

gtk.HPaned.prototype._animateDrawRight = function(){
    var self = this;
    if(!this._isDrawed){
        var right = self._drawerWidth;
        var intervalID = window.setInterval(function(){
            self._draw.style.right = right + "px";
            right -= 20;
            if(right <= -self._paned2Width){
                self._draw.style.right = -self._paned2Width + "px";
                clearInterval(intervalID);
            }
        }, 15);
    }else{
        var right = -this._paned2Width;
        var intervalID = window.setInterval(function(){
            self._draw.style.right = right + "px";
            right += 20;
            if(right >= self._drawerWidth){
                self._draw.style.right = self._drawerWidth + "px";
                clearInterval(intervalID);
            }
        }, 15);
    }
};

gtk.HPaned.prototype._animateDrawerLeft = function(){
    var self = this;
    var left = 0;
    var intervalID = window.setInterval(function(){
        self._drawer.style.left = left + "px";
        left -= 5;
        if(left <= -30) {
            clearInterval(intervalID);
            var innerInter = window.setInterval(function(){
                self._drawer.style.left = left + "px";
                left += 2;
                if(left >= 0) {
                    self._drawer.style.left = "0px";
                    clearInterval(innerInter);
                }
            }, 10);
        }
    }, 10);
};

gtk.HPaned.prototype._animateDrawerRight = function(){
    var self = this;
    var right = 0;
    var intervalID = window.setInterval(function(){
        self._drawer.style.right = right + "px";
        right -= 5;
        if(right <= -30) {
            clearInterval(intervalID);
            var innerInter = window.setInterval(function(){
                self._drawer.style.right = right + "px";
                right += 2;
                if(right >= 0) {
                    self._drawer.style.right = "0px";
                    clearInterval(innerInter);
                }
            }, 10);
        }
    }, 10);
};

gtk.HPaned.prototype._restoreWidget1 = function(){
    if(this._isPaned2Restore){
		this._paned1.style.width = this._paned1Width + "px";
		this._widget1.resizeWidthComposite(this._paned1Width);

		this._paned2.style.width = this._paned2Width + "px";
		this._widget2.resizeWidthComposite(this._paned2Width);

		this._domDivider.style.display = 'block';
		if(!this._isDrawer)this._ghostDivider.style.display = 'block';

	}else{
		this._paned1.style.width = this._width + "px";
		this._widget1.resizeWidthComposite(this._width);
	}
	this._isPaned1Restore = true;
};

gtk.HPaned.prototype._restoreWidget2 = function(){
    if(this._isPaned1Restore){
	    this._paned2.style.width = this._paned2Width + "px";
	    this._widget2.resizeWidthComposite(this._paned2Width);

	    this._paned1.style.width = this._paned1Width + "px";
	    this._widget1.resizeWidthComposite(this._paned1Width);

	    this._domDivider.style.display = 'block';
	    if(!this._isDrawer)this._ghostDivider.style.display = 'block';
    }else{
	    this._paned2.style.width = this._width + "px";
	    this._widget2.resizeWidthComposite(this._width);
    }
    this._isPaned2Restore = true;
};

gtk.HPaned.prototype.restorStatuse = function(widget){
	if(widget === this._widget1) this._restoreWidget1();
	if(widget === this._widget2) this._restoreWidget2();

	if(this._isPaned1Restore || this._isPaned2Restore) {
		this.emit('childrestore', this);
	}
};

/**
* _resizePaned1Height : resize the height of paned1 or left paned
*/
gtk.HPaned.prototype._resizePaned1Height = function(){
	if(this._height > this._widget1.getHeight())
		this._widget1.resize(this._widget1.getWidth(), this._height);
	else this._resizeHeight(this._widget1.getHeight());
};

/**
* _resizePaned1Width : resize the width of paned1 or left paned
*/
gtk.HPaned.prototype._resizePaned1Width = function(isInit){

	if(isInit) this._initModifyPaned1Width();
	else this._modifyPaned1Width();

	this._resizeWidth(this._paned1Width, this._paned2Width);
	this._leftMinX = this._shrink1 ? 0 : this._widget1.getMinWidthComposite();

	this._hBehaviour( this._leftMinX, this._width - this._dividerWidth);
};

/**
* _resizePaned1Height : resize the height of paned2 or right paned
*/
gtk.HPaned.prototype._resizePaned2Height = function(){
	if(this._height > this._widget2.getHeight())
		this._widget2.resize(this._widget2.getWidth(), this._height);
	else{
		this._resizeHeight(this._widget2.getHeight());
		this._widget1.resizeHeightComposite(this._widget2.getHeight());
	}
};

/**
* _resizePaned1Width : resize the width of paned2 or right paned
*/
gtk.HPaned.prototype._resizePaned2Width = function(isInit){

	if(isInit) this._initModifyPaned2Width();
	else this._modifyPaned2Width();

	this._resizeWidth(this._paned1Width, this._paned2Width);
	this._rightMinX = this._shrink2 ? 0 : this._widget2.getMinWidthComposite();
	var maxX = this._width - this._dividerWidth - this._rightMinX;

	this._hBehaviour(this._widget1.getMinWidthComposite(), maxX);
};

gtk.HPaned.prototype._initModifyPaned1Width = function(){
	if(this._paned1Width > this._widget1.getWidth())
		this._widget1.resize(this._paned1Width, this._widget1.getHeight());
	else{
		this._paned1Width = this._widget1.getWidth();
	}
};

gtk.HPaned.prototype._initModifyPaned2Width = function(){
	if(this._paned2Width > this._widget2.getWidth())
		this._widget2.resize(this._paned2Width, this._widget2.getWidth());
	else{
		this._paned2Width = this._widget2.getWidth();
	}
};

gtk.HPaned.prototype._modifyPaned1Width = function(width){
    if(width !== undefined) this._widget1.resizeWidthComposite(width);
	else this._widget1.resizeWidthComposite(this._paned1Width);
};

gtk.HPaned.prototype._modifyPaned2Width = function(width){
    if(width !== undefined) this._widget2.resizeWidthComposite(width);
	else{
	    this._widget2.resizeWidthComposite(this._paned2Width);
    	this._paned2Width = this._widget2.getWidth();
	}
};

/**
* _hBehaviour() method  : make ghostDivider draggable
* @param {integer} minX : lower bound of dragging area
* @param {integer} maxX : upper bound of dragging area
*/
gtk.HPaned.prototype._hBehaviour = function(minX, maxX){

	var self = this;
	jsgtk.Dom.hDragInit(this._ghostDivider, minX, maxX);
	this._ghostDivider.onDragStart = function(){
		self._showGhostDivider();
	};

	this._ghostDivider.onDragEnd = function(x, y){
		self._hideGhostDivider();

		var width1 = x;
		var width2 = self._width - width1 - self._dividerWidth;

		self._resizePaned12Dom(width1, width2);

		self._widget1.resizeWidthComposite(width1);
		self._widget2.resizeWidthComposite(width2);
	};
};

gtk.HPaned.prototype._resizePaned12Dom = function(width1, width2){
	this._paned1Width = width1;
	this._paned2Width = width2;
	this._paned1.style.width = width1 + 'px';
	this._paned2.style.width = width2 + 'px';
}

gtk.HPaned.prototype._resizeWidth = function(paned1Width, paned2Width){
	this._width = paned1Width + paned2Width + this._dividerWidth;
	this._domObj.style.width = this._width + 1 + 'px';
		this._paned1.style.width = paned1Width + 'px';
		this._ghostDivider.style.left = paned1Width + 'px';
		this._paned2.style.width = paned2Width + 'px';
};

gtk.HPaned.prototype._resizeHeight = function(height){
	this._height = height;
	this._domObj.style.height = this._height + 'px';
		this._paned1.style.height = this._height + 'px';
		this._domDivider.style.height = this._height + 'px';
		this._ghostDivider.style.height = this._height + 'px';
		this._paned2.style.height = this._height + 'px';

		this._drawer.style.height = this._height + "px";
};


gtk.HPaned.prototype.getMinWidthComposite = function(){
	var widget1Width = this._widget1.getMinWidthComposite();
	var widget2Width = this._widget2.getMinWidthComposite();
	var minWidth = widget1Width + widget2Width + this._drawerWidth;
	minWidth = minWidth > this._minWidth ? minWidth : this._minWidth;

	return minWidth;
};

gtk.HPaned.prototype.getMinHeightComposite = function(){
	var widget1Height = this._widget1.getMinHeightComposite();
	var widget2Height = this._widget2.getMinHeightComposite();
	var minHeight = this._minHeight > widget1Height ? this._minHeight : widget1Height;
	minHeight = minHeight > widget2Height ? minHeight : widget2Height;

	return minHeight;
};

gtk.HPaned.prototype.resizeWidthComposite = function(width){

	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	var offsetWidth = (minWidth - this.getWidth()) / 2 ;

	this.setWidth(minWidth);

	var width1 = this._paned1Width + offsetWidth;
	var width2 = this._paned2Width + offsetWidth;

	if(this._isDrawedToLeft){
	    this._modifyPaned2Width(minWidth - this._drawerWidth);
	    this._resizeWidth(0, minWidth);
	}
	else{
	    this._modifyPaned1Width(minWidth - this._drawerWidth);
        this._resizeWidth(minWidth, 0);
	}

	if(
		this._paned2Width === this._widget2.getMinWidthComposite() ||
		this._paned1Width === this._widget1.getMinWidthComposite() ||
		width1			   <  this._widget1.getMinWidthComposite() ||
		width2			   <  this._widget2.getMinWidthComposite()
 	){
		if(this._paned2Width === this._widget2.getMinWidthComposite() ||
		   width2			  < this._widget2.getMinWidthComposite()
		){
		    this._paned1Width = (this._paned1Width + offsetWidth * 2) - 1;
		    this._paned2Width = (this._widget2.getMinWidthComposite()) - 1;
		}
		if(this._paned1Width === this._widget1.getMinWidthComposite() ||
		   width1			  <  this._widget1.getMinWidthComposite()
		){
		    this._paned2Width = (this._paned2Width + offsetWidth * 2) - 1;
		    this._paned1Width = (this._widget1.getMinWidthComposite()) - 1;
		}
	}else{
		this._paned1Width = this._paned1Width + offsetWidth - 1;
		this._paned2Width = this._paned2Width + offsetWidth - 1;
	}

	if(this._isPaned1Restore && this._isPaned2Restore) {
        this.resize();
	}
};

gtk.HPaned.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this.setHeight(minHeight);

	this._widget1.resizeHeightComposite(minHeight);
	this._widget2.resizeHeightComposite(minHeight);

    if(this._isDrawedToLeft) this._resizePaned1Height();
    else this._resizePaned2Height();

	if(this._isPaned1Restore && this._isPaned2Restore) {
        this.resize();
	}
};
/*
*	Abstract Class
*/

gtk.Buildable = function(){

};

gtk.Buildable.prototype.addChild = function(builder, child, type){};
gtk.Buildable.prototype.constructChild = function(builder, name) {};
gtk.Buildable.prototype.getInternalChild = function(builder, childname) {};
gtk.Buildable.prototype.getName = function(){};
gtk.Buildable.prototype.parserFinished = function(builder) {};
gtk.Buildable.prototype.setName = function(name) {};
gtk.Adjustment = function(value, lower, upper, step_incr, page_incr, page_size){
    gtk.Object.apply(this);

    this._value = value || 0;
    this._lower = lower || 0;
    this._upper = upper || 0;
};

gtk.Adjustment.prototype = new gtk.Object();
gtk.Adjustment.prototype.constructor = gtk.Adjustment;

gtk.Adjustment.prototype.setValue = function(value){
    this._value = value;
};

gtk.Adjustment.prototype.getValue = function(){
    return this._value;
};

gtk.Adjustment.prototype.setLower = function(lower){
    this._lower = lower;
    this.Changed();
};

gtk.Adjustment.prototype.getLower = function(){
    return this._lower;
};

gtk.Adjustment.prototype.setUpper = function(upper){
    this._upper = upper;
    this.Changed();
};

gtk.Adjustment.prototype.getUpper = function(){
    return this._upper;
};

gtk.Adjustment.prototype.setAll = function(value, lower, upper, step_increment, page_increment, page_size){
    this._value = value || this._value;
    this._lower = lower || this._lower;
    this._upper = upper || this._upper;
    this.Changed();
};

gtk.Adjustment.prototype.Changed = function(){
    this.emit('changed', this._lower, this._upper);
};

gobject.signalNew('changed', gtk.Adjustment, [], null, null);
/**
 * A widget displaying an image
 * @constructor
 */
gtk.Image = function() {
	gtk.Misc.apply(this);

	this._imgSrc = pango.Path.getRootPath().split("javascript")[0];
	this._stock = null;
	this._size = null;
	this._dom = null;
	this._minWidth = 50;
	this._minHeight = 50;
	this._width = this._minWidth;
	this._height = this._minHeight;
	var self = this;

	this._render = function(){
		this._domObj.className += " gtk_image";
			var table = jsgtk.Dom.create({append: this._domObj, tag: "table", style: 'width: 100%; height: 100%;'});
				var tr = jsgtk.Dom.create({append: table, tag: "tr"});
					var td = jsgtk.Dom.create({append: tr, tag: "td", style: 'vertical-align: middle; text-align: center;'});
						this._dom = jsgtk.Dom.create({append: td, tag: "img", src: this._imgSrc + "images/icons/32x32/image-missing.png"});

		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + "px";
	};

	this._render();
};

gtk.Image.prototype = new gtk.Misc();
gtk.Image.prototype.constructor = gtk.Image;

gtk.Image.prototype.resize = function(width, height){
	this._resizeWidth(width);
	this._resizeHeight(height);
};

/*
* Sets the image data from the stock item identified by stock_id
* @param {String} A stock icon name which is assigned in pango_constant.js
* @param {integer} 	A stock icon size
*/
gtk.Image.prototype.setFromStock = function(stockId, size){
    this._stock = stockId;
   	this._size = size;
    this._dom.src = this._imgSrc + "images/icons/" + size + "/" + stockId;
    switch(size){
        case "16x16" :
            this._width = 16;
            this._height = 16;
            break;
        case "22x22" :
            this._width = 22;
            this._height = 22;
            break;
        case "24x24" :
            this._width = 24;
            this._height = 24;
            break;
        case "32x32" :
            this._width = 32;
            this._height = 32;
            break;
        default :
            this._width = 48;
            this._height = 48;
    }

    this._minWidth = this._width;
    this._minHeight = this._height;
    this.resize(this._width, this._height);
};

/**
* Get the stock icon name and the stock icon size of the image data
* @return {Array} An array containing the stock icon name and the stock icon size of the image data
*/
gtk.Image.prototype.getStock = function (){
    var stock = {
        id : this._stock,
        size: this._size
    };
    return stock;
};

/**
* Set Image src from given file
* @param {String} filename which is assigned when we call the method.
*/
gtk.Image.prototype.setFromFile = function(fileName, width, height){
    var file = fileName || this._imgSrc + "images/icons/32x32/image-missing.png";
	this._dom.src = file;

	this._minWidth = this._width = width;
	this._minHeight = this._height = height;

	this.resize(this._width, this._height);
};

/**
* Get Image's size from stock
* @return {Integer} imageSize
*/
gtk.Image.prototype.getImageSize = function(){
	return this._size.split('x')[0];
};
/**
 * Label class
 * @constructor
 */
gtk.Label = function(text) {
	gtk.Misc.apply(this);

	this._dom = null;
	this._text = text || "Label";
	this._attribute;
	this._isSelectable = false;

	this._render = function(){
			this._domObj.className += " gtk_label";
			var table = jsgtk.Dom.create({append: this._domObj, tag: "table", style: 'width: 100%; height: 100%;'});
				var tr = jsgtk.Dom.create({append: table, tag: "tr"});
					var td = jsgtk.Dom.create({append: tr, tag: "td", "className": "gtk_label_align"});
						this._dom = jsgtk.Dom.create({append: td, tag: "label", 'className': 'gtk_none_selectable'});
						this._dom.innerHTML = this._text;
	        this._minWidth = this._width = this._calculateMinWidthMinHeight()[0];
	        this._minHeight = this._height = this._calculateMinWidthMinHeight()[1];
			this._domObj.style.width = this._width + "px";
			this._domObj.style.height = this._height + "px";
		this.hide();
	};

	this._render();
}

gtk.Label.prototype = new gtk.Misc();
gtk.Label.prototype.constructor = gtk.Label;

gtk.Label.prototype.resize = function(width, height){
	this._resizeWidth(width);
	this._resizeHeight(height);
};

gtk.Label.prototype._applyAttribute = function(){
	var clonedObj = this._dom.cloneNode(true);
	for(el in this._attribute){
		clonedObj.style[el] = this._attribute[el];
	}
	this._domObj.childNodes[0].childNodes[0].childNodes[0].replaceChild(clonedObj, this._dom);
}

/**
 * Set text to label
 * @param {String} text which is assigned when we call the method.
 */
gtk.Label.prototype.setText = function(text){
	this._text = text;
	this._dom.innerHTML = text;
	var size = this._calculateMinWidthMinHeight();
	this._minWidth = this._width = size[0];
	this._minHeight = this._height = size[1];
	this.resize(size[0], size[1]);
	this.emit("bubble", this._width, this._height);
};

gtk.Label.prototype._calculateMinWidthMinHeight = function(width){
    var _tempDom = this._dom.cloneNode(true);
    _tempDom.style.position = "absolute";
    _tempDom.style.width = width? width + "px" : "";
    _tempDom.style.height = "";

	var width = jsgtk.Util.fullWidth(_tempDom);
	var height = jsgtk.Util.fullHeight(_tempDom);

	return [width , height];
};

/**
 * Get text from label
 * @return {String} text
 */
gtk.Label.prototype.getText = function(){
	return this._text;
};

/**
 * Set attributes
 * @param {array} array of attributes object
 */
gtk.Label.prototype.setAttribute = function(attribute){
	this._attribute = attribute;
	this._applyAttribute();
};

/**
 * Get attributes
 * @return {Array} array of attributes object
 */
gtk.Label.prototype.getAttribute = function(){
	return this._attribute;
};

/**
 * Set label's text selectable
 * @param {boolean} setting
 */
gtk.Label.prototype.setSelectable = function(setting){
	this._isSelectable = setting;
	var className = this._isSelectable ? "gtk_selectable" : "gtk_none_selectable";
	this._dom.className = className;
};

/**
 * Get label's text selectable
 * @return {boolean}
 */
gtk.Label.prototype.getSelectable = function(){
	return this._isSelectable;
};

/**
 * Visible label as display = block if display != inline.
 */
gtk.Label.prototype.show = function(){
	if(this._domObj.style.display != 'inline') this._domObj.style.display = 'block';
};

gtk.Label.prototype.setWidthChars = function(width){
    var size = this._calculateMinWidthMinHeight(width);
    this._minWidth = width;
    this._width = width;
    this._minHeight = this._height = size[1];

    this.resize(this._width, this._height);
    this.emit("bubble", this._width, this._height);
};

gtk.Label.prototype.setJustify = function(justify){
    this._dom.parentNode.style.textAlign = justify;
}

/** @private */
gtk.Label.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);
};

gtk.Label.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);
};
/*
* A pushbutton widget that issues a signal when clicked.
* @param {String} label The text to be displayed by the button label or None if no label is required
* @param {Stock} stock The stock id identifying the stock image and text to be used in the button or None if no stock id is to be used
*/
gtk.Button = function(label, stock){
	gtk.Bin.apply(this);
	var self = this;
	this._imgSrc = pango.Path.getRootPath().split("javascript")[0];
	this._stock = stock || "";
	this._label = label || "";
	this._widget1 = null;
	this._widget2 = null;

	this._minWidth = 16;
	this._minHeight = 16;

	this._width = this._minWidth;
	this._height = this._minHeight;

	this._render = function(){

	    this._domObj.className += " gtk_button";
	    this._domObj.style.display = "table";
	    this._domObj.style.position = "relative";
	        this._gradient = jsgtk.Dom.create({'append': this._domObj, "tag": 'div', 'class': 'gtk_button_gradient'});
	        this._gradient.style.height = this._height / 2 + 'px';
		    this._imageDom = jsgtk.Dom.create({"tag": "div", "style": "float: left; position: relative;"});
		    this._labelDom = jsgtk.Dom.create({"tag": "div", "style": "float: left; position: relative;"});

		this._domObj.style.width = this._width - this.borderWidth + 'px';
		this._domObj.style.height = this._height - this.borderWidth + "px";
	};

	jsgtk.Event.addDomListener(this._domObj, 'mouseup', function(){
	    self.setActivateSignal("clicked");
		self.activate();
	}, false);

    this._render();
};

gtk.Button.prototype = new gtk.Bin();
gtk.Button.prototype.constructor = gtk.Button;

/** @private */
gtk.Button.prototype._positionWidget = function(widget, widgetDom){
    var top = (this._height  - widget.getHeight()) / 2;
    var left = (this._width - widget.getWidth() - this.borderWidth)/2;

    widgetDom.style.top = top + 'px';
    widgetDom.style.left = left + 'px';
};

/** @private */
gtk.Button.prototype.resize = function(width, height){

    this._resizeWidth(width);
    this._resizeHeight(height);

    if(this._widget2 && this._widget1){
        if(this._imagePosition == "topPosition"){
            this._imageDom.style.cssFloat = "";
            this._labelDom.style.ccsFloat = "";
            this._labelDom.style.top = "0px";
            this._imageDom.style.left = (this._width / 2) - (this._widget2.getWidth() / 2) + "px";
            this._labelDom.style.left = (this._width / 2) - (this._widget1.getWidth() / 2) + "px";
        }
        else{
            var imageTop = (this._height / 2) - (this._widget2.getHeight() / 2);
            var imageLeft = (this._width - this._widget2.getWidth() - this._widget1.getWidth() - this.borderWidth)/2;
            this._imageDom.style.top = imageTop + 'px';
            this._imageDom.style.left = imageLeft + 'px';

            var labelTop = (this._height / 2) - (this._widget1.getHeight() / 2);
            this._labelDom.style.top = labelTop + 'px';
            this._labelDom.style.left = parseInt(this._imageDom.style.left) + 'px';
        }
        return;
    }

    if(this._widget2) this._positionWidget(this._widget2, this._imageDom);

    if(this._widget1) this._positionWidget(this._widget1, this._labelDom);
};

/** @private */
gtk.Button.prototype._getMaxChildrenHeight = function(){
    var maxHeight = this._height;
    if(this._widget2) maxHeight = maxHeight > this._widget2.getHeight() ? maxHeight : this._widget2.getHeight();
    if(this._widget1) maxHeight = maxHeight > this._widget1.getHeight() ? maxHeight : this._widget1.getHeight();

    return maxHeight;
};

/** @private */
gtk.Button.prototype._getMaxChildrenWidth = function(){
    var maxWidth = 0;
    if(this._widget2) maxWidth += this._widget2.getWidth();
    if(this._widget1) maxWidth += this._widget1.getWidth();
    maxWidth += 15;
    maxWidth = maxWidth < this._width ? this._width : maxWidth;
    return maxWidth;
};

/**
 * Sets the "image" property to the value of image
 * @param {gtk.Widget} image Sets the "image" property to the value of image
 */
gtk.Button.prototype.setImage = function(image){
    if(this._imageDom.childNodes) this._imageDom.innerHTML = "";
    this._widget2 = image;

    this._minWidth = this._getMaxChildrenWidth();
    this._minHeight = this._getMaxChildrenHeight();

    this.resize(this._minWidth, this._minHeight);

    this._widget2._domObj.style.display = "";

    this._imageDom.appendChild(this._widget2._domObj);
    this._domObj.insertBefore(this._imageDom, this._domObj.childNodes[1]);
};

gtk.Button.prototype.setButtonShape = function(image){
	this._domObj.className += " gtk_button_with_image_shap";
	this._gradient.style.display = "none";
	this._domObj.style.backgroundImage = "url("+image._dom.src+")";
	this.setSizeRequest(image._width, image._height);
	this.resize(image._width, image._height);

};

/**
 * Returns the value of the "image" property
 * @return The gtk.Widget used as the button image or None if there is no image
 */
gtk.Button.prototype.getImage = function(){
    return this._widget2;
}

/**
 * Sets the text of the button label to label
 * @param {gtk.Label} A label to be set as the text in the button label
 */
gtk.Button.prototype.setLabel = function(label){
    if(this._labelDom.childNodes) this._labelDom.innerHTML = "";
    this._widget1 = label;
    this._label = label.getText();

    this._minWidth = this._getMaxChildrenWidth();
    this._minHeight = this._getMaxChildrenHeight();

    this.resize(this._minWidth, this._minHeight);
    this._widget1.setJustify("center");
    this._widget1._domObj.style.display = "";

    this._labelDom.appendChild(this._widget1._domObj);
    this._domObj.appendChild(this._labelDom);
};

/**
 * Retrieves the text from the label of the button
 * @return The text of the label widget
 */
gtk.Button.prototype.getLabel = function(){
    return this._label;
};

/** @private */
gtk.Button.prototype._resizeHeight = function(height){
	this._domObj.style.height = height - this.borderWidth + 'px';
	this._domObj.childNodes[0].style.height = height / 2 + 'px';
	this._height = height;
};

/** @private */
gtk.Button.prototype._resizeWidth = function(width){
	this._domObj.style.width = width - this.borderWidth + 'px';
	this._width = width;
};

/** @private */
gtk.Button.prototype._setImagePosition = function(position){
    this._imagePosition = position;
    if(position == "topPosition"){
        this._imageDom.style.cssFloat = "";
        this._labelDom.style.ccsFloat = "";
        this._labelDom.style.top = "0px";
        this._imageDom.style.left = (this._width / 2) - (this._widget2.getWidth() / 2) + "px";
        this._labelDom.style.left = (this._width / 2) - (this._widget1.getWidth() / 2) + "px";

        var imageLabelHeight = this._widget1.getHeight() + this._widget2.getHeight();
        this._height = (this._height > imageLabelHeight)? this._height : imageLabelHeight;
        this._domObj.style.height = this._height - this.borderWidth + 'px';
	    this._domObj.childNodes[0].style.height = this._height / 2 + 'px';
    }
}

/** @private */
gtk.Button.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);
};

/** @private */
gtk.Button.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);
};

gobject.signalNew("clicked", gtk.Button, null, null, []);
/*
* A choice of one of multiple check buttons. gtk.RadioButton, a class inherite from gtk.CheckButton
* @constructor
* @param {gtk.RadioButton} group An existing gtk.RadioButton or None
* @param {String} label A string to use as the button text or None
*/

gtk.RadioButton = function(group, label){
	gtk.Button.apply(this);
	var self = this;

	this._name = group ? group.getName() : new UUID().id;
	this._label = label || "";
	this._imgSrc = pango.Path.getRootPath().split("javascript")[0];
	this._activated = false;
	this._addToGroup(this);

	this._isToggled = false;
	this._widget1 = null;
	this._widget2 = new gtk.Label(this._label);
	this._widget2.setJustify(gtk.JUSTIFY_CENTER);
	this._widget2.show();

	this._radioButtonWidth = 16;
	this._radioButtonHeight = 16;

	this._minWidth = this._getMaxChildrenWidth();
	this._minHeight = this._getMaxChildrenHeight();

	this._width = this._minWidth;
	this._height = this._minHeight;

	this._render = function(){
	    this._domObj.className += " gtk_radio_button";
		    this._radioButton = jsgtk.Dom.create({'append': this._domObj, "tag": "div", "className": "gtk_radio_button_radio_img"});
		    this._radioButton.style.width = this._radioButtonWidth + 'px';
		    this._radioButton.style.height = this._radioButtonHeight + 'px';

		    this._widgetDom2 = jsgtk.Dom.create({'append': this._domObj, "tag": "div", "className": "gtk_radio_button_child"});
            this._widgetDom2.appendChild(this._widget2._domObj);

		this._domObj.style.width = this._width - this.borderWidth + 'px';
		this._domObj.style.height = this._height - this.borderWidth + "px";

	};

	this._radio_img_className = "gtk_radio_button_radio_img";

	jsgtk.Event.addDomListener(this._domObj, 'mouseup', function(){
        self.unMarkeOther(self);
        self.emit("toggled");
	}, false);

    this._render();
    this.resize(this._width, this._height);
};

gtk.RadioButton.group = [];

gtk.RadioButton.prototype = new gtk.Button();
gtk.RadioButton.prototype.constructor = gtk.RadioButton;



gtk.RadioButton.prototype.setActive = function(isActive){
	this._activated = isActive;
};

gtk.RadioButton.prototype.getActive = function(){
	return this._activated;
};

gtk.RadioButton.prototype.unMarkeOther = function(btn){
    var group = gtk.RadioButton.group;
    for(var i = group.length; i--;){
        if(group[i].getName() === btn.getName()) group[i].deSelect();
    }
    btn.select();

};

gtk.RadioButton.prototype.select = function(){
    this._radioButton.className = this._radio_img_className + " gtk_radio_button_selected";
	this.setActive(true);

};

gtk.RadioButton.prototype.deSelect = function(){
    this._radioButton.className = this._radio_img_className;
	this.setActive(false);
};

gtk.RadioButton.prototype.getGroup = function(){
    var group = gtk.RadioButton.group;
    var tmpGroup = [];
    for(var i = group.length; i--;){
        if(group[i].getName() === this.getName()) tmpGroup.push(group[i])
    }
    return tmpGroup;
};

gtk.RadioButton.prototype.setGroup = function(group){
    if(group){
        var name = group.getName();
        if(name !== this.getName()){
            this.setName(name);
            this._radioButton.name = name;
        }
        return;
    }
    this._removeFromGroup();
};

gtk.RadioButton.prototype.getName = function(){
    return this._name;
};

gtk.RadioButton.prototype.setName = function(name){
    this._name = name;
};

/** @private */
gtk.RadioButton.prototype._addToGroup = function(group){
    gtk.RadioButton.group.push(group);
};

/** @private */
gtk.RadioButton.prototype._removeFromGroup = function(){
    var group = gtk.RadioButton.group;
    for(var i = group.length; i--;){
        if(group[i].getName() === this.getName()) group.splice(i, 1);
    }
};

/** @private */
gtk.RadioButton.prototype._getMaxChildrenWidth = function(){
    var width = this._radioButtonWidth + this._widget2.getWidth() + 5;
    return width > this._width ? width : this._width;
};

/** @private */
gtk.RadioButton.prototype._getMaxChildrenHeight = function(){
    var height = this._widget2.getHeight();
    return height > this._height ? height : this._height;
};

/** @private */
gtk.RadioButton.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);

    this._positionRadioButtonLabel();
};

/** @private */
gtk.RadioButton.prototype._positionRadioButtonLabel = function(){
    var widget1Top = (this._height / 2) - (parseInt(this._radioButton.style.height) / 2);
    this._radioButton.style.top = widget1Top - 2 + 'px';

    var labelTop = (this._height / 2) - (this._widget2.getHeight() / 2);
    this._widgetDom2.style.top = labelTop  + 'px';
    this._widgetDom2.style.left = parseInt(this._radioButton.style.left) + 'px';
};

gobject.signalNew("toggled", gtk.RadioButton, null, null, []);
/**
 * A toggle button widget styled as a checkbox and label
 * @constructor
 * @param {String} a string to be used as the label text or null
 */
gtk.CheckButton = function(label){

	gtk.Button.apply(this);
	this._label = label || "";
	this._widget1 = null;
	this._widget2 = new gtk.Label(this._label);
	this._widget2.setJustify(gtk.JUSTIFY_CENTER);
	this._widget2.show();
	this._activated = false;
	this._checkBoxWidth = 15;
	this._checkBoxHeight = 15;

	this._minWidth = this._getMaxChildrenWidth();
	this._minHeight = this._getMaxChildrenHeight();

	this._width = this._minWidth;
	this._height = this._minHeight;
	this._checkBoxWidth = 16;
	this._checkBoxHeight = 16;
	this._imgSrc = pango.Path.getRootPath().split("javascript")[0];

    /** @private */
	this._render = function(){
	    this._domObj.className += " gtk_check_button";
		    this._checkBox = jsgtk.Dom.create({'append': this._domObj, "tag": "div", "className": "gtk_check_button_checkbox"});
		    this._checkBox.style.width = this._checkBoxWidth + 'px';
		    this._checkBox.style.height = this._checkBoxHeight + 'px';

		    this._widgetDom2 = jsgtk.Dom.create({'append': this._domObj, "tag": "div", "className": "gtk_check_button_child"});
            this._widgetDom2.appendChild(this._widget2._domObj);

		this._domObj.style.width = this._width + 6 - this.borderWidth + 'px';
		this._domObj.style.height = this._height - this.borderWidth + "px";
	this._initEvent();
	};

    this._render();

    this.resize(this._width, this._height);
};

gtk.CheckButton.prototype = new gtk.Button();
gtk.CheckButton.prototype.constructor = gtk.CheckButton;

gtk.CheckButton.prototype._initEvent = function(){
	var self = this;
	var classValue = "gtk_check_button_checkbox";
	jsgtk.Event.addDomListener(this._domObj, 'mouseup', function(){
	    if(!self._isToggled){
	        self._checkBox.className = classValue + " gtk_check_button_checked";
	        self._isToggled = true;
	    }else{
	        self._checkBox.className = classValue;
	        self._isToggled = false;
	    }
		self.emit("checked", self._isToggled);
	}, false);
};

gtk.CheckButton.prototype.setActive = function(isActive){
	this._activated = isActive;
};

gtk.CheckButton.prototype.getActive = function(){
	return this._activated;
};


/** @private */
gtk.CheckButton.prototype._getMaxChildrenWidth = function(){
    var width = this._checkBoxWidth + this._widget2.getWidth() + 10;
    return width > this._width ? width : this._width;
};

/** @private */
gtk.CheckButton.prototype._getMaxChildrenHeight = function(){
    var height = this._widget2.getHeight();
    return height > this._height ? height : this._height;
};

/** @private */
gtk.CheckButton.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);

    this._positionCheckboxLabel();
};

/** @private */
gtk.CheckButton.prototype._positionCheckboxLabel = function(){
    var widget1Top = (this._height / 2) - (parseInt(this._checkBox.style.height) / 2);
    var widget1Left = (this._width / 2) - ( (parseInt(this._checkBox.style.width) + this._widget2.getWidth()) / 2);
    this._checkBox.style.top = widget1Top  + 'px';


    var labelTop = (this._height / 2) - (this._widget2.getHeight() / 2);
    this._widgetDom2.style.top = labelTop + 'px';
    this._widgetDom2.style.left = parseInt(this._checkBox.style.left) - 2 + 'px';
};
gobject.signalNew("checked", gtk.CheckButton, null, null, []);

gtk.ToggleButton = function(label){

	gtk.Button.apply(this);
	self = this;
	this._label = new gtk.Label(label);
	this._activated = false;
	this._widget1 = null;
	this._widget2 = null;
	this._minWidth = 16;
	this._minHeight = 16;
	this._width = this._minWidth;
	this._height = this._minHeight;

	this._drawIndicator = false;
	this._inconsistent = false;

	this._render = function(){
	    this._domObj.className += " gtk_toggle_button";
		    this._labelDom = jsgtk.Dom.create({"tag": "div", "style": "float: left; position: relative;"});
			this._setLabel(this._label);
		this._domObj.style.width = this._width + "px";
		this._domObj.style.height = this._height + "px";
		this._initEvent();
	};

	this._render();
};

gtk.ToggleButton.prototype = new gtk.Button();
gtk.ToggleButton.prototype.constructor = gtk.ToggleButton;

gtk.ToggleButton.prototype._initEvent = function(){
	var self = this;
	var isActive = false;
	var inconsistent = self.getInconsistent();

	jsgtk.Event.addDomListener(this._domObj, "click", function(){

		self.setActivateSignal("toggled");
		if(!isActive){
			self.setActive(true);
			self.activate();
			self._domObj.style.backgroundColor = "#9AC6F5";
			self._domObj.childNodes[0].style.backgroundColor = "#B8CDE4";
			isActive = true;
		}
		else{
			self._domObj.style.backgroundColor = "";
			self._domObj.childNodes[0].style.backgroundColor = "";
			self._domObj.style.border = "";
			self.setActive(false);
			self.activate();
			isActive = false;
		}
	}, false);
}

gtk.ToggleButton.prototype.activate = function(){
	var signal = this.getActivateSignal();
	this.emit(signal);
};

gtk.ToggleButton.prototype.setActive = function(isActive){
	this._activated = isActive;
};

gtk.ToggleButton.prototype.getActive = function(){
	return this._activated;
};

gtk.ToggleButton.prototype.toggled = function(){
	this.emit('toggled');
};

gtk.ToggleButton.prototype.setMode = function(drawIndicator){
	this._drawIndicator = drawIndicator;
};

gtk.ToggleButton.prototype.getMode = function(){
	return this._drawIndicator;
};

gtk.ToggleButton.prototype.setInconsistent = function(setting){
	this._inconsistent = setting;
};

gtk.ToggleButton.prototype.getInconsistent = function(){
	return this._inconsistent;
};

gtk.ToggleButton.prototype._positionWidget = function(widget, widgetDom){
    var top = (this._height / 2) - (widget.getHeight() / 2);
    var left = (this._width / 2) - (widget.getWidth() / 2);

    widgetDom.style.top = top + 'px';
    widgetDom.style.left = left + 'px';
};

gtk.ToggleButton.prototype.resize = function(width, height){

    this._resizeWidth(width);
    this._resizeHeight(height);
    if(this._widget1) this._positionWidget(this._widget1, this._labelDom);
};

gtk.ToggleButton.prototype._getMaxChildrenHeight = function(){

    var maxHeight = this._height;
    if(this._widget1) maxHeight = maxHeight > this._widget1.getHeight() ? maxHeight : this._widget1.getHeight();

    return maxHeight;
};

gtk.ToggleButton.prototype._getMaxChildrenWidth = function(){
    var maxWidth = 0;
    if(this._widget1) maxWidth += this._widget1.getWidth();
    maxWidth += 15;
    maxWidth = maxWidth < this._width ? this._width : maxWidth;
    return maxWidth;
};

gtk.ToggleButton.prototype._setLabel = function(label){

    this._widget1 = label;
	this._widget1.show();
    this._minWidth = this._getMaxChildrenWidth();
    this._minHeight = this._getMaxChildrenHeight();
    this.resize(this._minWidth, this._minHeight);
    this._labelDom.appendChild(this._widget1._domObj);
    this._domObj.appendChild(this._labelDom);
};

gtk.ToggleButton.prototype._resizeHeight = function(height){
	this._domObj.style.height = height -2 + 'px';
	this._domObj.childNodes[0].style.height = height / 2 + 'px';
	this._height = height;
};

gtk.ToggleButton.prototype._resizeWidth = function(width){
	this._domObj.style.width = width -2 + 'px';
	this._width = width;
};

gtk.ToggleButton.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);
};

gtk.ToggleButton.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);
};
gobject.signalNew("toggled", gtk.ToggleButton, null, null, []);
/**
 * A single line text entry field
 * @constructor
 * @param {String} maxLength The maximum length of the entry
 */
gtk.Entry = function(maxLength){
	gtk.Widget.apply(this);
    var self = this;
	this._dom = null;
	this._text = "";
	this._maxLength = maxLength || "";
	this._width = this._minWidth = 50;
	this._height = this._minHeight = 16;
	this._widthChars;
	this._span;
	this._visible = true;

	this._render = function(){
		var _self = this;
		this._domObj.className += " gtk_entry";
			this._span = jsgtk.Dom.create({append: this._domObj, tag: "span"});
				this._dom = jsgtk.Dom.create({append: this._span, tag: "input", type: "text"});
		this._updateWidthHeight();
		this.resize(this._width, this._height);

		this.hide();
	};

	this._render();

	jsgtk.Event.addDomListener(this._dom, "keyup", function(e){
        if(self._text != self._dom.value){
            self.emit("changed");
        }
        self.setText(self._dom.value);
        self.emit("keyreleaseevent", self._dom.value);
        if(e.keyCode === 13) self.emit("enterkeypressed", self._dom.value);
	    jsgtk.Event.stopBubble(e);
	}, false);

	jsgtk.Event.addDomListener(this._dom, "focus", function(e){
	    self.emit("focusinevent", self._dom.value);
	    if(self._label) self._label.style.display = "none";
	}, false);

	jsgtk.Event.addDomListener(this._dom, "blur", function(e){
	    self.emit("focusoutevent", self._dom.value);
	    if(self._label) if(!self._dom.value) self._label.style.display = "";
	}, false);


};

gtk.Entry.prototype = new gtk.Widget();
gtk.Entry.prototype.constructor = gtk.Entry;


gtk.Entry.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
	this._span.style.lineHeight = height + "px";
};

gtk.Entry.prototype.focus = function(){
    this._dom.focus();
};

gtk.Entry.prototype.setBorderVisible = function(isBorderVisible){
    if(!isBorderVisible){
        this._dom.style.border = "1px solid #FFF";
    }
};

/** @private */
gtk.Entry.prototype._resizeWidth = function(width){
	this._width = width;
	this._domObj.style.width = width - 7 + 'px';
	this._dom.style.width = width - 7 + 'px';
};

/**
 * Reset height by font size
 * @param {Interger} number in px
 */
gtk.Entry.prototype.resizeEntryByFont = function(size){
	this._dom.style.fontSize = size + "px";
	var tmpNode = this._dom.cloneNode(true);

	this._height = jsgtk.Util.fullHeight(tmpNode);
	this.setSizeRequest(this._width, this._height);
	this.resize(this._width, this._height);
	this.emit('bubble', this._width, this._height);
}

/**
 * Sets the "text" property to the value of text. The string in text replaces the current contents of the entry.
 * @param {String} text A string to use as the new contents of the entry
 */
gtk.Entry.prototype.setText = function(text){
	this._text = text;
	this._dom.value = this._text;
};

/**
 * Returns the value of the "text" property which is a string containing the contents of the entry.
 * @return {String} the contents of the entry as a string
 */
gtk.Entry.prototype.getText = function(){
	return this._text;
}

/**
 * sets the "width-chars" property to the value of n_char
 * @param {interger} nChars Width in chars
 */
gtk.Entry.prototype.setWidthChars = function(nChars){
 	this._widthChars = nChars;
 	this._updateWidthHeight(nChars);

    this.resize(this._width, this._height);

	this.emit('bubble', this._width, this._height);
};

/**
 * gets the value of the "widthChars" property which is set by the setWidthChars() method
 * @return {integer} number of chars to request space for
 */
gtk.Entry.prototype.getWidthChars = function(){
	return this._widthChars;
}

/**
 * sets the "max-length" property to the value of max
 * @param {interger} max The maximum length of the entry. The value passed in will be clamped to the range 0-65536.
 */
gtk.Entry.prototype.setMaxLength = function(max){
 	this._maxLength = max;
 	this._dom.setAttribute("maxlength", max);
};

/**
 * retrieves the value of the "max-length" property that specifies the maximum allowed length of the text in the entry.
 * @return {integer} The maximum allowed number of characters
 */
gtk.Entry.prototype.getMaxLength = function(){
	return this._maxLength;
};

/**
 * sets the "visibility" property to the value of visible. If visible is True  the contents of the entry are displayed as plain text. If visible is False, the contents are obscured by replacing the characters with the invisible character
 * @param {boolean} visible If False the contents are obscured using the "invisible-char"
 */
gtk.Entry.prototype.setVisibility = function(visible){
 	this._visible = visible;
 	this._visible? this._dom.setAttribute("type", "text"): this._dom.setAttribute("type", "password");
};

/**
 * retrieves the value of the "visibility" property that determines whether the text in entry is visible.
 * @return {boolean} True if the text is currently visible
 */
gtk.Entry.prototype.getVisibility = function(){
	return this._visible;
};

/**
 * Retrieves the current length of the text in entry
 * @return {interger} Return the current number of characters in GtkEntry, or 0 if there are none.
 */
gtk.Entry.prototype.getTextLength = function(){
	var charLength = this._dom.value.length;
	return charLength;
};

/** @private */
gtk.Entry.prototype._updateWidthHeight = function(size){
	var input = this._dom.cloneNode(true);
	if(size){
		var inputStyle = input.style;
		input.setAttribute("size", size);
		inputStyle.width = "";
		inputStyle.height = "";
		inputStyle.minWidth = "";
		inputStyle.minHeight = "";
	}
	document.body.appendChild(input);
	this._width = input.clientWidth - 10;
	this._height = input.clientHeight;
	this._minWidth = this._width;
	this._minHeight = this._height;
	document.body.removeChild(input);
};

gtk.Entry.prototype.setDisplayLabel = function(label){
    this._label = jsgtk.Dom.create({"tag": "span", "append": this._span, "className": "gtk_entry_label", "text": label});
}

gtk.Entry.prototype.getMinWidthComposite = function(){
	return this._minWidth;
};

gtk.Entry.prototype.getMinHeightComposite = function(){
	return this._minHeight;
};

gtk.Entry.prototype.resetHeightComposite = function(){
	var minSize = this.getSizeRequest();
	this.setHeight(minSize[1]);
};

gtk.Entry.prototype.resetWidthComposite = function(){
	var minSize = this.getSizeRequest();
	this.setWidth(minSize[0]);
};

gtk.Entry.prototype.resizeWidthComposite = function(width){
	this.resize(width, this._height);
};

gtk.Entry.prototype.resizeHeightComposite = function(height){
    this.resize(this._width, height);
};

gobject.signalNew("keyreleaseevent", gtk.Entry, null, null, []);
gobject.signalNew("enterkeypressed", gtk.Entry, null, null, []);
gobject.signalNew("focusinevent", gtk.Entry, null, null, []);
gobject.signalNew("focusoutevent", gtk.Entry, null, null, []);
gobject.signalNew("changed", gtk.Entry, null, null, []);
/**
 * A bin with a decorative frame and optional label
 * @constructor
 * @param A string to use as the label text or None if no label is required.
 */

gtk.Frame = function(label){
	gtk.Bin.apply(this);

	this._label = label || " ";
    this._labelXAlign = 0;
    this._labelYAlign = 0.5;
    this._child = null;

	this._minWidth = this._minContainerWidth = this._width = 100;
	this._minHeight = this._minContainerHeight = this._height = 150;
	this._childOffsetWidth = 18;
	this._childOffsetHeight = 39;


	this._render = function(){
		this._domObj.className += ' gtk_frame';
		    this._labelDom = jsgtk.Dom.create({'append': this._domObj, 'tag' : 'div'})
		        this._label = new gtk.Label(label);
    		    this._label.show();
    		    this._label.setJustify(gtk.JUSTIFY_CENTER);
    		    this._labelDom.appendChild(this._label._domObj);

		this._minWidth = this._minContainerWidth = this._width = this._label.getWidth() + 2;
		this._minHeight = this._minContainerHeight = this._height = this._label.getHeight() + 24;

		    this._frameArea = jsgtk.Dom.create({"append": this._domObj,"tag":"div", "className": "gtk_frame_area"});
		    this._frameArea.style.width = this._width - 2 + "px";
		    this._frameArea.style.height = this._height - 10 + "px";
		        this._widgetContainer = jsgtk.Dom.create({"append": this._frameArea, 'tag': 'div', 'style': 'position: relative'});
		        this._widgetContainer.style.left = "7px";

		this._domObj.style.height = this._height + "px";
		this._domObj.style.width = this._width + "px";
		this.setLabelAlign(this._labelXAlign, 0.5);
	}

	this._render();
};

gtk.Frame.prototype = new gtk.Bin();
gtk.Frame.prototype.constructor = gtk.Frame;

gtk.Frame.prototype.setBackgroundColor = function(color){
    this._domObj.style.backgroundColor = color;
};

/**
 * Add the child widget into Frame
 * @param {gtk.widget} widget A child widget to be displayed in Frame
 */

gtk.Frame.prototype.add = function(widget){
    if(this._child) return;

    this._child = widget;
    this._widgetContainer.appendChild(widget._domObj);
    widget.show();

    var size = this._getSize();
    this.resize(size[0], size[1]);
}

/**
 * Sets the text of the label as specified by label. If label is None the current label is removed
 * @param {String} label A string to be used as the label text
 */

gtk.Frame.prototype.setLabel = function(label){

    this._label.setText(label);

    this._resetMinWidthMinHeight(this._label);

    this.setLabelAlign(this._labelXAlign, this._labelYAlign);

};

/**
 * Returns the text in the label widget
 * @return The text in the label, or None if there is no label widget.
 */
gtk.Frame.prototype.getLabel = function(){
    return this._label.getText();
};

/**
 * set the label widget (usually to something other than a gtk.Label widget) for the frame
 * @param {gtk.Widget} widget The new label widget
 */
gtk.Frame.prototype.setLabelWidget = function(widget){
    this.setLabel(widget.getText());
    this._labelWidget = widget;
	this._domObj.style.width = 	this._labelWidget._minWidth + "px";
	this._frameArea.style.width = this._labelWidget._minWidth + "px";
};

/**
 * Retrieves the label widget for the frame
 * @return the label widget, or null if there is no label widget
 */
gtk.Frame.prototype.getLabelWidget = function(){
    return this._labelWidget;
};

/**
 * Sets the alignment of the frame's label widget and decoration (defaults are 0.0 and 0.5) as specified by xalign and yalign
 * @param {Float} xAlign The horizontal alignment of the label widget along the top edge of the frame (in the range of 0.0 to 1.0)
 * @param {Float} yAlign The vertical alignment of the decoration with respect to the label widget (in the range 0.0 to 1.0)
 */
gtk.Frame.prototype.setLabelAlign = function(xAlign, yAlign){
    this._labelXAlign = xAlign;
    this._labelYAlign = yAlign;
    var left = (this._width - this._label.getWidth()) * xAlign -1;
    if(left < 1) left = 1;
    this._labelDom.style.left = left + "px";
};

/**
 * returns an Array containing the X and Y alignment of the frame's label widget and decoration
 * @return An Array containing the x and y alignments of the frame's label widget
 */
gtk.Frame.prototype.getLabelAlign = function(){
    return [this._labelXAlign, this._labelYAlign];
};

gtk.Frame.prototype._getSize = function(){
    var width  = this._child.getMinWidthComposite();
    var height = this._child.getMinHeightComposite();
    width      = this._minContainerWidth  > width  ? this._minContainerWidth  : width;
    height     = this._minContainerHeight > height ? this._minContainerHeight : height;
    return [width + this._childOffsetWidth, height + this._childOffsetHeight];
};

gtk.Frame.prototype._resetMinWidthMinHeight = function(label){
    if(this._minWidth < label.getWidth()) this._minWidth = label.getWidth();
    if(this._minHeight < label.getHeight()) this._minHeight = label.getHeight();
}

gtk.Frame.prototype._setLabelXAlign = function(){
    this._labelXAlign = (this._width/2) - parseInt(this._labelDom.style.width)/2;
};

gtk.Frame.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
    this._resizeChildren(width, height);
    this.setLabelAlign(this._labelXAlign, this._labelYAlign);
};

gtk.Frame.prototype._resizeWidth = function(width){
    if(this._minWidth > width) return;

    if(this._width < width) this._width = width;
    else width = this._width;

    this._domObj.style.width = width - 2 + "px";
        this._frameArea.style.width = width - 4 + "px";
            this._widgetContainer.style.width = width - this._childOffsetWidth + 'px';
};

gtk.Frame.prototype._resizeHeight = function(height){
    this._domObj.style.height = height - 2 + "px";
        this._frameArea.style.height = height - 12 + "px" ;
            this._widgetContainer.style.height = height - this._childOffsetHeight + 'px';
    this._height = height;
};

gtk.Frame.prototype._resizeChildren = function(width, height){
    this._child.resizeWidthComposite(width - this._childOffsetWidth);
    this._child.resizeHeightComposite(height - this._childOffsetHeight);
}


gtk.Frame.prototype.getMinWidthComposite = function(){
	var minWidth = this._child.getMinWidthComposite();
    if(this._minWidth < minWidth)
		this._minWidth = minWidth;
	return this._minWidth + this._childOffsetWidth;
};

gtk.Frame.prototype.getMinHeightComposite = function(){
	var minHeight = this._child.getMinHeightComposite();
    if(this._minHeight < minHeight)
		this._minHeight = minHeight;
	return this._minHeight + this._childOffsetHeight;
};

gtk.Frame.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this.setWidth(minWidth);
	this.resize(minWidth, this._height);
};

gtk.Frame.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite? height : minHeightComposite;
	this.resize(this._width, minHeight);
};
/**
 * A widget which indicates progress visually.
 */
gtk.ProgressBar = function() {

	gtk.Widget.apply(this);
	var _self = this;
	this._pulseStep = 0.1;
	this._fraction = 0.0;
	this._domProgress = null;
	this._tmpPulseStep = 0.0;
	this._tmpBoolean = true;
	this._orientation = gtk.PROGRESS_LEFT_TO_RIGHT;
	this._width = this._minWidth = 100;
	this._height = this._minHeight = 20;
	this._text = "";
    this._textHeight = jsgtk.Util.calculateTextWidthHeight(this._text)[1];

	this.render = function() {
		this._domObj.className += " gtk_progressBar";
		this._domText = jsgtk.Dom.create({"tag":"div", "text": this._text, "class": "gtk_progress_bar_text", "append" : this._domObj});
		this._domProgress = jsgtk.Dom.create({"tag":'div', "class": "gtk_progressBar_loader", "append":this._domObj});
		this._domObj.style.width = this._width + "px";
		this._domObj.style.height = this._height + "px";
		    this._domText.style.top = jsgtk.Util.getTextFromTop(this._height, this._textHeight) + 'px';
		this.hide();
	};

	this.render();
};

gtk.ProgressBar.prototype = new gtk.Widget();
gtk.ProgressBar.prototype.constructor = gtk.ProgressBar;

/**
* Nudges the progressbar to indicate that some progress has been made, but you don't know how much. This method also changes progress bar mode to "activity mode," where a block bounces back and forth
*/
gtk.ProgressBar.prototype.pulse = function() {
	var tmpStep = parseFloat(this._tmpPulseStep).toFixed(1);
	if(tmpStep >= 0.8){
			this._tmpBoolean = false;
	}else if(tmpStep <= 0.0) {
			this._tmpBoolean = true;
	}

	if(this._tmpBoolean == true){
		this._tmpPulseStep = this._tmpPulseStep + this.getPulseStep();
	}
	else{
		this._tmpPulseStep =  this._tmpPulseStep - this.getPulseStep();
	}

	if(this._orientation == gtk.PROGRESS_LEFT_TO_RIGHT || this._orientation == gtk.PROGRESS_RIGHT_TO_LEFT) {

		this._domProgress.style.width = '20%';
		this._domProgress.style.height = '100%';
		if(tmpStep < 0.9) this._domProgress.style.left = tmpStep * 100 + "%";
		else this._domProgress.style.left = "80%";

	}else{

		this._domProgress.style.width = '100%';
		this._domProgress.style.height = '20%';
		if(tmpStep < 0.9) this._domProgress.style.top =  tmpStep * 100 + "%";
		else this._domProgress.style.top = "80%";
	}

};

/**
 * Switches the progress bar to a different orientation as specified by the value of orientation
 * @param {Constant} The orientation of the progress bar
 */
gtk.ProgressBar.prototype.setOrientation = function(orientation) {
	this._orientation = orientation || gtk.PROGRESS_LEFT_TO_RIGHT;
};

/**
 * Returns the current progress bar orientation.
 * @return The orientation of the progress bar
 */
gtk.ProgressBar.prototype.getOrientation = function(orientation) {
	return this._orientation;
};

/**
 * Sets the portion (specified by fraction) of the total progress bar length to move the bouncing block for each call to the pulse() method.
 * @param {Float} fraction A value between 0.0 and 1.0
 */
gtk.ProgressBar.prototype.setPulseStep = function(fraction) {
	fraction = parseFloat(fraction);
	if(!fraction || fraction < 0.1 || fraction > 1.0){
		this._pulseStep = 0.1;
	}
	else this._pulseStep = fraction;
};

/**
* Causes the progress bar to "fill in" the portion of the bar specified by fraction. The value of fraction should be between 0.0 and 1.0.
* @param {Float} fraction The fraction of the task that's been completed
*/
gtk.ProgressBar.prototype.setFraction = function(fraction) {
	var _self = this;
	fraction = parseFloat(fraction);
	if(fraction < 0.1 || fraction > 1){
		this._fraction = 0.1;
	}
	else this._fraction = fraction;

	if(this._orientation == gtk.PROGRESS_LEFT_TO_RIGHT){
		this._domProgress.style.height = '100%';
		this._domProgress.style.width = this._fraction * 100 + 1 + '%';
	}else if(this._orientation == gtk.PROGRESS_RIGHT_TO_LEFT){
		this._domProgress.style.height = '100%';
		this._domProgress.style.left = 100 - (this._fraction * 100) + '%';
		this._domProgress.style.width = '0%';
		this._domProgress.style.width =   this._fraction * 100 + '%';
	}else if(this._orientation == gtk.PROGRESS_TOP_TO_BOTTOM){
		this._domProgress.style.width = '99.8%';
		this._domProgress.style.height = this._fraction * 100 + 1 + '%';
		this._domProgress.style.left = "1px";
	}else if(this._orientation == gtk.PROGRESS_BOTTOM_TO_TOP){
		this._domProgress.style.width = '99.8%';
		this._domProgress.style.height = '0%';
		this._domProgress.style.top =  100 - (this._fraction * 100 + 1) + '%';
		this._domProgress.style.height = this._fraction * 100 + 1 + '%';
		this._domProgress.style.left = "1px";
	}
};

/*
* Returns the current fraction of the task that's been set by the set_fraction() method
* @return {Float} A fraction from 0.0 to 1.0
*/
gtk.ProgressBar.prototype.getFraction = function() {
	return this._fraction;
};

/**
 * Returns the pulse step set with the set_pulse_step()
 * @return {Float} A fraction from 0.0 to 1.0
 */
gtk.ProgressBar.prototype.getPulseStep = function() {
	return this._pulseStep;
};

/**
* Superimposes the text specified by text on the progress bar
* @param {String} text A UTF-8 string
*/
gtk.ProgressBar.prototype.setText = function(text) {
	this._text = ""+ text;
	this._domText.innerHTML = this._text;
	this._textHeight = jsgtk.Util.calculateTextWidthHeight(this._text)[1];
};

/**
* Returns the text superimposed on the progress bar. If there is no superimposed text this method returns None.
* @return {String} The text, or None
*/
gtk.ProgressBar.prototype.getText = function() {
	return this._text;
}

gtk.ProgressBar.prototype.resize = function(width, height){
	this._resizeWidth(width);
    this._resizeHeight(height);
};

gtk.ProgressBar.prototype._resizeWidth = function(width){
	this._domObj.style.width = width - 2 + "px";
	this._width = width;
};

gtk.ProgressBar.prototype._resizeHeight = function(height){
	this._domObj.style.height = height - 2 + "px";
	this._height = height;
	this._domText.style.top = jsgtk.Util.getTextFromTop(this._height, this._textHeight) + 'px';
};

gtk.ProgressBar.prototype.resizeWidthComposite = function(width){
    var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
    this.resize(minWidth, this._height);
};

gtk.ProgressBar.prototype.resizeHeightComposite = function(height){
    var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
    this.resize(this._width, minHeight);
};
/**
 * class gtk.TreePath
 */
 gtk.TreePath = function(path){
 	this.pathInt = 0;
 	this.pathStr = path ? path : "0";
 	this.pathArr = [0];
};


/**
 * Class gtk.TreeIter
 * follow composite pattern: TreeStore will contains one or more treeiter
 * interface : 'add(), remove(), run(), getChild(index)'
 */
gtk.TreeIter = function(path){
	gtk.Object.apply(this);
 	this.path = new gtk.TreePath(path).pathStr;
 	this.children = new Array();
 	this.row = new Array();
};

gtk.TreeIter.prototype = new gtk.Object();
gtk.TreeIter.prototype.constructor = gtk.TreeIter;

/**
 * Returns a copy of the treeiter.
 * return {object} treeiter
 */
gtk.TreeIter.prototype.copy = function(){
 	return this;
};

gtk.TreeIter.prototype.getChildByPath = function(path){
    var paths = path.split(":");
    var childPath = paths[0];
    var child = this.children[childPath];
    if(child === undefined) return null;
    paths.splice(0,1);
    if(child.getChildren().length > 0){
        return child.getChildByPath(paths.join(":"));
    }else return this.children[childPath];
};

gtk.TreeIter.prototype.setRow = function(row){
	this.row = row;
};

gtk.TreeIter.prototype.getRow = function(){
	return this.row;
};

gtk.TreeIter.prototype.getPath = function(){
	return this.path;
};

gtk.TreeIter.prototype.run = function(view, targetSibbling, cols, margin, isExpanded, width, height, docFragment){
	if(!isExpanded) view.renderRows(this, cols, targetSibbling, margin, width, height, docFragment);
	else{
		for(var i = 0, len = this.children.length; i < len; i++){
			var child = this.children[i];
			child.run(view, targetSibbling, cols, margin, false, width, height);
		}
	}
};

/**
* getChildren() method
* @param {array} children: array of children of gtk.TreeIter type
*/
gtk.TreeIter.prototype.getChildren = function(){
	return this.children;
};

/**
* add() method
* @param{object} child: object of of gtk.TreeIter type
*/
gtk.TreeIter.prototype.add = function(child){
	this.children.push(child);
};

/*
* remove() method : remove a child
* @param {object} child: child of gtk.TreeIter type
*/
gtk.TreeIter.prototype.remove = function(child){
	for(var i = this.children.length; i--;){
		if(this.children[i] === child){
			this.children.splice(i, 1);
			break;
		}
	}
};

/**
* getChild() method
* @param {integer} index : index of child
* @return {object} child: child of gtk.TreeIter type
*/
gtk.TreeIter.prototype.getChild = function(index){
	return this.children[index] || null;
};
/**
 * Class gtk.ListStore
 * Constructor: one or more column types
 * follow composite pattern: ListStore will contains one or more treeiter
 * interface : 'add(), remove(), run(), getChild(index)'
 */
gtk.ListStore = function(){
 	gtk.Object.apply(this);
 	this._columns = new Array();
	this._modelType = gtk.LISTSTORE;
 	this.children = new Array();
 	for(var i = 0, len = arguments.length; i < len; i++){
		this._columns.push(arguments[i]);
 	}
 };

gtk.ListStore.prototype = new gtk.Object();
gtk.ListStore.prototype.constructor = gtk.ListStore;

/**
 * The append() method appends a new row to the liststore
 * row : a tuple or list containing ordered column values to be set in the new row
 * @return {object} a gtk.TreeIter pointing to the new row
 */
gtk.ListStore.prototype.append = function(row){
	var row = this._filterRow(row);
	var iter = new gtk.TreeIter(this.children.length.toString() + ':');
	iter.setRow(row);
	this.add(iter);
	return iter;
};

gtk.ListStore.prototype.getChildByPath = function(path){
    for(var i = this.children.length; i--;){
        var child = this.children[i];
        if(child.getPath() === path) return child;
    }
};

gtk.ListStore.prototype.getModelType = function(){
	return this._modelType;
};


/**
 * _filterRow() method: filter the column of row so it match the this._columns
 */
gtk.ListStore.prototype._filterRow = function(row){
	var filters = [];
	for(var i = 0, len = this._columns.length; i < len; i++){
		if(row[i] === null || row[i] === "" || row[i] === undefined){
			filters.push('');
			continue;
		}
		filters.push(row[i]);
 	}
 	return	filters;
};

gtk.ListStore.prototype.getChildren = function(){
	return this.children;
};

gtk.ListStore.prototype.getColumns = function(){
	return this._columns;
};

gtk.ListStore.prototype.run = function(view, targetSibbling, cols, margin, isExpanded, width, height, docFragment){
	var self = this;
	for(var i = 0, len = this.children.length; i < len; i++){
		var child = this.children[i];
		child.run(view, targetSibbling, cols, margin, isExpanded, width, height, docFragment);
	}
};

gtk.ListStore.prototype.add = function(child){
	this.children.push(child);
};

gtk.ListStore.prototype.remove = function(child){
	for(var i = this.children.length; i--;){
		if(this.children[i] === child){
			this.children.splice(i, 1);
			break;
		}
	}
};

gtk.ListStore.prototype.getChild = function(index){
	return this.children[index] || null;
};

gtk.ListStore.prototype.search = function(text){
    var re = new RegExp("^" + text.toLowerCase());
    var children = this.children;
    var result = ""

    for(var i = 0, len = children.length; i < len; i++){
        var row = children[i].getRow();
        for( j = row.length; j--;){
            result = row[j].toLowerCase().match(re);
            if(result){
                return children[i].getPath();
            }
        }

    }
}
/**
 * Class gtk.TreeStore
 * Constructor: one or more column types
 * follow composite pattern: TreeStore will contains one or more treeiter
 * interface : 'add(), remove(), run(), getChild(index)'
 */
gtk.TreeStore = function(){
 	gtk.Object.apply(this);
 	this._columns = new Array();
	this._modelType = gtk.TREESTORE;
 	this.children = new Array();
 	for(var i = 0, len = arguments.length; i < len; i++){
		this._columns.push(arguments[i]);
 	}
 };

gtk.TreeStore.prototype = new gtk.Object();
gtk.TreeStore.prototype.constructor = gtk.TreeStore;

/**
 * append() method : appends a new row to the liststore
 * parent : a gtk.TreeIter, or None
 * row : a tuple or list containing ordered column values to be set in the new row
 * @return {object} a gtk.TreeIter pointing to the new row
 */
gtk.TreeStore.prototype.append = function(parent, row){
	var row = this._filterRow(row);
	if(parent){
		var path = parent.getPath() + parent.getChildren().length.toString() + ':';
		var iter = new gtk.TreeIter(path);
		iter.setRow(row);
		parent.add(iter);
	}else{
		var iter = new gtk.TreeIter(this.children.length.toString() + ':');
		iter.setRow(row);
		this.add(iter);
	}
	return iter;
};

gtk.TreeStore.prototype.getModelType = function(){
	return this._modelType;
};

/**
 * _filterRow() method: filter the column of row so it match the this._columns
 */
gtk.TreeStore.prototype._filterRow = function(row){
	var filters = [];
	for(var i = 0, len = this._columns.length; i < len; i++){
		if(row[i] === null || row[i] === "" || row[i] === undefined){
			filters.push('');
			continue;
		}
		filters.push(row[i]);
 	}
 	return	filters;
};

gtk.TreeStore.prototype.getChildByPath = function(path){
    var paths = path.split(":")
    var childPath = paths[0];
    var child = this.children[parseInt(childPath)];
    paths.splice(0,1);
    if(child.getChildren().length > 0){
        return child.getChildByPath(paths.join(":"));
    }
    else return this;
};

gtk.TreeStore.prototype.getChildren = function(){
	return this.children;
};

gtk.TreeStore.prototype.getColumns = function(){
	return this._columns;
};

gtk.TreeStore.prototype.run = function(view, targetSibbling, cols, margin, isExpanded){
	for(var i = 0, len = this.children.length; i < len; i++){
		var child = this.children[i];
		child.run(view, targetSibbling, cols, margin, isExpanded);
	}
};

gtk.TreeStore.prototype.add = function(child){
	this.children.push(child);
};

gtk.TreeStore.prototype.remove = function(child){
	for(var i = this.children.length; i--;){
		if(this.children[i] === child){
			this.children.splice(i, 1);
			break;
		}
	}
};

gtk.TreeStore.prototype.getChild = function(index){
	return this.children[index] || null;
};
/**
 * class gtk.TreeView Follow composite pattern: treevie will contains one or more treeviewcolumns. Interface : 'add(), remove(), run(), getChild(index)'
 */
gtk.TreeView = function(model){
	gtk.Container.apply(this);

	this._width = 	this._minWidth = 100;
	this._height = this._minHeight = 20;
	this._currentHeight = this._height;

	this._tvColumns = [];

	this._tvColumnsRepo = [];
	this._titleHeight = 18;
	this._cellHeight = 20;
	this._headerVisible = true;
	this._model = model || null;
	this._vAdjustment = new gtk.Adjustment(0,0,0);
	this._hAdjustment = new gtk.Adjustment(0,0,0);

	this._render = function(){
		this._domObj.className += " gtk_treeview";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';

			this._domTitle = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'className': "gtk_treeview_header"});
			this._domTitle.style.height = this._titleHeight + 'px';
			this._domTitle.style.width = this._width + 'px';

			this._cellDom = jsgtk.Dom.create({'append': this._domObj, 'className': 'gtk_treeview_body','tag': 'div'});
			this._cellDom.style.height = this._height - this._titleHeight + 'px';
			this._cellDom.style.width = this._width + 'px';

			this._emptyCell = jsgtk.Dom.create({"tag": "div"});
		this.hide();
	};
	this._render();

	new gtk.TreeViewController(this, model);
};

gtk.TreeView.prototype = new gtk.Container();
gtk.TreeView.prototype.constructor = gtk.TreeView;

gtk.TreeView.prototype.setBorderVisible = function(setBorder){
	if(!setBorder){
		this._domTitle.style.borderTop = "solid 1px #FFF";
		this._domTitle.style.borderLeft = "solid 1px #FFF";
		this._domTitle.style.borderRight = "solid 1px #FFF";
		this._cellDom.style.border = "solid 1px #FFF";
	}
	else {
		this._domTitle.style.borderTop = "solid 1px #EFC169";
		this._domTitle.style.borderLeft = "solid 1px #EFC169";
		this._domTitle.style.borderRight = "solid 1px #EFC169";
		this._cellDom.style.border = "solid 1px #EFC169";
	}
};

gtk.TreeView.prototype.getColumns = function(){
	return this._tvColumns;
};

gtk.TreeView.prototype.setModel = function(model){
	this._model = model;
};

gtk.TreeView.prototype.getModel = function(){
	return this._model;
};

gtk.TreeView.prototype.appendColumn = function(tvcolumn) {
	if(this._isValideColumn(tvcolumn)){
		this._clearTreeView();
		this.add(tvcolumn);
		this.run();
		this._hAdjustment.setAll(0, this._width);
		this._vAdjustment.setAll(0, this._height);
	}
};

gtk.TreeView.prototype.removeColumn = function(tvcolumn) {
	if(this._isContain(this.getColumns(), tvcolumn)){
		this._clearTreeView();
		this.remove(tvcolumn);
		this.run();
		this._hAdjustment.setAll(0, this._width);
		this._vAdjustment.setAll(0, this._height);
	}
};

gtk.TreeView.prototype.setVadjustment = function(adjustment){
    this._vAdjustment = adjustment;
};

gtk.TreeView.prototype.getVadjustment = function(){
    return this._vAdjustment;
};

gtk.TreeView.prototype.setHadjustment = function(adjustment){
    this._hAdjustment = adjustment;
};

gtk.TreeView.prototype.getHadjustment = function(){
    return this._hAdjustment;
};

gtk.TreeView.prototype.hideColumn = function(index) {
	var tvcolumn = this.getChild(index);
	if(tvcolumn){
		this.remove(tvcolumn);
		tvcolumn.hideCells();
		this._decreaseWidth(tvcolumn.getWidth());
		this._resizeHeader();
		this._resizeRows();
	}
};

gtk.TreeView.prototype.showColumn = function(index) {
	var tvcolumn = this.getChildInRepo(index);
	if(tvcolumn){
		this.add(tvcolumn);
		tvcolumn.show();
		this._resizeWidth(this._getColsWidth());
		this._resizeHeader();
		this._resizeRows();
	}
};

gtk.TreeView.prototype._isContain = function(tvColumns, tvColumn){
	for(var i = tvColumns.length; i--;){
		if(tvColumns[i] === tvColumn) return true;
	}
	return false;
};

gtk.TreeView.prototype._clearTreeView = function(){
	this._domTitle.innerHTML = "";
	this._cellDom.innerHTML = "";
	var columns = this.getColumns();
	for(var i = columns.length; i--;) columns[i].empty();
};

gtk.TreeView.prototype._updateColWidth = function(){
	var children = this._model.getChildren();


	for(var i = this._tvColumns.length; i--;){
		var column = this._tvColumns[i];
        maxColWidth = column.getWidth();


		column.run(maxColWidth);
	}
};

gtk.TreeView.prototype._getColsWidth = function(){
	var width = 0;
	for(var i = this._tvColumns.length; i--;){
		width += this._tvColumns[i].getWidth();
	}
	return width;
};

gtk.TreeView.prototype.setHeadersVisible = function(headerVisible){
    this._headerVisible = headerVisible !== undefined ? headerVisible : true;
    if(!this._headerVisible){
        this._domTitle.parentNode.removeChild(this._domTitle);
        this._resizeHeight(this._height);
    }
};

gtk.TreeView.prototype._appendHeaders = function(){
	for(var i = 0, len = this._tvColumns.length; i < len; i++){
		var column = this._tvColumns[i];
		var className = i ? 'gtk_header_cell' : 'gtk_first_header_cell';
		column.render(this._domTitle, className);
	}
};

gtk.TreeView.prototype._resize = function(){
	this._resizeWidth(this._getColsWidth());
	if(this._getColHeight() > this._height) this._resizeHeight(this._getColHeight());
	if(this._getColHeight() < this._currentHeight) this._resizeHeight(this._currentHeight);
	else this._resizeHeight(this._getColHeight());
	this._resizeHeader();
	this._resizeRows();
};

gtk.TreeView.prototype._resizeHeader = function(){
	for(var i = this._tvColumns.length; i--;)
		this._domTitle.childNodes[i].style.width = this._tvColumns[i].getWidth() + 'px';
};

gtk.TreeView.prototype._resizeRows = function(){
	var colLength = this._model.getColumns().length - 1;
	var columHeight = this._getColHeight();
	for(var i = 0, len = this._cellDom.childNodes.length; i < len; i++){
		var rowOrder = (i % 2 === 0) ? 'even' : 'odd';
		var row = this._cellDom.childNodes[i];
		row.className = 'row_' + rowOrder;
		row.style.width = this._getColsWidth() + colLength +'px';
		row.style.height = this._cellHeight + "px";
		for(var j = 0, length = this._tvColumns.length; j < length; j++){
			var cell = row.childNodes[j];
			cell.style.width = this._tvColumns[j].getWidth() + 'px';
			cell.style.height = this._cellHeight + "px";
		}
	}
};

gtk.TreeView.prototype._getColHeight = function(){
	var tHeight = 0;
	for(var i = this._cellDom.childNodes.length; i--;){
		var row = this._cellDom.childNodes[i];
		tHeight += parseInt(row.style.height);
	}
	return tHeight;
};

gtk.TreeView.prototype._isValideColumn = function(col){
	return this._model.getColumns()[col.getIndex()] === col.getAttribute();
};

gtk.TreeView.prototype._decreaseWidth = function(width){
	var colLength = this._model.getColumns().length - 1;
	var width = this._width - width;
		width += colLength; //plus number of white space between cells
		this._domObj.style.width = width +'px';
			this._domTitle.style.width = width + 'px';
			this._cellDom.style.width = width + 'px';
		this._width = width;
};

gtk.TreeView.prototype._resizeWidth = function(width){
	var colLength = this._model.getColumns().length - 1;
	this._domObj.style.width = width + colLength +'px';
		this._domTitle.style.width = width + colLength+ 'px';
		this._cellDom.style.width = width + colLength+ 'px';
	this._width = width;
};

gtk.TreeView.prototype._resizeHeight = function(height){
    this._height = height;
    if(this._headerVisible){
        this._cellDom.style.height = this._height + 2 + "px";
        this._domObj.style.height = this._height + this._titleHeight + 2 + "px";
    }
    else {
        this._cellDom.style.height = this._height + this._titleHeight + 2 + 'px';
    	this._domObj.style.height = this._height + this._titleHeight + 2 + 'px';
    }
};

gtk.TreeView.prototype._appendRow = function(row, sibbling){
	if(sibbling) this._cellDom.insertBefore(row, sibbling);
	else this._cellDom.appendChild(row);
};

gtk.TreeView.prototype.renderRows = function(iter, cols, sibbling, margin){
	var self = this;
	var cell;
	var row = jsgtk.Dom.create({'tag': 'div', 'id': iter.path});
	row.style.height = this._cellHeight + 'px';
	row.style.width = this._width + 'px';

	this._appendRow(row, sibbling);

		for(var i = 0, len = cols.length; i < len; i++){

			var col = cols[i];
			var colIndex = col.getIndex();

			if(!colIndex & (this.getModel().getModelType() === gtk.TREESTORE) ){

				var imgObj = self._collExpImg(iter, margin);
				cell = col.createCell(row, iter, margin, 16, imgObj.image);
				if(iter.getChildren().length > 0){

					imgObj.image.appendChild(imgObj.imageCollapse._domObj);

					jsgtk.Event.addDomListener(imgObj.imageCollapse._domObj, 'click', function(){
						imgObj.image.replaceChild(imgObj.imageExpand._domObj, imgObj.imageCollapse._domObj);
						self.emit('rendersubrows', row, iter, cols, margin);
					});

					jsgtk.Event.addDomListener(imgObj.imageExpand._domObj, 'click', function(){
						self.emit('removerows', self._cellDom, self._cellDom.childNodes, imgObj.image.id);
						imgObj.image.replaceChild(imgObj.imageCollapse._domObj, imgObj.imageExpand._domObj);
						self._resize();
					});
				}
			}else{
                cell = col.createCell(row, iter, 0, 0, null);
			}
            var offsetWidth = cell.getOffsetWidth()
			var width = offsetWidth > col.getWidth() ? offsetWidth : col.getWidth();
			if(this._model.getModelType() === gtk.TREESTORE)col.setWidth(width);

			cell.connect('cellselected', function(text, path){
			    self.emit('rowselected', text, path);
			    self.emit("lastoffspringselected", self._model.getChildByPath(path));
			})
		}
	this._resize();
};

gtk.TreeView.prototype._collExpImg = function(iter, margin){
	var image = jsgtk.Dom.create({'tag': 'div', id: iter.path, 'style': 'float: left;'});
		image.style.width =	16 + 'px';
		image.style.height = 16 + 'px';
		image.style.marginLeft = margin + 'px';

			var imageCollapse = new gtk.Image();
			imageCollapse.show();
			imageCollapse.setFromStock(pango.STOCK_COLLAPSE, pango.ICON_SIZE_MENU);

			var imageExpand = new gtk.Image();
			imageExpand.show();
			imageExpand.setFromStock(pango.STOCK_EXPANDED, pango.ICON_SIZE_MENU);
	return {image: image, imageExpand: imageExpand, imageCollapse: imageCollapse};
};

gtk.TreeView.prototype.removeChildNodes = function(parentNode, childNodes, id){
	var re = new RegExp("^" + id);
	for(var i = childNodes.length; i--;){
		var node = childNodes[i];
		if(node.id === id) continue;
		if(node.id.match(re)) parentNode.removeChild(node);
	}
};


gtk.TreeView.prototype.add = function(child){
	this._tvColumns.push(child);
	this._tvColumnsRepo.push(child);
};

gtk.TreeView.prototype.remove = function(child){
	for(var i = this._tvColumns.length; i--;){
		if(this._tvColumns[i] === child){
			this._tvColumns.splice(i, 1);
			break;
		}
	}
};

gtk.TreeView.prototype.getChild = function(index){
	return this._tvColumns[index] || null;
};

gtk.TreeView.prototype.getChildInRepo = function(index){
	return this._tvColumnsRepo[index] || null;
};

gtk.TreeView.prototype.run = function(){

	this._updateColWidth();

	this._appendHeaders();

	this.emit('renderrows', this.getColumns());
};

gtk.TreeView.prototype.getMinWidthComposite = function(){
    var tvCols = this._tvColumns;
    var minWidth = 0;
    for(var i = tvCols.length; i--;){
        minWidth += tvCols[i].getMinWidthComposite();
	}
	return minWidth;
};

gtk.TreeView.prototype.resizeWidthComposite = function(width){
    var tvCols = this._tvColumns;
    var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	var offsetWidth = minWidth - minWidthComposite
	var extraWidth = offsetWidth / tvCols.length;

    for(var i = tvCols.length; i--;){
        tvCols[i].setWidth(tvCols[i].getMinWidthComposite() + extraWidth);
	}
	this._resize();
};

gtk.TreeView.prototype.resizeHeightComposite = function(height){
    this._resizeHeight(height);
    this._currentHeight = height;
};


gobject.signalNew('renderrows', gtk.TreeView, [], null, null);
gobject.signalNew('rendersubrows', gtk.TreeView, [], null, null);
gobject.signalNew('removerows', gtk.TreeView, [], null, null);
gobject.signalNew('rowselected', gtk.TreeView, [], null, null);
gobject.signalNew('lastoffspringselected', gtk.TreeView, [], null, null);
/**
 * class gtk.TreeViewColumn
 */
gtk.TreeViewColumn = function(title, cell_renderer, colWidth){
	gtk.Object.apply(this);

	this._title = title || 'title';
	this._cellRender = cell_renderer || {};
	this._attr;
	this._col;
	this._expand = true;
	var width = jsgtk.Dom.getTextSize(this._title)[0];
	this._width = this._minWidth = colWidth > width ? colWidth : width;
	this._cells = [];
	this._row;
	this._domObj;
};

gtk.TreeViewColumn.prototype = new gtk.Object();
gtk.TreeViewColumn.prototype.constructor = gtk.TreeViewColumn;

gtk.TreeViewColumn.prototype.hideHeader = function(){
    this._domObj.style.display = "none";
};

gtk.TreeViewColumn.prototype.render = function(row, className){
	this._row = row;
	this._domObj = jsgtk.Dom.create({'append': row, 'class': className, 'tag': 'div', 'text': this._title, 'style': 'float: left;'});
	this._domObj.style.width = this.getWidth() + 'px';
};

gtk.TreeViewColumn.prototype.packStart = function(cell, expand){
	var self = this;
	this._expand = (expand === undefined) ? true : expand;
	this._cellRender = this._cellRender ? this._cellRender : cell;
};

gtk.TreeViewColumn.prototype.addAttribute = function(cell, attribute, column){
	this._cellRender = this._cellRender ? this._cellRender : cell;
	this._attr = attribute || gobject.TYPE_STRING;
	this._col = (column === undefined) ? null : column ;
};

gtk.TreeViewColumn.prototype.getAttribute = function(){
	return this._attr;
};

gtk.TreeViewColumn.prototype.getIndex = function(){
	return this._col;
};

gtk.TreeViewColumn.prototype.setWidth = function(width){
	this._width = width;
};

gtk.TreeViewColumn.prototype.getWidth = function(){
	return this._width;
};

gtk.TreeViewColumn.prototype.run = function(width){
	this.setWidth(width);
};

gtk.TreeViewColumn.prototype.empty = function(){
	this._cells = [];
};

gtk.TreeViewColumn.prototype.show = function(){
	this._row.appendChild(this._domObj);
	var cells = this._cells;
	for( var i = cells.length; i--;){
		cells[i].show();
	}
};

gtk.TreeViewColumn.prototype.Cellshide = function(){
	this._row.removeChild(this._domObj);
	var cells = this._cells;
	for( var i = cells.length; i--;){
		cells[i].hide();
	}
};

gtk.TreeViewColumn.prototype.createCell = function(row, iter, margin, imgWidth, imgObj){

	var path = iter.path;

	var newCell = new gtk.CellRendererText(this.getWidth(), this.getIndex());
	newCell.render(row, iter.getRow()[this.getIndex()], margin, imgWidth, imgObj);

	var cell = this._getCellByPath(path);

	if(cell) cell.run(path, newCell);
	else{
		newCell.setPath(path);
		this.add(newCell);
	}

	return newCell;
};

gtk.TreeViewColumn.prototype.add = function(cell){
	this._cells.push(cell);
};

gtk.TreeViewColumn.prototype._getCellByPath = function(path){
	var cellPath = path.split(':');
	var cells = this._cells;
	for( var i = cells.length; i--;){
		if(cells[i].getPath() === cellPath[0] + ':') return cells[i];
	}
	return null;
};

gtk.TreeViewColumn.prototype.getMinWidthComposite = function(){
	return this._minWidth;
};
/**
 * class gtk.CellRendererText
 */
gtk.CellRenderer = function(){
	gtk.Object.apply(this);

	this._minWidth = gtk.CELLRENDERER_WIDTH;
	this._minHeight = gtk.CELLRENDERER_HEIGHT;
};

gtk.CellRenderer.prototype = new gtk.Object();
gtk.CellRenderer.prototype.constructor = gtk.CellRenderer;
/**
 * class gtk.CellRendererText
 */
gtk.CellRendererText = function(width, index, className){
	gtk.CellRenderer.apply(this);
	this._cellHeight = 20;
	this._width = width || 0;
	this._index = index || 0;
	this._text = "";
	this._isHiLighted = false;
	this._className = className || "first_cell";
	this._path = "0:";
	this._offsetWidth = 0;
	this._cells = [];
	this._domObj = jsgtk.Dom.create({'tag': 'div', 'style': 'float: left; overflow: hidden;'});
	this._row;
};

gtk.CellRendererText.prototype = new gtk.CellRenderer();
gtk.CellRendererText.prototype.constructor = gtk.CellRendererText;

gtk.CellRendererText.prototype.render = function(row, text, margin, imgWidth, imgObj, width, height){

    var self = this;
	this._text = text;
   	row.appendChild(this._domObj);
    var margin = margin || 0;
    var height = height || this._cellHeight;
	this._row = row;
	this._domObj.style.width = this._width + 'px';
	this._domObj.style.height = height + 'px';
	this._domObj.className = this._index ? 'cell' : this._className;

	if(imgObj) this._domObj.appendChild(imgObj);
		var content = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'text': text, 'style': 'overflow: hidden;'});
		var size = jsgtk.Dom.getTextSize(text);
		content.style.width = size[0] + 'px';
		content.style.height = this._cellHeight + 'px';
		content.style.position = "relative";
		content.style.left = "4px";
	this._offsetWidth = (jsgtk.Dom.getTextSize(text)[0] + margin + imgWidth);

	jsgtk.Event.addDomListener(this._domObj, 'mousedown', function(){
        self.emit('cellselected', text, self.getPath());
    }, false);

    jsgtk.Event.addDomListener(this._domObj, 'mouseover', function(){
        self.emit('cellhilighted');
    }, false);
}

gtk.CellRendererText.prototype.getOffsetWidth = function(){
	return this._offsetWidth;
};

gtk.CellRendererText.prototype.setPath = function(path){
	this._path = path;
};

gtk.CellRendererText.prototype.getPath = function(){
	return this._path;
};

gtk.CellRendererText.prototype.getText = function(){
	return this._text;
};

gtk.CellRendererText.prototype.setText = function(text){
	this._text = text;
};

gtk.CellRendererText.prototype.show = function(){
	var cells = this._cells;
	for(var i = cells.length; i--;) cells[i].show();
	this._row.appendChild(this._domObj);
};

gtk.CellRendererText.prototype.hide = function(){
	var cells = this._cells;
	for(var i = cells.length; i--;) cells[i].hide();
	this._row.removeChild(this._domObj);
};

gtk.CellRendererText.prototype.add = function(cell){
	this._cells.push(cell);
};

gtk.CellRendererText.prototype.run = function(path, newCell){
	var searchPath = this._getSearchPath(path);
	var cells = this._cells;
	for(var i = cells.length; i--;){
		if(cells[i].getPath() === searchPath) {
			cells[i].run(path, newCell);
			return;
		}
	}
	this.add(newCell);
	newCell.setPath(path);
};

gtk.CellRendererText.prototype.activateHilight = function(){
    var self = this;
    var parentNode = self._domObj.parentNode.parentNode;
    var sibblings = parentNode.childNodes;
    jsgtk.Event.addDomListener(this._domObj, 'mouseover', function(e){
        self._isHiLighted = true;
        if(parentNode.hasAnHilightedChild){
            parentNode.hasAnHilightedChild = false;
        }
        self.setText(self._domObj.firstChild.innerHTML);
	    jsgtk.Event.stopBubble(e);
	}, false);
	 jsgtk.Event.addDomListener(this._domObj, 'mouseout', function(e){
	   jsgtk. Event.stopBubble(e);
	    self._isHiLighted = false;
	}, false);
};

gtk.CellRendererText.prototype._getSearchPath = function(path){
	var givenPaths = path.split(":");
	var paths = this.getPath().split(":");
	var searchPath = this.getPath() + givenPaths[paths.length - 1] + ':';
	return searchPath;
};

gtk.CellRendererText.prototype.getNode = function(){
	return this._domObj;
};

gobject.signalNew('cellselected', gtk.CellRendererText, [], null, null);
gobject.signalNew('cellhilighted', gtk.CellRendererText, [], null, null);

gtk.Viewport = function(hadjustment, vadjustment){
	gtk.Bin.apply(this);

	this._vAdjustment = vadjustment || new gtk.Adjustment(0,0,0) ;
	this._hAdjustment = hadjustment || new gtk.Adjustment(0,0,0);
	this._child = null;
	this._domObj;
	this.hide();
};

gtk.Viewport.prototype = new gtk.Bin();
gtk.Viewport.prototype.constructor = gtk.Viewport;

gtk.Viewport.prototype.add = function(widget){
    var self = this;
	if(!this._child){
		this._child   = widget;
		this._domObj  = widget._domObj;
		var minWidth  = widget.getMinWidthComposite();
		var minHeight = widget.getMinHeightComposite();
		this._vAdjustment.setLower(minHeight);
		this._hAdjustment.setLower(minWidth);
	}else{
	}
};

gtk.Viewport.prototype.setVadjustment = function(adjustment){
    this._vAdjustment = adjustment;
};

gtk.Viewport.prototype.getVadjustment = function(){
    return this._vAdjustment;
};

gtk.Viewport.prototype.setHadjustment = function(adjustment){
    this._hAdjustment = adjustment;
};

gtk.Viewport.prototype.getHadjustment = function(){
    return this._hAdjustment;
};
/*
* class gtk.TreeViewController
*/
gtk.TreeViewController = function(view, model){
	this._view = view;
	this._model = model;
	var self = this;
	this._view.connect('renderrows', function(cols){
		self._model.run(self._view, null, cols, 0, false);
	});
	this._view.connect('rendersubrows', function(row, iter, cols, margin){
		iter.run(self._view, row.nextSibling, cols, margin + 10, true);
	});
	this._view.connect('removerows', function(parentNode, childNodes, id){
		self._view.removeChildNodes(parentNode, childNodes, id);
	});
};
/*
* Class Toolbar A bar holding buttons and other widgets
*/

gtk.Toolbar = function() {
	gtk.Container.apply(this);

	this._height = this._minHeight;
	this._width = this._minWidth;
	this._widgetsInToolbar = [];
	this._render = function(){
		this._domObj.className += " gtk_toolbar";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this.hide();
	};

	this._render();
};

gtk.Toolbar.prototype = new gtk.Container();
gtk.Toolbar.prototype.constructor = gtk.Toolbar;

gtk.Toolbar.prototype.insert = function(item, pos){
    item.show();

    this._appendChild(item, pos);

    this.resizeChildren();
};

gtk.Toolbar.prototype.getItemIndex = function(item){

}

gtk.Toolbar.prototype.getNItems = function(){
    return this._widgetsInToolbar.length;
};

gtk.Toolbar.prototype.getNthItem = function(n){
    return this._widgetsInToolbar[n-1];
};

gtk.Toolbar.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
    this.resizeChildren();
}

gtk.Toolbar.prototype.resizeChildren = function(){
	var children = this._widgetsInToolbar;
	var childrenSize = this._getChildrenSize();

    this._width < childrenSize[0] ? this._resizeWidth(childrenSize[0]) : this._resizeChildrenWidth(childrenSize[0]);

	this._height < childrenSize[1] ? this._resizeHeight(childrenSize[1]): this._resizeChildrenHeight(this._height);
};

gtk.Toolbar.prototype._resizeChildrenHeight = function(height){
    var children = this._widgetsInToolbar;
    for(var i = 0, len = children.length; i < len; i++){
        children[i].resizeHeightComposite(height);
    }
}

gtk.Toolbar.prototype._resizeChildrenWidth = function(width){
    var expandElements = [];
    var children = this._widgetsInToolbar;
    for(var j = 0, len = children.length; j < len; j++){
        if(children[j].getExpand()) expandElements.push(children[j]);
    }
    if(expandElements.length > 0){
        var offsetWidth = this._width - width;
        var extraWidth = offsetWidth / expandElements.length;
        for(var i = 0, len = expandElements.length; i < len; i++){
            var element = expandElements[i];
            element.resizeWidthComposite(element.getMinWidthComposite() + extraWidth);
        }
    }
};

gtk.Toolbar.prototype._getChildrenSize = function(){
    var len = this._widgetsInToolbar.length;
    var totalChildrenWidth = 0;
    var maxChildHeight = 0;
    for(var i = 0; i < len; i++){
        var child = this._widgetsInToolbar[i];
        var childMinHeight = child.getMinHeightComposite();
        totalChildrenWidth += child.getMinWidthComposite();
        if(maxChildHeight < child.getMinHeightComposite()) maxChildHeight = child.getMinHeightComposite();
    }
    return [totalChildrenWidth, maxChildHeight];
};

gtk.Toolbar.prototype._appendChild = function(item, pos){
    item._domObj.style.cssFloat = "left";
    if(pos < 0){
        this._widgetsInToolbar.push(item);
        this._domObj.appendChild(item._domObj);
    }else{
        this._widgetsInToolbar.splice(pos,0,item);
        this._domObj.insertBefore(item._domObj, this._domObj.childNodes[pos]);
    }
}



/**
* getMinWidthComposite() composite method : get the min width of vbox. If it has children then the min width of children, else the min width of vbox itself.
* @return {integer} minWidth			  : the min width to be used when need decrease the width of vbox thus the decreasing can't go smaller then the minWidth
*/
gtk.Toolbar.prototype.getMinWidthComposite = function(){
	var children = this._widgetsInToolbar;
	var minWidth = 0;
	for(var i = children.length; i--;){
		minWidth += children[i].getMinWidthComposite();
	}
    this._minWidth = minWidth;
	return this._minWidth;
};

/**
* getMinHeightComposite() composite method : get the min height of vbox.
*								  			 if it has children then the min height of children,
*								  			 else the min height of vbox itself.
* @return {integer} minWidth			   : the min height to be used when need decrease the height of vbox
*								  			 thus the decreasing can't go smaller then the minHeight
*/
gtk.Toolbar.prototype.getMinHeightComposite = function(){
	var children = this._widgetsInToolbar;
	var minHeight = 1;
	for(var i = children.length; i--;){
		var height = children[i].getMinHeightComposite();
		if( height > minHeight & height != undefined) minHeight = height;
	}
	this._minHeight = minHeight;
	return this._minHeight;
};

/**
* resizeWidthComposite() composite method : decrease the width of vbox.
*											  decrease vbox's width and all the composite children
*
*/
gtk.Toolbar.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this.resize(minWidth - 1, this._height);
};

/**
* resizeHeightComposite() composite method : decrease the height of vbox.
*											   decrease vbox's height and all the composite children
*
*/
gtk.Toolbar.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
	this.resize(this._width, minHeight - 5);
};
/*
* Class ToolItem is the base class of widgets that can be added to gtk.Toolbar
* @constructor
*/

gtk.ToolItem = function() {
	gtk.Bin.apply(this);

	this._homogeneous = true;
	this._expand = false;
	this._children = [];
	this._minWidth = 32;
	this._minHeight = 32;
	this._width = this._minWidth;
	this._height = this._minHeight;
	this._expand;

	this._render = function(){
		this._domObj.className += " gtk_tool_item";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this.hide();
	};

	this._render();
};

gtk.ToolItem.prototype = new gtk.Bin();
gtk.ToolItem.prototype.constructor = gtk.ToolItem;

/**
 * Sets the expand setting of the tool item to the value of expand. If expand is True the tool item is allocated extra space when there is more room on the toolbar than needed for the items. The effect is that the item gets bigger when the toolbar gets bigger and smaller when the toolbar gets smaller.
 * @param {boolean} expand 	If True the tool item is allocated extra space when available
 */
gtk.ToolItem.prototype.setExpand = function(expand){
    this._expand = expand;
};

/**
 * Returns the value of the expand setting of the tool item. If True the tool item is allocated extra space.
 * @return True if the tool item is allocated extra space when available.
 */
gtk.ToolItem.prototype.getExpand = function(){
    return this._expand;
};

/*
*Method sets the homogeneous setting of the tool item to the value of homogeneous.
*@param {boolean} If homogeneous is True the tool item is to be allocated the same size as other homogeneous items.
*/
gtk.ToolItem.prototype.setHomogeneous = function(homogeneous){
	this._homogeneous = homogeneous;
	this.resize(this._width, this._height);
};

/*
*Method gets the value of homogeneous.
@return {boolean} If True the tool item is the same size as other homogeneous items
*/
gtk.ToolItem.prototype.getHomogeneous = function(homogeneous){
	return this._homogeneous;
};

/*
* A toolbar item that separates groups of other toolbar items. A class inherite from gtk.ToolItem
* @constructor
*/
gtk.SeparatorToolItem = function(){
	gtk.ToolItem.apply(this);

	this._width = this._minWidth = 8;
	this._height = this._minHeight;
	this._draw = false;
    this._render = function(){
        this._domObj.className += " gtk_separator_tool_item";
		this._line = jsgtk.Dom.create({"append":this._domObj, "tag":"div","class":"gtk_separator_invisible_line"});

    };
	this._render();
};

gtk.SeparatorToolItem.prototype = new gtk.ToolItem();
gtk.SeparatorToolItem.prototype.constructor = gtk.SeparatorToolItem;

/** @private */
gtk.SeparatorToolItem.prototype._resizeHeight = function(height){
	this._domObj.style.height = height - 2 + 'px';
	this._domObj.childNodes[0].style.height = "80%";
	this._height = height;
};

/** @private */
gtk.SeparatorToolItem.prototype.resize = function(width, height){
	this._resizeWidth(width);
    this._resizeHeight(height);
};

/**
 * Sets the "draw" property to the value of draw. If draw is True the gtk.SeparatorToolItem is drawn as a vertical line; if False, just blank
 * @param {boolean} draw If True the gtk.SeparatorToolItem  is drawn as a vertical line
 */
gtk.SeparatorToolItem.prototype.setDraw = function(draw){
	if(draw){
		this._line.style.visibility = "visible";
	}
	this._draw = draw;
};

/**
 * Returns True if the separator tool item is drawn as a line or False, if it's just blank.
 * @return True if separator_tool_item is drawn as a line, or just blank.
 */
gtk.SeparatorToolItem.prototype.getDraw = function(){
	return this._draw;
};

/** @private */
gtk.SeparatorToolItem.prototype.resizeWidthComposite = function(width){
    this.resize(width, this._height);
};

/** @private */
gtk.SeparatorToolItem.prototype.resizeHeightComposite = function(height){
    this.resize(this._width, height);
};
/**
 * Class ToolButton which is a container
 * @constructor
 * @param {Object} iconWidget It's a Dom object which will display image as icon for toolButton. But you can use Stock_id which is represent a constant of image here.
 * @param {String} label Normal text to display in button
 */

gtk.ToolButton = function(iconWidget, label){
	gtk.ToolItem.apply(this);

	var self = this;
	this._labelWidget = new gtk.Label(label);
	this._labelWidget.setJustify(gtk.JUSTIFY_CENTER);
	this._iconWidget = iconWidget;

	this._minWidth = 16;
	this._minHeight = 16;

	this._width = this._minWidth;
	this._height = this._minHeight;

    this._render = function(){
        this._domObj.className += " gtk_tool_button";
        this._button = new gtk.Button();

        this._button.setImage(this._iconWidget);
        this._button.setLabel(this._labelWidget);
        this._labelWidget.show();
        this._iconWidget.show();
        this._button._setImagePosition(gtk.POS_TOP);
        this._button._domObj.style.display = "";
        this._domObj.appendChild(this._button._domObj);

    this._minWidth = this._getMaxChildrenWidth();
    this._minHeight = this._getMaxChildrenHeight();

    this._resizeWidth(this._width);
    this._resizeHeight(this._height);

    };
	this._render();
	this.hide();

	jsgtk.Event.addDomListener(this._domObj, "click", function(){
	    self.emit("clicked");
	});
};

gtk.ToolButton.prototype = new gtk.ToolItem();
gtk.ToolButton.prototype.constructor = gtk.ToolButton;

gtk.ToolButton.prototype.setLabel = function(text){
    var label = text || "";
    this._labelWidget.setText(label);
    this._button.setLabel(this._labelWidget);

    this._minWidth = this._getMaxChildrenWidth();
    this._minHeight = this._getMaxChildrenHeight();

    this.resize(this._width, this._height);
};

gtk.ToolButton.prototype.getLabel = function(){
    return this._labelWidget.getText();
};

gtk.ToolButton.prototype.setLabelWidget = function(labelWidget){
    this._labelWidget = labelWidget;
    this._button.setLabel(this._labelWidget);
};

gtk.ToolButton.prototype.getLabelWidget = function(){
    return this._labelWidget;
}

gtk.ToolButton.prototype.setIconWidget = function(iconWidget){
    this._iconWidget = iconWidget;
    this._button.setImage(this._iconWidget);

    this._minWidth = this._getMaxChildrenWidth();
    this._minHeight = this._getMaxChildrenHeight();

    this.resize(this._width, this._height);
};

gtk.ToolButton.prototype.getIconWidget = function(){
    return this._iconWidget;
};

gtk.ToolButton.prototype.resize = function(width, height){

    this._resizeWidth(width);
    this._resizeHeight(height);

    this._rePositionChild();
};


gtk.ToolButton.prototype._resizeHeight = function(height){
	this._domObj.style.height = height -2 + 'px';
	this._height = height;
	this._domObj.childNodes[0].style.height = height -2 + 'px';
	this._domObj.childNodes[0].childNodes[0].style.height = height/2 + "px";
};

gtk.ToolButton.prototype._resizeWidth = function(width){
	this._domObj.style.width = width -2 + 'px';
	this._width = width;
	this._domObj.childNodes[0].style.width = width -2 + 'px';
};

gtk.ToolButton.prototype._getMaxChildrenHeight = function(){

    var maxHeight = this._height;
    var iconHeight = 0;
    var labelHeight = 0;
    if(this._iconWidget) iconHeight = this._iconWidget.getHeight();
    if(this._labelWidget) labelHeight = this._labelWidget.getHeight();
    maxHeight = iconHeight + labelHeight;
    this._height = maxHeight;

    return maxHeight;
};

gtk.ToolButton.prototype._getMaxChildrenWidth = function(){
    var maxWidth = 0;
    if(this._iconWidget) maxWidth += this._iconWidget.getWidth();
    if(this._labelWidget) maxWidth += this._labelWidget.getWidth();
    maxWidth += 15;
    maxWidth = maxWidth < this._width ? this._width : maxWidth;
    this._width = maxWidth;
    return maxWidth;
};

gtk.ToolButton.prototype._rePositionChild = function(){

    this._domObj.childNodes[0].childNodes[1].style.top =  (this._height / 2) - (this._iconWidget.getHeight() / 2) - (this._labelWidget.getHeight() / 2) + 'px';
    this._domObj.childNodes[0].childNodes[2].style.top = (this._height / 2) - (this._labelWidget.getHeight() / 2) - (this._iconWidget.getHeight() / 2) + 'px';

    this._domObj.childNodes[0].childNodes[1].style.left =  (this._width / 2) - (this._iconWidget.getWidth() / 2) + 'px';
    this._domObj.childNodes[0].childNodes[2].style.left = (this._width / 2) - (this._labelWidget.getWidth() / 2) + 'px';

};

gtk.ToolButton.prototype.getMinWidthComposite = function(){
    return this._minWidth;
};

gtk.ToolButton.prototype.getMinHeightComposite = function(){
    return this._minHeight;
};

gtk.ToolButton.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);

};

gtk.ToolButton.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);

};

gobject.signalNew('clicked', gtk.ToolButton, [], null, null);
/**
* class gtk.Dom - a widget which is used to append domObj into.
*                 this is custom widget, not exist in gtk
*/
gtk.Dom = function(width, height) {
	gtk.Container.apply(this);

	this._width  = this._minWidth  = width  || 100;
	this._height = this._minHeight = height || 100;

	this._dom = jsgtk.Dom.create({'tag': 'div'});

	this._render = function(){
	    var domObj = this._domObj
		domObj.className   += " gtk_dom";
		domObj.style.width  = this._width + 'px';
		domObj.style.height = this._height + 'px';
		this.hide();
	};

    this._render();
};

gtk.Dom.prototype = new gtk.Container();
gtk.Dom.prototype.constructor = gtk.Dom;

gtk.Dom.prototype.append = function(dom){
    this._dom = dom;
    this._domObj.appendChild(dom);
    var size = this._getChildSize();
    this.resize(size[0], size[1]);
};

gtk.Dom.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
};

gtk.Dom.prototype._resizeWidth = function(width){
	this._width = width;
	this._domObj.style.width = this._width - 2 + 'px';
	this._dom.style.width = this._width - 5 + 'px';
};

gtk.Dom.prototype._resizeHeight = function(height){
	this._height = height;
	this._domObj.style.height = this._height - 2 + 'px';
	this._dom.style.height = this._height;
};

gtk.Dom.prototype._getChildSize = function(){
    var tmpNode = this._dom.cloneNode(true);
    var width    = jsgtk.Util.fullWidth(tmpNode)  ? jsgtk.Util.fullWidth(tmpNode)  : this._width;
    var height   = jsgtk.Util.fullHeight(tmpNode) ? jsgtk.Util.fullHeight(tmpNode) : this._height;
    width  = width  < this._minWidth  ? this._minWidth  : width;
    height = height < this._minHeight ? this._minHeight : height;
    return [width + 5, height + 10];
};

gtk.Dom.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this.resize(minWidth, this._height);
};

gtk.Dom.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
	this.resize(this._width, minHeight);
};
/**
* class gtk.Panel
*/
gtk.Panel = function(title, padding) {
	gtk.Container.apply(this);

	this._width               = this._minWidth  = 200;
	this._height              = this._minHeight = 200;
	this._title               = title || "gtk Title";
	this._activeTitle         = this._getMinimizedTitle(this._title, this._width);
	this._minimizedWidth      = 150;
	this._headerHeight        = 27;
	this._subHeaderHeight     = 0;
	this._footerHeight        = 0;
	this._padding             = padding * 2 || 10;
	this._bodyHeight          = this._height - this._headerHeight;
	this._child               = null;
	this._childHeader         = null;
	this._childFooter         = null;
	this._isCloseButtonActive = false;
	var self = this;

	this._render = function(){
		this._domObj.className   += " gtk_panel";
		    this._header = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'className': 'gtk_panel_header'});
		        var table = jsgtk.Dom.create({'append': this._header, 'tag': "table", 'style': 'width: 95%; height: 100%;'});
			        var tr = jsgtk.Dom.create({'append': table, 'tag': "tr"});
				        var td = jsgtk.Dom.create({'append': tr, 'tag': "td", 'style': 'vertical-align: middle;'});
					        this._domTitle = jsgtk.Dom.create({"append": td, "tag": "label", "text": this._activeTitle, 'className': 'gtk_none_selectable gtk_panel_header_title'})
                this._closeButton = jsgtk.Dom.create({"append": this._header, "tag": "div", "className": "gtk_panel_close_button", "style": "display:none;"});
                this._minimizeButton = jsgtk.Dom.create({'append': this._header, 'tag': 'div', 'className': 'gtk_panel_minimize_button'});

		    this._header.style.height = this._headerHeight + 'px';

		    this._subHeader = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "className": "gtk_panel_sub_header"});
		    this._subHeader.style.width = this._width - 2 + "px";

		    this._body = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'className': 'gtk_panel_body'});
		    this._body.style.width = this._width - 2 + 'px';
		    this._body.style.height = this._bodyHeight - 3 + 'px';

		    this._footer = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "className": "gtk_panel_footer"});
		    this._footer.style.width = this._width - 2 + "px";

		this._domObj.style.width  = this._width + 'px';
		this._domObj.style.height = this._height + 'px';

		this.hide();
	};

    this._render();

    jsgtk.Event.addDomListener(this._minimizeButton, "mousedown", function(e){
        self.minimize();
    }, false);
};

gtk.Panel.prototype = new gtk.Container();
gtk.Panel.prototype.constructor = gtk.Panel;

gtk.Panel.prototype.hideMinimizeButton = function(){
    this._minimizeButton.style.display = "none";
};

gtk.Panel.prototype.minimize = function(){
    var self = this;
    this._resetTitle(this._getMinimizedTitle(this._title, this._minimizedWidth));
    var minimizePanel = this._getMinimizedPanel();

    jsgtk.Dom.hideElement(this._domObj);

    var id = "gtk_minimized_widget_holder";
    var holder = document.getElementById(id);
    if(!holder) var holder = jsgtk.Dom.create({"append": document.body, "tag": "div", "id": id});
    holder.appendChild(minimizePanel);

    var restoreButton = minimizePanel.childNodes[2];
    jsgtk.Event.addDomListener(restoreButton, "click", function(){
		self.emit('restorepanel', self);

		self._resetTitle(self._activeTitle);
        jsgtk.Dom.showElement(self._domObj);

	    minimizePanel.parentNode.removeChild(minimizePanel);
    });

	var closeButton = minimizePanel.childNodes[1];
	jsgtk.Event.addDomListener(closeButton, "click", function(e){
	    minimizePanel.parentNode.removeChild(minimizePanel);
	    minimizePanel = null;
	    jsgtk.Event.stopBubble(e);
	});

    jsgtk.Event.addDomListener(minimizePanel, "mouseover", function(e){
        self.emit("minimizepanelmouseover", self._title);
        jsgtk.Event.stopBubble(e);
    });
    self.emit('minimizepanel', self);
};

gtk.Panel.prototype.setCloseButton = function(isCloseButtonActive){
	var self = this;
	this._isCloseButtonActive = isCloseButtonActive;

	if(this._isCloseButtonActive) {
	    jsgtk.Dom.showElement(this._closeButton);
		this._minimizeButton.style.right = "22px";
		jsgtk.Event.addDomListener(this._closeButton, "click", function(e){
		    self._domObj.parentNode.removeChild(self._domObj);
		    self._domObj = null;
		    jsgtk.Event.stopBubble(e);
		});
	}
	else {
		if(this._closeButton){
			this._closeButton.style.display = "none";
			this._minimizeButton.style.right = "5px";
		}
	}
};

gtk.Panel.prototype.getTitle = function(){
    return this._title;
};

gtk.Panel.prototype.add = function(widget){
    this._positionChild(widget.getNode());
    this._child = widget;
    var size = this._getChildSize();
    this.resize(size[0] + 2, size[1] + 5);
    this.emit("bubble", size[0], size[1]);
    this._connectChildrenSignal();
};

gtk.Panel.prototype._positionChild = function(childNode){
    this._body.appendChild(childNode);
    childNode.style.left = this._padding / 2 + "px";
    childNode.style.top  = this._padding / 2 + "px";
};

gtk.Panel.prototype.addToHeader = function(widget, height){
    this._subHeader.appendChild(widget._domObj);
    this._childHeader = widget;
    this._subHeaderHeight = height;
    var size = this._getChildSize();
    this.resize(size[0], size[1]);
};

gtk.Panel.prototype.addToFooter = function(widget, height){
    this._footer.appendChild(widget._domObj);
    this._childFooter = widget;
    this._footerHeight = height;
    var size = this._getChildSize();
    this.resize(size[0], size[1]);
};

gtk.Panel.prototype.flushChild = function(){
    this._body.removeChild(this._child._domObj);
    this._child = null;
};

gtk.Panel.prototype._resetTitle = function(title){
    this._domTitle.innerHTML = title;
};

gtk.Panel.prototype.setTitle = function(title, xalign){
    this._title = title;
    var xalign = xalign || 1.0;
    this._domTitle.innerHTML = this._title;
};

gtk.Panel.prototype._connectChildrenSignal = function(){
    var self = this;
    this._child.connect("bubble", function(width, height){
        self.resize(width, height + self._headerHeight);
        self.emit("bubble", width, height + self._headerHeight);
    });
};

gtk.Panel.prototype._getMinimizedPanel = function(){

    var minimizePanel = this._header.cloneNode(true);
	minimizePanel.className = "gtk_panel_minimize";
    minimizePanel.removeAttribute("style");
    minimizePanel.style.width = this._minimizedWidth + "px";
    return minimizePanel;
};

gtk.Panel.prototype._getMinimizedTitle = function(title, minimizedWidth){
    var tmpNode = jsgtk.Dom.create({"append": document.body, "tag": "span"});
    tmpNode.innerHTML = title;

    var titleWidth = jsgtk.Util.fullWidth(tmpNode);
    if( titleWidth < minimizedWidth){
        return this._title;
    }

    var charWidth = 0;
    var title = this._title.replace(/\s+/g,'`');

    for(var i = 0, len = title.length; i < len; i++){
        var char = title.substring(i, i+1);
        tmpNode.innerHTML = char;
        charWidth += jsgtk.Util.fullWidth(tmpNode);
        if(charWidth >= minimizedWidth){
            break;
        }
    }

    var minimizedTitle = this._isCloseButtonActive ? title.substring(0, i - 8) : title.substring(0, i - 5);
    return minimizedTitle.split("`").join(" ") + "...";
};

gtk.Panel.prototype._getChildSize = function(){

    var width = this.getMinWidthComposite();

    var height = this._child ? this._child.getMinHeightComposite() + this._padding : this._bodyHeight;
    var subElementsHeight = this._getSubElementsHeight();
    var bodyHeight = this._minHeight - subElementsHeight;
    height     = height < bodyHeight ? bodyHeight : height;

    return [width, height + subElementsHeight];
};

gtk.Panel.prototype._getSubElementsHeight = function(){
    return this._headerHeight + this._subHeaderHeight + this._footerHeight;
};

gtk.Panel.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);

    this._activeTitle = this._getMinimizedTitle(this._title, this._width);
    this._resetTitle(this._activeTitle);

    if(this._child) this._child.resizeWidthComposite(this._width - this._padding - 1);
    if(this._child) this._child.resizeHeightComposite(this.getBodyHeight() - this._padding - 3);
    if(this._childHeader){
        this._childHeader.resizeWidthComposite(this._width - 2);
        this._childHeader.resizeHeightComposite(this._subHeaderHeight - 2);
    }
    if(this._childFooter){
        this._childFooter.resizeWidthComposite(this._width - 2);
        this._childFooter.resizeHeightComposite(this._footerHeight - 1);
    }
};

gtk.Panel.prototype._resizeWidth = function(width){
	this._width = width;
	this._domObj.style.width    = this._width - 1 + 'px';
	this._body.style.width      = this._width - 3 + 'px';
	this._footer.style.width    = this._width - 1 + 'px';
	this._subHeader.style.width = this._width - 1 + "px";
};

gtk.Panel.prototype._resizeHeight = function(height){
	this._height = height;
	this._bodyHeight = this._height - this._getSubElementsHeight();
	this._domObj.style.height    = this._height - 2 + 'px';
	this._body.style.height      = this._bodyHeight - 3 + 'PX';
	this._footer.style.height    = this._footerHeight + "px";
	this._subHeader.style.height = this._subHeaderHeight - 1 + "px";
};

gtk.Panel.prototype.getBodyHeight = function(){
    return this._bodyHeight;
}

gtk.Panel.prototype.getMinWidthComposite = function(){

    var headerWidth = this._childHeader ? this._childHeader.getMinWidthComposite() : this._minWidth;
    var width       = headerWidth < this._minWidth ? this._minWidth : headerWidth;

    var bodyWidth   = this._child ? this._child.getMinWidthComposite() + this._padding + 3 : this._minWidth;
    width           = width < bodyWidth ? bodyWidth : width;

    var footerWidth = this._childFooter ? this._childFooter.getMinWidthComposite() : this._minWidth;
    width           = width < footerWidth ? footerWidth : width;

    return width;
};

gtk.Panel.prototype.getMinHeightComposite = function(){
    var childHeight = ( this._child ? this._child.getMinHeightComposite() : this._bodyHeight) + this._getSubElementsHeight();
    var minHeight = this._minHeight > childHeight ? this._minHeight : childHeight;
    return minHeight + 5;
};

gtk.Panel.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this.resize(minWidth, this._height);
};

gtk.Panel.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
	this.resize(this._width, minHeight);
};
gobject.signalNew('minimizepanel', gtk.Panel, [], null, null);
gobject.signalNew('minimizepanelmouseover', gtk.Panel, [], null, null);
gobject.signalNew('restorepanel', gtk.Panel, [], null, null);
/**
* A tabbed notebook container
*/
gtk.NoteBook = function() {

	gtk.Container.apply(this);
	var self = this;

	/* constructor arguments as private variables */
	this._minWidth = 200;
	this._minHeight = 200;
	this._width = this._minWidth;
	this._height = this._minHeight;
	this._tabHeight = 32;
    this._hBarHeight = 3;
    this._extraWidthRight = 10;
    this._border = 2;
    this._vspaceWidth = 2;

	this._tabs = new gtk.Tabs(this._width, this._tabHeight, this._vspaceWidth);
	this._tabs.show();
    var contentsHeight = this._height - this._tabHeight - this._hBarHeight - 1;
	this._contents = new gtk.Contents(this._width, contentsHeight);
	this._contents.show();

	this._render = function(){
		this._domObj.className += " gtk_notebook";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		    var hBar = jsgtk.Dom.create({'tag' : 'div', 'className': 'gtk_hbar'});
		    hBar.style.height = this._hBarHeight + 'px';
		this._appendChild(this._contents, this._tabs, hBar);
		this.hide();
	};

	this._tabs.connect('active', function(label){
		var content = self._contents.activateContent(label.id);
		self.emit("tabactivated", label.getText(), content);
	});

	this._render();
};

gtk.NoteBook.prototype = new gtk.Container();
gtk.NoteBook.prototype.constructor = gtk.NoteBook;

/**
*	Appends pages to the notebook using the widget specified by child and the widget specified by tab_label as the label on the tab.
*	@param {object} pages - array: [{child, labels}, ... ]
*/
gtk.NoteBook.prototype.appendPages = function(pages){
	var children = [], labels = [];
	for(var i = 0, len = pages.length; i < len; i++){
		var page = pages[i];
		var uuid = new UUID();
		page.child.id = uuid;
		page.label.id = uuid;
		labels.push(page.label);
		children.push(page.child);
	}
	this._contents.addChildren(children);
	this._tabs.addTabs(labels);
	var size = this._getMaxSize();
	this.resize(size[0], size[1]);



	this._tabs.activateDefault();
	this._contents.activateDefault();
};

/**
*	Appends a page to the notebook using the widget specified by child and the widget specified by tab_label as the label on the tab.
*	@param {object} child - widget as the contents of the page.
*	@param {object} label - widget as the label for the page.
*	@return {integer} index - index number of the page in the notebook
*/
gtk.NoteBook.prototype.appendPage = function(child, label){
	var uuid = new UUID();
	this._contents.addChild(child, uuid);
	this._tabs.addTab(label, uuid);
	var size = this._getMaxSize();
	this.resize(size[0], size[1]);



	this._tabs.activateDefault();
	this._contents.activateDefault();

	child.show();
	label.show();
};

gtk.NoteBook.prototype._connectChildrenSignal = function(){
	var self = this;
	this._tabs.connect("bubble", function(width, height){
    	self.resize();
    	self.setSize( parseInt(self._domObj.style.width), parseInt(self._domObj.style.height) );
    });
    this._contents.connect("bubble", function(width, height){
    	self.resize();
    	self.setSize( parseInt(self._domObj.style.width), parseInt(self._domObj.style.height) );
    });
};

gtk.NoteBook.prototype._appendChild = function(contents, tabs, hBar){
	this._domObj.appendChild(tabs._domObj);
	this._domObj.appendChild(hBar);
	this._domObj.appendChild(contents._domObj);
};

gtk.NoteBook.prototype._getMaxSize = function(){
	var maxWidth = this._width, maxHeight = this._height;
	var tabsSize = this._tabs.getSize();
	var contentsSize = this._contents.getSize();
	if(tabsSize[0] > maxWidth) maxWidth = tabsSize[0];
	if(contentsSize[0] > maxWidth) maxWidth = contentsSize[0];
	if( (contentsSize[1] + tabsSize[1]) > maxHeight) maxHeight = contentsSize[1] + tabsSize[1];
	return [maxWidth + this._extraWidthRight - 1, maxHeight + 2];
};

gtk.NoteBook.prototype._resizeHeight = function(height){
    this._domObj.style.height = height - this._border + 'px';
	this._height = height;
};

gtk.NoteBook.prototype._resizeWidth = function(width){
	this._domObj.style.width = width - this._border + 'px';
	this._width = width;
};

gtk.NoteBook.prototype.resize = function(width, height){
	this._resizeWidth(width);
	this._resizeHeight(height);

	var tabsSize = this._tabs.getSize();

	this._tabs.resize(this._width - 1, tabsSize[1]);
	this._contents.resize(this._width - 2, this._height - tabsSize[1] - 5);
};


gtk.NoteBook.prototype.getMinWidthComposite = function(){
	var minWidth = this._minWidth;

	var tabsWidth = this._tabs.getMinWidthComposite();
	var contentsWidth = this._contents.getMinWidthComposite();

	if(tabsWidth > minWidth) minWidth = tabsWidth;
	if(contentsWidth > minWidth) minWidth = contentsWidth;

	return minWidth + this._extraWidthRight +1;
};

gtk.NoteBook.prototype.getMinHeightComposite = function(){
	var minHeight = this._minHeight - this._tabs.getHeight();
	var contentsHeight = this._contents.getMinHeightComposite();

	if(contentsHeight > minHeight) minHeight = contentsHeight;

	return minHeight + this._tabs.getHeight();
};

gtk.NoteBook.prototype.resetWidthComposite = function(){

	var minSize = this.getSizeRequest();
	this.setWidth(minSize[0]);

	this._tabs.resetWidthComposite();
	this._contents.resetWidthComposite();
};

gtk.NoteBook.prototype.resetHeightComposite = function(){

	var minSize = this.getSizeRequest();
	this.setHeight(minSize[1]);

	this._contents.resetHeightComposite();
};

gtk.NoteBook.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this._contents.resizeHeightComposite(minHeight - this._tabs.getHeight());

	this.resize(this._width, minHeight);
};

gtk.NoteBook.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	this._tabs.resizeWidthComposite(minWidth);
	this._contents.resizeWidthComposite(minWidth - this._border);

	this.resize(minWidth, this._height);
};

gobject.signalNew('tabactivated', gtk.NoteBook, [], null, null);
gtk.Tabs = function(width, height, vspaceWidth) {

	gtk.Container.apply(this);
	this._children = [];
	this._width = width;
	this._height = height;
	this._vspaceWidth = vspaceWidth;
	this._render = function(){
		this._domObj.className += " gtk_tabs";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this.hide();
	};
	this.connect('active', function(label){
		this.activateTab(label.id);
	});

	this._render();
};

gtk.Tabs.prototype = new gtk.Container();
gtk.Tabs.prototype.constructor = gtk.Tabs;

gtk.Tabs.prototype.activateDefault = function(){
	this._children[0]._domObj.parentNode.parentNode.style.backgroundColor = "#fff";
	this._children[0]._domObj.parentNode.style.borderBottom = "0px";
};

gtk.Tabs.prototype.activateTab = function(id){
	for(var i = 0, len = this._children.length; i < len; i++){
		var label = this._children[i];
		if(label.id != id) {
			label._domObj.parentNode.parentNode.style.backgroundColor = "";
			label._domObj.parentNode.style.borderBottom = "";
		}
	};
};

gtk.Tabs.prototype.addTabs = function(labels){
	for(var i = 0; i < labels.length; i++){
		var label = labels[i];
		this._children.push(label);
		this._appendPage(label);
	}

	var size = this._getMaxSize();
	var width = this._width > size[0] + 10 ? this._width : size[0] + 10;
	this.resize(width, this._height);

};


gtk.Tabs.prototype.addTab = function(label, uuid){
	label.id = uuid;
	this._children.push(label);
	this._appendPage(label);

	var size = this._getMaxSize();
	var width = this._width > size[0] + 10 ? this._width : size[0] +10;
	var tabsBorderWidth = this._children.length * 2;
	this.resize(width, this._height);

};

gtk.Tabs.prototype._appendPage = function(label){
	var self = this;
	var size = label.getSize();
	var page = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'class': 'gtk_page'});
	page.style.width = size[0] + 2 + 'px';
	page.style.height = size[1] + 10 + 'px';
	page.style.top = 4 + 'px';
		var wrapper = jsgtk.Dom.create({'append': page, 'tag': 'div', 'class': 'gtk_tabs_wrapper'});
		wrapper.style.width = size[0] + 2 + 'px';
		wrapper.style.height = size[1] + 9 + 'px';

	wrapper.appendChild(label._domObj);

	jsgtk.Event.addDomListener(page, 'mousedown', function(){
		page.style.backgroundColor = "#fff";
		wrapper.style.borderBottom = "0px";
		self.emit('active', label);
	});
	var vspace = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'class': 'gtk_vspace'});
	vspace.style.width = this._vspaceWidth + "px";
	vspace.style.height = "100%";
};

gtk.Tabs.prototype._getMaxSize = function(){
	var totalWidth = 0, height;
	for(var i = 0, len = this._children.length; i < len; i++){
		var size = this._children[i].getSize();
		totalWidth += size[0];
		height = size[1];
	}
	var extraWidth = this._children.length * (2 + this._vspaceWidth) ;
	return [totalWidth + extraWidth, height];
};

gtk.Tabs.prototype._resizeContainer = function(width, height){
	if(width > this._width){
		this._domObj.style.width = width + 'px';
		this._width = width;
	}
	this._domObj.style.height = height + 'px';
	this._height = height;
};

gtk.Tabs.prototype.resize = function(width, height){
	this._resizeWidth(width);
	this._resizeHeight(height);
};


gtk.Tabs.prototype.getMinWidthComposite = function(){
	var tabs = this._children;
	if(tabs.length > 0){
		var minWidth = 0;
		for(var i = tabs.length; i--;){
			minWidth += tabs[i].getWidth() + 2;
		}
		var extraWidth = this._children.length * (2 + this._vspaceWidth) ;
		this._minWidth = minWidth + extraWidth;
		return this._minWidth - 2;
	}
	return this._minWidth - 2;
};

/**
* resetHeightComposite() composite method : reset the current height of vbox and all the composite _children
*											to the original minHeight
*/
gtk.Tabs.prototype.resetWidthComposite = function(){

	var minSize = this.getSizeRequest();
	this.setWidth(minSize[0]);

	var tabs = this._children;
	for(var i = tabs.length; i--;){
		tabs[i].resetWidthComposite();
	}
};

gtk.Tabs.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;

	this.resize(minWidth, this._height);
};

gobject.signalNew('active', gtk.Tabs, [], null, null);
gtk.Contents = function(width, height) {

	gtk.Container.apply(this);
	this._width = width;
	this._height = height;
	this._children = []
	this._render = function(){
		this._domObj.className += " gtk_contents";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this.hide();
	};

	this._render();
};

gtk.Contents.prototype = new gtk.Container();
gtk.Contents.prototype.constructor = gtk.Contents;

gtk.Contents.prototype.activateDefault = function(){
	this._domObj.appendChild(this._children[0]._domObj);
};

gtk.Contents.prototype.activateContent = function(id){
	var content
	for(var i = 0, len = this._children.length; i < len; i++){
		content = this._children[i];
		if(id === content.id) break;
	}
	this._domObj.innerHTML = "";
	this._domObj.appendChild(content._domObj);
	return content;
};

gtk.Contents.prototype.addChildren = function(children, uuid){
	for(var i = 0; i < children.length; i++){
		var child = children[i];
		this._children.push(child);
	}
	var size = this._getMaxSize();
	this.resize(size[0] + 5, size[1]);


};


gtk.Contents.prototype.addChild = function(child, uuid){
	child.id = uuid;
	this._children.push(child);

	var size = this._getMaxSize();
	this.resize(size[0], size[1]);


};

gtk.Contents.prototype._connectChildrenSignal = function(){
    var children = this._children, len = children.length;
    var self = this;
    for(var i = 0; i < len; i++){
        children[i].connect("bubble", function(width, height){
        	self.resize();
        	self.setSize( parseInt(self._domObj.style.width), parseInt(self._domObj.style.height) );
        });
    }
};

gtk.Contents.prototype.resize = function(width, height){
	this._resizeWidth(width);
	this._resizeHeight(height);

    for(var i = this._children.length; i--;){
        this._children[i].resizeWidthComposite(this._width);
        this._children[i].resizeHeightComposite(this._height);
    }
};

gtk.Contents.prototype._getMaxSize = function() {
	var maxWidth = this._width, maxHeight = this._height;
	for(var i = 0, len = this._children.length; i < len; i++){
		var box = this._children[i];
		var size = box.getSize();
		if(size[0] > maxWidth) maxWidth = size[0];
		if(size[1] > maxHeight) maxHeight = size[1];
	}
	return [maxWidth, maxHeight];
};


gtk.Contents.prototype.getMinWidthComposite = function(){
	var children = this._children;
	if(children.length > 0){
		var minWidth = this._minWidth;

		for(var i = children.length; i--;){
			var width = children[i].getMinWidthComposite();
			if( width > minWidth & width != undefined) minWidth = width;
		}

		this._minWidth = minWidth;
		return this._minWidth;
	}
	return this._minWidth;
};

gtk.Contents.prototype.getMinHeightComposite = function(){
	var children = this._children;
	if(children.length > 0){
		var minHeight = this._minHeight;
		for(var i = children.length; i--;){
			var height = children[i].getMinHeightComposite();
			if( height > minHeight & height != undefined) minHeight = height;
		}

		this._minHeight = minHeight;
		return this._minHeight;
	}
	return this._minHeight;
};

/**
* resetHeightComposite() composite method : reset the current height of vbox and all the composite children
*											to the original minHeight
*/
gtk.Contents.prototype.resetWidthComposite = function(){

	var minSize = this.getSizeRequest();
	this.setWidth(minSize[0]);

	var children = this._children;
	for(var i = children.length; i--;){
		children[i].resetWidthComposite();
	}
};

/**
* resetHeightComposite() composite method : reset the current height of vbox and all the composite children
*											to the original minHeight
*/
gtk.Contents.prototype.resetHeightComposite = function(){

	var minSize = this.getSizeRequest();
	this.setHeight(minSize[1]);

	var children = this._children;
	for(var i = children.length; i--;){
		children[i].resetHeightComposite();
	}
};

gtk.Contents.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this.resize(minWidth, this._height);
};

gtk.Contents.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
	this.resize(this._width, minHeight);
};
gtk.Combo = function(model, rows){
	gtk.Bin.apply(this);
    var self = this;
    this._imgSrc = pango.Path.getRootPath().split("javascript")[0];
	this._vBarWidth = 25;
    this._dropDownContainer = null;
    this._cells = [];
    this._cell;
    this._child = null;
    this._hiddenEntry = null;
    this._width = this._minWidth = 20 + this._vBarWidth;;
	this._height = this._minHeight = 20;
	this._isToogled = false;
	this._isDropDownCreated = false;
	this._cellIndex = -1;
	this._hilightedCell = null;
	this._activeText = "";
	this._model = model;

	this._render = function(){
	    this._domObj.className += " gtk_combo";
	    this._className = this._domObj.className;
	    this._dropDownContainer = jsgtk.Dom.create({"tag": 'div', 'className': 'gtk_combobox_dropdown'});
	};

	this._render();

	jsgtk.Event.addDomListener(this._domObj, 'click', function(e){
	    if(!self._isToogled) {
	        self._activate();
        	if(!self._isDropDownCreated){
        	    var docFragment = document.createDocumentFragment();
        	    self.emit('rendercells', self._col, self._width, docFragment);
        	}
        	else jsgtk.Dom.showElement(self._dropDownContainer);

        	if(self._hiddenEntry) self._hiddenEntry.focus();
	    }else{
	        self._deActivate();
        	jsgtk.Dom.hideElement(self._dropDownContainer);

        	if(self._hiddenEntry) self._hiddenEntry.blur();
	    }
	    jsgtk.Event.stopBubble(e);
	}, false);

	jsgtk.Event.addDomListener(this._dropDownContainer, 'click', function(e){
	    jsgtk.Event.stopBubble(e);
	}, false);
};

gtk.Combo.prototype = new gtk.Bin();
gtk.Combo.prototype.constructor = gtk.Combo;

/**
 * Pack the cell into ComboBox
 * @param {gtk.CellRendererText} cell A cell renderer text to be display in ComboBox
 * @param {Boolean} expand The setting of expand, either True or False
 */
gtk.Combo.prototype.packStart = function(cell, expand){
	this._expand = (expand === undefined) ? true : expand;
	this._cellRender = this._cellRender ? this._cellRender : cell;
};

/**
 * Add attribute to ComboBox
 * @param {gtk.CellRendererText} cell A cell renderertext
 * @param {String} attribute A gobject constaints
 * @param {Integer} column The number of column in comboBox
 */

gtk.Combo.prototype.addAttribute = function(cell, attribute, column){
	this._cellRender = this._cellRender ? this._cellRender : cell;
	this._attr = attribute || "";
	this._col = (column === undefined) ? null : column;
};

/**
 * Returns the currently active string or None if no entry is selected
 * @return The currently active text
 */
gtk.Combo.prototype.getActiveText = function(){
    return this._activeText;
};

gtk.Combo.prototype._scrollToHilightedRow = function(positionFromTop){
    this._dropDownContainer.scrollTop = positionFromTop * 20;
};

gtk.Combo.prototype.displayComboText = function(text){
    this._activeText = text;
    this._child.setText(text);
};

gtk.Combo.prototype.setModel = function(model){
    this._model = model;
    this._controller.setModel(this._model);
    var docFragment = document.createDocumentFragment();
    this.emit('rendercells', this._col, this._width, docFragment);
    jsgtk.Dom.hideElement(this._dropDownContainer);
};

gtk.Combo.prototype.renderDropDownContainer = function(width, height, rowHeight){
    var dHeight = rowHeight * this._rows;
    var height = dHeight > height ? height : dHeight;
    this._dropDownContainer.style.width = width + 'px';
    this._dropDownContainer.style.height = height + 'px';
    this._dropDownContainer.style.position = "relative";
    this._dropDownContainer.style.top = "101%";
    this._domObj.appendChild(this._dropDownContainer);
};

gtk.Combo.prototype.appendRows = function(docFragment){
    this._dropDownContainer.appendChild(docFragment);
};

gtk.Combo.prototype.renderRows = function(iter, cols, sibbling, margin, width, height, docFragment){
    var row = jsgtk.Dom.create({'tag': 'div', 'id': iter.path});
	row.style.height = height + 'px';
	row.style.width = width + 'px';
	row.style.cursor = 'pointer';
	docFragment.appendChild(row);

	this.renderCell(row, iter, 0, 0, null, width, height);
	this._isDropDownCreated = true;
};

gtk.Combo.prototype.renderCell = function(row, iter, margin, imgWidth, imgObj, width, height){

    var self = this;

	var path = iter.path;

	this._cell = new gtk.CellRendererText(width - 5, 0, 'gtk_combo_cell');
	this._cell.render(row, iter.getRow()[0], margin, imgWidth, imgObj, width, height);

	var cell = this._getCellByPath(path);

	if(cell) cell.run(path, this._cell);
	else{
		this._cell.setPath(path);
		this.add(this._cell);
	}
	this._cell.connect('cellselected', function(text){
	    self._activeText = text;
	    self._child.setText(text);
	    self._domObj.className = self._className;
    	self._isToogled = false;
    	jsgtk.Dom.hideElement(self._dropDownContainer);
    	self.emit("changed", text);
	});

	this._cell.connect("cellhilighted", function(){
	    self._cellIndex = self.getIndex(this);
	    if(self._hilightedCell) self._deHilightCell(self._hilightedCell);
	    self._hilightedCell = this;
	    self._hilightCell(this);
	});

	this._cell._domObj.style.marginLeft = '2px';

	this._cell.activateHilight();

	return this._cell.getOffsetWidth();
};

gtk.Combo.prototype.add = function(cell){
	this._cells.push(cell);
};

gtk.Combo.prototype.getIndex = function(cell){
    for(var i = 0, len = this._cells.length; i < len; i++){
        if(cell === this._cells[i]) return i;
    }
};

gtk.Combo.prototype.getCell = function(index){
    return this._cells[index];
};

gtk.Combo.prototype.setActive = function(i){
    var text = this._model.children[i]? this._model.children[i].row[0] : "";
    this.emit("loadcontent", text);
}

gtk.Combo.prototype._deHilightCell = function(cell){
    var node = cell.getNode();
    node.style.backgroundColor    = "";
    node.style.border             = "";
    node.style.MozBorderRadius    = "";
    node.style.WebkitBorderRadius = "";
};

gtk.Combo.prototype._hilightCell = function(cell){
    var node = cell.getNode();
    node.style.backgroundColor    = "#FFF9D6";
    node.style.border             = "solid 1px #EFC169";
    node.style.MozBorderRadius    = "2px";
    node.style.WebkitBorderRadius = "2px";
};

gtk.Combo.prototype._getCellByPath = function(path){
	var cellPath = path.split(':');
	var cells = this._cells;
	for( var i = cells.length; i--;){
		if(cells[i].getPath() === cellPath[0] + ':') return cells[i];
	}
	return null;
};

gtk.Combo.prototype._activate = function(){
    this._domObj.className = this._className + " gtk_combo_active";
	this._isToogled = true;
};

gtk.Combo.prototype._deActivate = function(){
    this._domObj.className = this._className;
	this._isToogled = false;
};

gobject.signalNew("clicked", gtk.Combo, null, null, []);
gobject.signalNew("loadcontent", gtk.Combo, null, null, []);
gobject.signalNew('rendercells', gtk.Combo, [], null, null);
gobject.signalNew("searchcontent", gtk.Combo, null, null, []);
gobject.signalNew("changed", gtk.Combo, null, null, []);
/**
 * A widget used to choose from a list of items
 * @constructor
 * @param {gtk.TreeModel} model A valid gtk.TreeModel
 * @param {Integer} Integer used to specify the row of comboBox
 */

gtk.ComboBox = function(model, rows){
	gtk.Combo.apply(this);
	var self = this;

    this._model = model || null;
    this._rows = rows;

    this._child = new gtk.Label();
	this._child.show();
	this._child.setSelectable(false);

	this._render = function(){
	    this._domObj.className += " gtk_combobox";
	    this._domObj.style.display = "table";
	    this._domObj.style.position = "relative";

	        this._hiddenEntry = jsgtk.Dom.create({"append": this._domObj, "tag": "input", "type": "text", "className": "gtk_combobox_entry_hidden"});

	        var gradient = jsgtk.Dom.create({'append': this._domObj, "tag": 'div', 'class': 'gtk_button_gradient'});
	        gradient.style.height = this._height / 2 + 'px';
		    this._labelDom = jsgtk.Dom.create({"tag": "div", 'class': 'gtk_combo_widget'});
		    this._labelDom.style.width = this._width - this._vBarWidth + 'px';

		    var vBar = jsgtk.Dom.create({'append': this._domObj, "tag": "div", 'class': 'gtk_vbar'});
            vBar.style.right = this._vBarWidth + 'px';

            var arrowImge = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div','class': 'gtk_arrow_imge'});
            arrowImge.style.width = this._vBarWidth + 'px';
    			var table = jsgtk.Dom.create({append: arrowImge, tag: "table", style: 'width: 100%; height: 100%;'});
	    			var tr = jsgtk.Dom.create({append: table, tag: "tr"});
	    				var td = jsgtk.Dom.create({append: tr, tag: "td", style: 'vertical-align: middle; text-align: center;'});
	    					jsgtk.Dom.create({append: td, tag: "img", src: this._imgSrc + "images/icons/16x16/combo_arrow_down.png"});

		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + "px";
	};

	this._render();

	this._controller = new gtk.ComboBoxController(this, model);

	this.emit('loadcontent');

	this.setLabel(this._child);

	jsgtk.Event.addDomListener(this._hiddenEntry, 'blur', function(e){

        setTimeout(function(){
      	    self._deActivate();
    	    jsgtk.Dom.hideElement(self._dropDownContainer);
        }, 200);

	    jsgtk.Event.stopBubble(e);
	}, false);

	jsgtk.Event.addDomListener(this._hiddenEntry, "keypress", function(e){
	    if(e.keyCode === 38){
	        if(self._cellIndex >= 1){
	            self._cellIndex -= 1;

	            self._scrollToHilightedRow(self._cellIndex);

	            var cell = self.getCell(self._cellIndex);
	            if(!cell) return;
                if(self._hilightedCell) self._deHilightCell(self._hilightedCell);
                self._hilightedCell = cell;
                self._hilightCell(cell);
	        }
	    }
	    if(e.keyCode === 40){
	        if(self._cellIndex < self._cells.length){

	            self._cellIndex += 1;

	            self._scrollToHilightedRow(self._cellIndex);

	            var cell = self.getCell(self._cellIndex);
	            if(!cell) return;
                if(self._hilightedCell) self._deHilightCell(self._hilightedCell);
                self._hilightedCell = cell;
                self._hilightCell(cell);
	        }
	    }

	    if(e.keyCode === 13){
            var cell = self._hilightedCell;
	        jsgtk.Dom.hideElement(self._dropDownContainer);
            if(self._child && cell){
                self._child.setText(cell.getText());
    	        self.emit("changed", cell.getText());
            }
            self._deActivate();
	    }

        jsgtk.Event.stopBubble(e);
	}, false);
};

gtk.ComboBox.prototype = new gtk.Combo();
gtk.ComboBox.prototype.constructor = gtk.ComboBox;

gtk.ComboBox.prototype.setLabel = function(label){
    this.resize(this._width, this._height);
    this._labelDom.appendChild(this._child._domObj);
    this._domObj.appendChild(this._labelDom);
};

gtk.ComboBox.prototype._positionWidget = function(widget, widgetDom){
    var top = (this._height / 2) - (widget.getHeight() / 2);
    widgetDom.style.top = top - 2 + 'px';
    widgetDom.style.left = 5 + 'px';
};

gtk.ComboBox.prototype.resize = function(width, height){

    this._resizeWidth(width);
    this._resizeHeight(height);

    if(this._child) this._positionWidget(this._child, this._labelDom);
};

gtk.ComboBox.prototype._resizeHeight = function(height){
	this._domObj.style.height = height - 2 + 'px';
	this._domObj.childNodes[1].style.height = height / 2 + 'px';
	this._height = height;
};

gtk.ComboBox.prototype._resizeWidth = function(width){
	this._domObj.style.width = width - 2 + 'px';
	this._labelDom.style.width = width - this._vBarWidth - 9 + 'px';
	this._width = width;
};

gtk.ComboBox.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);
};

gtk.ComboBox.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);
};

gtk.ComboBoxEntry = function(model, rows){
	gtk.Combo.apply(this);

	var self = this;

    this._model = model || null;
    this._rows = rows;

	this._child = new gtk.Entry();
	this._child.show();
	this._child.setBorderVisible(false);
	this._childDomInput = this._child._dom;

	this._width = this._minWidth = this._child.getMinWidthComposite() + this._vBarWidth;
	this._height = this._minHeight = this._child.getMinHeightComposite();

	this._render = function(){
	    this._domObj.className += " gtk_combobox_entry";
	    this._domObj.style.position = "relative";
	        var gradient = jsgtk.Dom.create({'append': this._domObj, "tag": 'div', 'class': 'gtk_button_gradient'});

		    this._entryDom = jsgtk.Dom.create({'append': this._domObj, 'class': 'gtk_combo_widget','tag': 'div'});
		    this._entryDom.appendChild(this._child._domObj);

		    var vBar = jsgtk.Dom.create({'append': this._domObj, "tag": "div", 'class': 'gtk_vbar'});
            vBar.style.right = this._vBarWidth + 'px';

            var arrowImge = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', 'class': 'gtk_arrow_imge'});
            arrowImge.style.width = this._vBarWidth + 'px';
    			var table = jsgtk.Dom.create({append: arrowImge, tag: "table", style: 'width: 100%; height: 100%;'});
	    			var tr = jsgtk.Dom.create({append: table, tag: "tr"});
	    				var td = jsgtk.Dom.create({append: tr, tag: "td", style: 'vertical-align: middle; text-align: center;'});
	    					jsgtk.Dom.create({append: td, tag: "img", src: this._imgSrc + "images/icons/16x16/combo_arrow_down.png"});

		this._domObj.style.width = this._width + 1 + 'px';
		this._domObj.style.height = this._height + "px";
	};

	this._render();

    this._controller = new gtk.ComboBoxController(this, model);

	this.emit('loadcontent');

	jsgtk.Event.addDomListener(this._childDomInput, 'blur', function(e){
  	    self._deActivate();
	    jsgtk.Dom.hideElement(self._dropDownContainer);
	    jsgtk.Event.stopBubble(e);
	}, false);

	this._child.connect('enterkeypressed', function(){
        var cell = self._hilightedCell;
        self._child.setText(cell.getText());
        self._deActivate();
	    jsgtk.Dom.hideElement(self._dropDownContainer);
	    self.emit("changed", cell.getText());
	});

	jsgtk.Event.addDomListener(this._childDomInput, "keypress", function(e){
	    if(e.keyCode === 38){
	        if(self._cellIndex >= 1){
	            self._cellIndex -= 1;
	            self._scrollToHilightedRow(self._cellIndex);
	            var cell = self.getCell(self._cellIndex);
	            if(!cell) return;
                if(self._hilightedCell) self._deHilightCell(self._hilightedCell);
                self._hilightedCell = cell;
                self._hilightCell(cell);

                self._child.setText(cell.getText());

                jsgtk.Dom.showElement(self._dropDownContainer);
	        }
	        return;
	    }
	    if(e.keyCode === 40){
	        if(self._cellIndex < self._cells.length){
	            self._cellIndex += 1;
	            self._scrollToHilightedRow(self._cellIndex);
	            var cell = self.getCell(self._cellIndex);
	            if(!cell) return;
                if(self._hilightedCell) self._deHilightCell(self._hilightedCell);
                self._hilightedCell = cell;
                self._hilightCell(cell);

                self._child.setText(cell.getText());

                jsgtk.Dom.showElement(self._dropDownContainer);
	        }
	        return;
	    }

        self._activate();
        jsgtk.Dom.showElement(self._dropDownContainer);
	    if(this.value)self.emit("searchcontent", this.value);

        jsgtk.Event.stopBubble(e);
	}, false);
};

gtk.ComboBoxEntry.prototype = new gtk.Combo();
gtk.ComboBoxEntry.prototype.constructor = gtk.ComboBoxEntry;

gtk.ComboBoxEntry.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
};

gtk.ComboBoxEntry.prototype.hilightRow = function(id){
    var row = this._dropDownContainer.childNodes;
    var cell = this._getCellByPath(id);
    var positionFromTop = 0;
    var target;
    for(var i = row.length; i--;){
        if(row[i].id === id){
            target = row[i];
            positionFromTop = i;
            break;
        }else{
            target = row[0];
        }
    }

    if(this._hilightedCell) this._deHilightCell(this._hilightedCell);
    this._hilightedCell = cell;
    this._cellIndex = positionFromTop;
    this._hilightCell(cell);

    target.parentNode.hasAnHilightedChild = true;

    this._scrollToHilightedRow(positionFromTop);
};

gtk.ComboBoxEntry.prototype._getCellByPath = function(path){
    var cell = null;
    for(var i = this._cells.length; i--;){
        if(this._cells[i].getPath() === path){
            cell = this._cells[i];
            break;
        }
    }
    return cell;
};

gtk.ComboBoxEntry.prototype.resizeWidthComposite = function(width){
    var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
    this.resize(minWidth, this._height);
    this._child.resizeWidthComposite(width - this._vBarWidth - 1);
};

gtk.ComboBoxEntry.prototype.resizeHeightComposite = function(height){
    var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
    this.resize(this._width, minHeight);
    this._child.resizeHeightComposite(minHeight);
};
/**
 * Adds scrollbars to its child widget. A class inherite from gtk.Bin
 * @constructor
 */

gtk.ScrolledWindow = function() {

	gtk.Bin.apply(this);
	var self = this;
	this._width  = this._minWidth = 100;
	this._height = this._minHeight = 100;
	this._vAdjustmentLower;
	this._hAdjustmentLower;
	this._vScrolledBar = null;
	this._child = null;

	this._render = function(){
        this._domObj.className   += " gtk_scrolled_window";
        this._domObj.style.width  = this._width + "px";
        this._domObj.style.height = this._height + "px";
            this._scrolledDom = jsgtk.Dom.create({'append': this._domObj, 'tag': 'div', "class": "gtk_scrolled_window_dom"});
            this._scrolledDom.style.width  = this._width + "px";
            this._scrolledDom.style.height = this._height + "px";
                this._widgetDomObj = jsgtk.Dom.create({'append': this._scrolledDom, 'tag': 'div'});
                this._widgetDomObj.style.width  = this._width + 'px';
                this._widgetDomObj.style.height = this._height + 'px';
        this.hide();
	}
	this._render();

	this.addScrolledEvent();

};

gtk.ScrolledWindow.prototype = new gtk.Bin();
gtk.ScrolledWindow.prototype.constructor = gtk.ScrolledWindow;

/**
 * Overide the parent method
 */
gtk.ScrolledWindow.prototype.add = function(widget){
    var self = this;
	if(!this._child){
		this._child = widget;
		this._widgetDomObj.appendChild(widget._domObj);

		var vadjustmentLower = this._child.getVadjustment().getLower();
		var hadjustmentLower = this._child.getHadjustment().getLower();

		this._resizeWidget(hadjustmentLower, vadjustmentLower);

		this.emit("add");

		this._child.getVadjustment().connect('changed', function(lower, upper){
            self._resizeWidget(null, lower);
        });

		this._child.getHadjustment().connect('changed', function(lower, upper){
            self._resizeWidget(lower, null);
        });

	}else{
	}
};

gtk.ScrolledWindow.prototype.removeScrolledEvent = function(){
    jsgtk.Event.removeListener(this._onScroll);
};

gtk.ScrolledWindow.prototype.addScrolledEvent = function(){
    var self = this;
	this._onScroll = jsgtk.Event.addDomListener(this._scrolledDom, "scroll", function(){
	    if(self._vScrolledBar) self._vScrolledBar.moveSlider(this.scrollTop);
	});
};

gtk.ScrolledWindow.prototype.setVscrolledBar = function(vScrolledbar){
    this._vScrolledBar = vScrolledbar;
    var scrolledNode = vScrolledbar.getNode();
    this._domObj.appendChild(scrolledNode);
    scrolledNode.style.top = "0px";
    scrolledNode.style.right = "0px";
    if(this._vAdjustmentLower < this._height) this._vScrolledBar.hideSlider();
}

gtk.ScrolledWindow.prototype.getScrolledDom = function(){
    return this._scrolledDom;
};

gtk.ScrolledWindow.prototype.disableHScrolled = function(){
    this._scrolledDom.style.overflowX = "hidden";
};

gtk.ScrolledWindow.prototype.disableVScrolled = function(){
    this._scrolledDom.style.overflowY = "hidden";
};

gtk.ScrolledWindow.prototype.enableHScrolled = function(){
    this._scrolledDom.style.overflowX = "auto";
};

gtk.ScrolledWindow.prototype.enableVScrolled = function(){
    this._scrolledDom.style.overflowY = "auto";
};

gtk.ScrolledWindow.prototype.getScrollHeight = function(){
    return this._child.getHeight();
};

gtk.ScrolledWindow.prototype._resizeWidget = function(width, height){

	this._vAdjustmentLower = height;
	this._hAdjustmentLower = width;

    this._widgetDomObj.style.width = this._hAdjustmentLower + 'px';
    this._widgetDomObj.style.height = this._vAdjustmentLower + 'px';
}

gtk.ScrolledWindow.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
};

gtk.ScrolledWindow.prototype._resizeWidth = function(width){
	this._width = width;
	this._domObj.style.width = width + "px";
	this._scrolledDom.style.width = width + "px"
};

gtk.ScrolledWindow.prototype._resizeHeight = function(height){
    this._height = height;
	this._domObj.style.height = height + "px";
	this._scrolledDom.style.height = height + "px"
};

/**
 * Returns the value of the "vadjustment" prthis._vAdjustmentLoweroperty which is a reference to the vertical adjustment.
 * @return The vertical gtk.Adjustment
 */
gtk.ScrolledWindow.prototype.getVadjustmentLower = function(){
    return this._vAdjustmentLower;
};

/**
 * Returns the gtk.HScrollbar for the scrolled window or null if there is no horizontal scrollbar
 * @return The horizontal scrollbar of the scrolled window or None if it does not exist.
 */
gtk.ScrolledWindow.prototype.getHadjustmentLower = function(){
    return this._hAdjustmentLower;
};

gtk.ScrolledWindow.prototype.getMinHeightComposite = function(){
    return this._minHeight;
};

gtk.ScrolledWindow.prototype.getMinWidthComposite = function(){
    return this._minWidth;
};

gtk.ScrolledWindow.prototype.resizeWidthComposite = function(width){

	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this.resize(minWidth, this._height);
	if(this._child instanceof gtk.TreeView &&  minWidth > this._hAdjustmentLower) {
	    this._child.resizeWidthComposite(minWidth - 5);
	}
};

gtk.ScrolledWindow.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;

	this.resize(this._width, minHeight);
	if(this._child instanceof gtk.TreeView) {
	    this._child.resizeHeightComposite(minHeight - 25);
	}
	if(this._vScrolledBar) {
	    this._vScrolledBar.resizeHeight(minHeight);
	    if(this._vAdjustmentLower < minHeight) this._vScrolledBar.hideSlider();
	    else this._vScrolledBar.showSlider();
	}
};
gtk.ComboBoxController = function(view, model){
    this._view = view;
	this._model = model;
	var self = this;
	this._view.connect('rendercells', function(cols, comboWidth, docFragment){
	    var docFragment = docFragment || null;
        var size = self._calculateDropDownSize();
        var width = comboWidth < size[0] ? size[0] : comboWidth;
        var dropDownContainerHeight = (size[1] + 2) * this._model.getChildren().length;
        self._view.renderDropDownContainer(width - 3, dropDownContainerHeight, size[1] + 2);
        self._model.run(self._view, null, cols, 0, false, width - 3, size[1], docFragment);
        self._view.appendRows(docFragment);
	});

	this._view.connect('loadcontent', function(text){
	    var text = text || self._model.getChildren()[0].getRow()[0];
	    self._view.displayComboText(text);
	});
	this._view.connect('searchcontent', function(value){
        self._view.hilightRow(self._model.search(value));
	});
};

gtk.ComboBoxController.prototype._calculateDropDownSize = function(){
    var children = this._model.getChildren(), maxCellWidth = 0, maxCellHeight = 0;
    var length = children.length;
    for(var i = length; i--;){
        var text = children[i].getRow()[0];
        var size = jsgtk.Util.calculateTextWidthHeight(text);
        maxCellWidth  = maxCellWidth  < size[0] ? size[0] : maxCellWidth;
        maxCellHeight = maxCellHeight < size[1] ? size[1] : maxCellHeight;
    }
    return [maxCellWidth + 10, maxCellHeight];
};

gtk.ComboBoxController.prototype.setModel = function(model){
    this._model = model;
};
gtk.TextBuffer = function(table){
	gobject.GObject.apply(this);

	this._tagTable = table;
};

gtk.TextBuffer.prototype = new gobject.GObject();
gtk.TextBuffer.prototype.constructor = gtk.TextBuffer;
gtk.TextTag = function(name){
	gobject.GObject.apply(this);

    this.name = name;
};

gtk.TextTag.prototype = new gobject.GObject();
gtk.TextTag.prototype.constructor = gtk.TextTag;
gtk.TextTagTable = function(){
	gobject.GObject.apply(this);

    this._tagTable = [];
};

gtk.TextTagTable.prototype = new gobject.GObject();
gtk.TextTagTable.prototype.constructor = gtk.TextTagTable;

gtk.TextTagTable.prototype.add = function(tagText){
    this._tagTable.push(tagText);
}
/**
 * A widget that displays the contents of a gtk.TextBuffer. A class inherit from gtk.Container
 * @constructor
 */
gtk.TextView = function(){
	gtk.Container.apply(this);

	var self = this;
	this._editable = true;
	this._justification = "left";
	this._focus = false;

	this._minWidth = this._width = 100;
	this._minHeight = this._height = 50;

	this._render = function(){
	    var className = this._domObj.className;
		this._domObj = jsgtk.Dom.create({"tag": "textarea"})
		this._domObj.className = className + ' gtk_text_view';
	}

	this._render();

	jsgtk.Event.addDomListener(this._domObj, "focus", function(){
	    self._focus = true;
	    self.emit("movefocus", self._focus);
	});

	jsgtk.Event.addDomListener(this._domObj, "blur", function(){
	    self._focus = false;
	    self.emit("movefocus", self._focus);
	});
};

gtk.TextView.prototype = new gtk.Container();
gtk.TextView.prototype.constructor = gtk.TextView;

/**
 * Sets the "editable" property to the value of setting. If setting is True the text in textview is editable by default
 * @param {boolean} setting If True the text is editable by default
 */
gtk.TextView.prototype.setEditable = function(setting){
    this._editable = setting;

    setting? this._domObj.removeAttribute("readonly"):this._domObj.setAttribute("readonly", "readonly");
};

/**
 * Returns the value of the "editable" property
 * @return True if text is editable by default
 */
gtk.TextView.prototype.getEditable = function(){
    return  this._editable;
}

/**
 * Sets the "justification" property to the value of justification. The value of justification must be one of: gtk.JUSTIFY_LEFT, gtk.JUSTIFY_RIGHT, gtk.JUSTIFY_CENTER or gtk.JUSTIFY_FILL
 * @param {String} the text justification
 */
gtk.TextView.prototype.setJustification = function(justification){
    this._justification = justification;
    this._domObj.style.textAlign = justification;
};

/**
 * Returns the value of the "justification" property. the default justification of paragraphs in text_view. The value of "justification" must be one of: gtk.JUSTIFY_LEFT, gtk.JUSTIFY_RIGHT, gtk.JUSTIFY_CENTER or gtk.JUSTIFY_FILL.
 * @return The default justification
 */
gtk.TextView.prototype.getJustification = function(){
    return this._justification;
};

gtk.TextView.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
};

/** @private */
gtk.TextView.prototype._resizeWidth = function(width){
    this._domObj.style.width = width - 3 + 'px';
    this._width = width;
};

/** @private */
gtk.TextView.prototype._resizeHeight = function(height){
    this._domObj.style.height = height - 4 + 'px';
    this._height = height;
};

/** @private */
gtk.TextView.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);
};

/** @private */
gtk.TextView.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);
};

gobject.signalNew("movefocus", gtk.TextView, null, null, []);
/**
* Class gtk.Table
*/
gtk.Table = function(rows, columns, homogeneous, resizeable, spacing) {
	gtk.Container.apply(this);
	this._homogeneous    = homogeneous === undefined ? false : homogeneous;
	this._resizeable     = resizeable === undefined  ? false : resizeable;
	this._rows           = rows || 0;
	this._columns        = columns || 0;
	this._spacing        = spacing || 0;
	this._width          = this._minWidth = 10;
	this._height         = this._minHeight = 10;
	this._maxChildWidth  = this._width / this._columns;
	this._maxChildHeight = this._height/ this._rows;
	this._widths         = new Array(this._columns);
	this._heights        = new Array(this._rows);
	this._render = function(){
	    var domObj            = this._domObj
		domObj.className     += " gtk_table";
		domObj.style.width    = this._width + 'px';
		domObj.style.height   = this._height + 'px';
		domObj.style.position = "relative";
        this._children        = this._initChildren(this._rows, this._columns);
		this.hide();

		this._initWidthsHeights();
	};

	this._render();
};

gtk.Table.prototype = new gtk.Container();
gtk.Table.prototype.constructor = gtk.Table;

gtk.Table.prototype.attach = function(child, left, right, top, bottom, xoptions, yoptions, xpadding, ypadding){

    if(this._children[left][top].isEmpty){
        var xcells = 1;

        for(var i = left + 1; i < right; i++){
            if(this._children[i][top].isEmpty){
                this._children[i][top].isEmpty    = false;
                this._children[i][top].minWidth   = child.getMinWidthComposite();
                this._children[i][top].minHeight  = child.getMinHeightComposite();
                xcells += 1;
            }else break;
        }
        if(left + 1 < right){
            for(var i = left; i < right; i++){
                var ycells = 1;
                for(var j = top + 1; j < bottom; j++){
                    if(this._children[i][j].isEmpty){
                        this._children[i][j].isEmpty    = false;
                        this._children[i][j].minWidth   = child.getMinWidthComposite();
                        this._children[i][j].minHeight  = child.getMinHeightComposite();
                        ycells += 1;
                    }else break;
                }
            }
        }else{

            var ycells = 1;
            for(var i = top + 1; i < bottom; i++){
                if(this._children[left][i].isEmpty){
                    this._children[left][i].isEmpty    = false;
                    this._children[left][i].minWidth   = child.getMinWidthComposite();
                    this._children[left][i].minHeight  = child.getMinHeightComposite();
                    ycells += 1;
                }else break;
            }
        }

        var targetChild = this._children[left][top];
        targetChild.widget   = child;
        targetChild.isEmpty  = false;
        targetChild.xoptions = xoptions;
        targetChild.yoptions = yoptions;
        targetChild.xpadding = xpadding;
        targetChild.ypadding = ypadding;
        targetChild.xcells   = xcells;
        targetChild.ycells   = ycells;
        targetChild.left     = left;
        targetChild.right    = right;
        targetChild.top      = top;
        targetChild.bottom   = bottom;
        targetChild.minWidth = child.getMinWidthComposite();
        targetChild.minHeight= child.getMinHeightComposite();

        if(this._homogeneous){
            this._setMaxChildWidthHeightHomo(targetChild);
            this._placeChildrenHomo(this._maxChildWidth, this._maxChildHeight);
            this.resize(this._maxChildWidth * this._columns, this._maxChildHeight * this._rows);
        }else{

            this._resetWidths(child, left, right, xoptions);
            this._resetHeights(child, top, bottom, yoptions);

            this._placeChildrenNoneHomo();

            var maxWidth  = this._getWidths();
            var maxHeight = this._getHeights();

            this.resize(maxWidth, maxHeight);
            this._minWidth = maxWidth;
            this._minHeight= maxHeight;
        }
    }
};

gtk.Table.prototype._initWidthsHeights = function(){
	for(var i = 0, len = this._widths.length; i < len; i++) this._widths[i]  = {"width": this._maxChildWidth + this._spacing, "resizeable": true};
	for(var i = 0, len = this._heights.length; i < len; i++) this._heights[i] = {"height": this._maxChildHeight + this._spacing, "resizeable": true};
};

gtk.Table.prototype._setMaxChildWidthHeightHomo = function(child){
    var childWidth       = child.minWidth + 2   * child.xpadding;
    var childHeight      = child.minHeight + 2  * child.ypadding;
    this._maxChildWidth  = this._maxChildWidth  * child.xcells > childWidth ? this._maxChildWidth : childWidth / child.xcells;
    this._maxChildHeight = this._maxChildHeight * child.ycells > childHeight? this._maxChildHeight: childHeight / child.ycells;
};

gtk.Table.prototype._resetWidths = function(child, left, right, xoptions){
    var extraWidth = 0;
    for(var i = left; i < right; i++){
        extraWidth += this._widths[i]["width"];
    }

    var childWidthComposite = child.getMinWidthComposite() + this._spacing;
    var biggerWidth = (extraWidth < childWidthComposite ? childWidthComposite : extraWidth);

    offsetWidth = (biggerWidth - extraWidth) / (right - left);

    for(var i = left; i < right; i++){
        this._widths[i]["width"]      += offsetWidth;
        this._widths[i]["resizeable"]  = xoptions["resizeable"] === undefined ? true : xoptions["resizeable"];
    }
};

gtk.Table.prototype._resetHeights = function(child, top, bottom, yoptions){
    var extraHeight = 0;
    for(var i = top; i < bottom; i++){
        extraHeight += this._heights[i]["height"];
    }

    var childHeightComposite = child.getMinHeightComposite() + this._spacing;
    var biggerHeight = (extraHeight < childHeightComposite ? childHeightComposite : extraHeight)

    offsetHeight = (biggerHeight - extraHeight) / (bottom - top);
    for(var i = top; i < bottom; i++){
        this._heights[i]["height"]     += offsetHeight;
        this._heights[i]["resizeable"]  = yoptions["resizeable"] === undefined ? true : yoptions["resizeable"];
    }
};

gtk.Table.prototype._placeChildrenNoneHomo = function(){
    var child;
    this._domObj.innerHTML = "";
    var docFragment = document.createDocumentFragment();
    for(var i = 0; i < this._rows; i++){
        for(var j = 0; j < this._columns; j++){
            child = this._children[j][i];
            var width = 0;
            var height = 0;
            if(child.widget){
                var childWrapper = jsgtk.Dom.create({"append": docFragment, "tag": "div", "style": "position: absolute;"});

                for(var k = child.left; k < child.right; k++){
                    width += this._widths[k]["width"];
                }
                var left = 0; //how far from the left has to place the wrapper
                for(var k = 0; k < child.left; k++){
                    left += this._widths[k]["width"];
                }

                for(var k = child.top; k < child.bottom; k++){
                    height += this._heights[k]["height"];
                }
                var top = 0;//how far from the top has to place the wrapper
                for(var k = 0; k < child.top; k++){
                    top += this._heights[k]["height"];
                }

                childWrapper.style.width  = width + "px";
                childWrapper.style.height  = height + "px";
                childWrapper.style.left = left + "px";
                childWrapper.style.top = top + "px";

                childWrapper.appendChild(child.widget._domObj);

                this._positionWidgetByXoptionsNoneHomo(child, width);
                this._positionWidgetByYoptionsNoneHomo(child, height);
            }
        }
    }
    this._domObj.appendChild(docFragment);
};

gtk.Table.prototype._positionWidgetByXoptionsNoneHomo = function(child, width){
    var xpadding = child.xpadding;
    var spacing = child.right === this._columns ? 0 : this._spacing;
    if(child.xoptions.fill){
        child.widget._domObj.style.left = xpadding + "px";
        child.widget.resizeWidthComposite(width - xpadding * 2 - spacing);
    }else{
        var left;
        switch(child.xoptions.align){
            case gtk.JUSTIFY_LEFT :
                child.widget._domObj.style.left = child.xpadding + "px";
                break;
            case gtk.JUSTIFY_RIGHT :
                left = width - (child.minWidth + child.xpadding) - spacing;
                child.widget._domObj.style.left = left + "px";
                break;
            case gtk.JUSTIFY_CENTER :
                left = ( (width-spacing) / 2) - (child.minWidth / 2);
                child.widget._domObj.style.left = left + 'px';
                break;
        }
        child.widget.resizeWidthComposite(child.minWidth);
    }
};

gtk.Table.prototype._positionWidgetByYoptionsNoneHomo = function(child, height){
    var ypadding = child.ypadding;
     var spacing = child.bottom === this._rows ? 0 : this._spacing;
    if(child.yoptions.fill){
        child.widget._domObj.style.top = ypadding + "px";
        child.widget.resizeHeightComposite(height - ypadding * 2 - spacing);
    }else{
        var top;
        switch(child.yoptions.align){
            case gtk.JUSTIFY_TOP :
                child.widget._domObj.style.top = child.ypadding + "px";
                break;
            case gtk.JUSTIFY_BOTTOM :
                top = height - (child.minHeight + child.ypadding) - spacing;
                child.widget._domObj.style.top = top + "px";
                break;
            case gtk.JUSTIFY_CENTER :
                top = ( (height-spacing) / 2) - (child.minHeight / 2);
                child.widget._domObj.style.top = top + 'px';
                break;
        }
        child.widget.resizeHeightComposite(child.minHeight);
    }
};

gtk.Table.prototype._placeChildrenHomo = function(childWidth, childHeight){
    var children = this._children;
    this._domObj.innerHTML = "";
    var docFragment = document.createDocumentFragment();
    for(var i = 0; i < this._columns; i++){
        for(var j = 0; j < this._rows; j++){
            var child = children[i][j];
            if(child.widget){
                var childWrapper = jsgtk.Dom.create({'append': docFragment, 'tag': 'div', 'style': 'position: absolute;'});
                childWrapper.style.width  = childWidth  * child.xcells + 'px';
                childWrapper.style.height = childHeight * child.ycells + 'px';
                childWrapper.style.top    = child.top * childHeight + 'px';
                childWrapper.style.left   = child.left * childWidth + 'px';
                childWrapper.appendChild(child.widget._domObj);

                var width  = this._positionWidgetByXoptionsHomo(child, childWidth);
                var height =this._positionWidgetByYoptionsHomo(child, childHeight);

                child.widget.resizeWidthComposite(width - 2);
                child.widget.resizeHeightComposite(height - 2);
            }
        }
    }
    this._domObj.appendChild(docFragment);
};

gtk.Table.prototype._positionWidgetByYoptionsHomo = function(child, childHeight){
    var height;
    var spacing = child.bottom === this._rows ? 0 : this._spacing;
    if(child.yoptions.fill){
        child.widget._domObj.style.top = child.ypadding + 'px';
        height  = childHeight  * child.ycells - child.ypadding * 2 - spacing;
    }else{
        var top;
        height  = child.widget.getMinHeightComposite();
        switch(child.yoptions.align){
            case gtk.JUSTIFY_TOP :
                child.widget._domObj.style.top = child.ypadding + "px";
                break;
            case gtk.JUSTIFY_BOTTOM :
                top = (childHeight * child.ycells) - (height + child.ypadding);
                child.widget._domObj.style.top = top + "px";
                break;
            case gtk.JUSTIFY_CENTER :
                top = ( (childHeight * child.ycells) / 2) - (height / 2);
                child.widget._domObj.style.top = top + "px";
                break;
        }
    }
    return height;
};

gtk.Table.prototype._positionWidgetByXoptionsHomo = function(child, childWidth){
    var width;
    var spacing = child.right === this._columns ? 0 : this._spacing;
    if(child.xoptions.fill){
        child.widget._domObj.style.left = child.xpadding + 'px';
        width  = childWidth * child.xcells - child.xpadding * 2 - spacing;
    }else{
        var left;
        width  = child.widget.getMinWidthComposite();
        switch(child.xoptions.align){
            case gtk.JUSTIFY_LEFT :
                child.widget._domObj.style.left = child.xpadding + "px";
                break;
            case gtk.JUSTIFY_RIGHT :
                left = (childWidth * child.xcells) - (width + child.xpadding);
                child.widget._domObj.style.left = left + "px";
                break;
            case gtk.JUSTIFY_CENTER :
                left = ( (childWidth * child.xcells) / 2) - (width / 2);
                child.widget._domObj.style.left = left + 'px';
                break;
        }
    }
    return width;
};

gtk.Table.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
};

gtk.Table.prototype._initChildren = function(rows, columns){
    var children = new Array(columns);
    for(var i = 0, len = this._columns; i < len; i++){
        children[i] = new Array(rows);
    }

    for(var i = 0, len = this._columns; i < len; i++){
        for(var j = 0, length = this._rows; j < length; j++){
            children[i][j] = {
                isEmpty  : true,
                widget   : null,
                minWidth : null,
                minHeight: null,
                width    : null,
                height   : null,
                xoptions : null,
                yoptions : null,
                xpadding : null,
                ypadding : null,
                xcells   : null,
                ycells   : null,
                left     : null,
                right    : null,
                top      : null,
                bottom   : null
            };
        }
    }
    return children;
};

gtk.Table.prototype._getWidths = function(){
    var width = 0;
    for(var i = 0; i < this._columns; i++){
        width += this._widths[i]["width"];
    }
    return width;
};

gtk.Table.prototype._getHeights = function(){
    var height = 0;
    for(var i = 0; i < this._rows; i++){
        height += this._heights[i]["height"];
    }
    return height;
};

gtk.Table.prototype._getResizeableColumns = function(){
    var columns = 0;
    for(var i = this._widths.length; i--;){
        if(this._widths[i]["resizeable"]) columns += 1;
    }
    return columns;
};

gtk.Table.prototype._getResizeableRows = function(){
    var rows = 0;
    for(var i = this._heights.length; i--;){
        if(this._heights[i]["resizeable"]) rows += 1;
    }
    return rows;
};

gtk.Table.prototype.getMinWidthComposite = function(){
    return this._homogeneous ? this._maxChildWidth * this._columns : this._minWidth;//this._minWidth will be replaced by getWidths()
};

gtk.Table.prototype.getMinHeightComposite = function(){
    return this._homogeneous ? this._maxChildHeight * this._rows : this._minHeight;//this._minHeight will be replaced by getHeights()
};

gtk.Table.prototype.resizeWidthComposite = function(width){
    var widthComposite = this.getMinWidthComposite();
   	widthComposite     = width > widthComposite ? width : widthComposite;

    if(this._homogeneous){
        width = width > widthComposite ? width : widthComposite;
	    var maxChildWidth  = (width / this._columns) + this._spacing;
	    var maxChildHeight = this._height / this._rows
	    if(this._resizeable) this._placeChildrenHomo(maxChildWidth, maxChildHeight);
        this.resize(maxChildWidth * this._columns, maxChildHeight * this._rows);
    }else{
        var columns = this._getResizeableColumns();
        var offsetWidth = (widthComposite - this._getWidths()) / columns;
        for(var i = 0; i < this._columns; i++){
            if(this._widths[i]["resizeable"]) this._widths[i]["width"] += offsetWidth;
        }
        if(this._resizeable) this._placeChildrenNoneHomo();
        this.resize(widthComposite, this._height);
    }
};

gtk.Table.prototype.resizeHeightComposite = function(height){
   	var heightComposite = this.getMinHeightComposite();
   	heightComposite     = height > heightComposite ? height : heightComposite;
   	if(this._homogeneous){
    	height = height > heightComposite ? height : heightComposite;
        var maxChildHeight = height / this._rows + this._spacing;
        var maxChildWidth  = this._width / this._columns;
		if(this._resizeable) this._placeChildrenHomo(maxChildWidth, maxChildHeight);
        this.resize(maxChildWidth * this._columns, maxChildHeight * this._rows);
   	}else{
        var rows = this._getResizeableRows();
        var offsetHeight = (heightComposite - this._getHeights()) / rows;
        for(var i = 0; i < this._rows; i++){
            if(this._heights[i]["resizeable"]) this._heights[i]["height"] += offsetHeight;
        }
        if(this._resizeable) this._placeChildrenNoneHomo();
        this.resize(this._width, heightComposite);
   	}
};
/**
* class gtk.Slider
*/
gtk.Slider = function(columns, spacing) {
	gtk.Container.apply(this);
    var self = this;
    this._imgSrc = pango.Path.getRootPath().split("javascript")[0];
	this._width      = this._minWidth  = 300;
	this._height     = this._minHeight = 200;
	this._columns    = columns || 1;
	this._spacing    = spacing || 1;
	this._marginLeft = 50;
	this._slideWidth = this._getSlideWidth(this._width);
	this._slideWidths;
	this._slides     = [];
	this._currentLeft= 0;
	this._arrowWidth = 40;
	this._arrowHeight= 52;

	this._isMoving = false;

	this._render = function(){
		this._domObj.className   += " gtk_slider";
		    this._frame = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_slides_frame", "style": "position: relative;"});
		    this._frame.style.left  = this._marginLeft + "px";
		    this._frame.style.overflowY = "hidden";
		        this._slidesContainer = jsgtk.Dom.create({"append": this._frame, "tag": "div", "class": "gtk_slides_container"});
		        this._slidesContainer.style.height = this._height + "px";

        this._leftArrow = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_slider_leftarrow"});
        this._leftArrowDisabled = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_slider_leftarrow_disabled"});
        this._positionArrowLeft(this._leftArrow);
        this._positionArrowLeft(this._leftArrowDisabled);
        jsgtk.Dom.hideElement(this._leftArrow);

        this._rightArrow = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_slider_rightarrow"});
        this._rightArrowDisabled = jsgtk.Dom.create({"append": this._domObj, "tag": "div", "class": "gtk_slider_rightarrow_disabled"});
        this._positionArrowRight(this._rightArrow);
        this._positionArrowRight(this._rightArrowDisabled);
        jsgtk.Dom.hideElement(this._rightArrowDisabled);

 		this.resize(this._width, this._height);
		this.hide();
	};

    this._render();

    jsgtk.Event.addDomListener(this._leftArrow, "click", function(e){

        if(!self._isMoving && self._currentLeft !== 0)self._moveRight();
	    jsgtk.Event.stopBubble(e);
	}, false);

    jsgtk.Event.addDomListener(this._rightArrow, "click", function(e){

        if(!self._isMoving){
            var len = self._slides.length >= self._columns ? self._columns : 1;
            var left = self._slideWidth * (self._slides.length - len);
            var isMovable = left + self._currentLeft;
            if(isMovable >= 0) self._moveLeft();
        }
        jsgtk.Event.stopBubble(e);
	}, false);
};

gtk.Slider.prototype = new gtk.Container();
gtk.Slider.prototype.constructor = gtk.Slider;

gtk.Slider.prototype.addSlide = function(widget){
    var self = this;
    var scrolledWindow = this._getScrolledWindow(widget);

    var slide = this._constructSlide(scrolledWindow, this._slideWidth, this._height);
    this._resizeElement(slide, this._slideWidth, this._height - 7);

    var space = this._constructSpace();
    this._resizeElement(space, this._spacing, this._height);

    this._slides.push({
        "slide"  : slide,
        "space"  : space,
        "widget" : scrolledWindow
    });
    scrolledWindow.resizeWidthComposite(this._slideWidth);
    scrolledWindow.resizeHeightComposite(this._height - 7);

    this.resize(this._width, this._height);
    var slideWidth = this._slideWidth + this._spacing + 2;
    this._setSlideWidths(slideWidth * (this._slides.length));

    if(this._slides.length <= this._columns) {
        jsgtk.Dom.hideElement(this._rightArrow);
        jsgtk.Dom.showElement(this._rightArrowDisabled);
    }else{
        jsgtk.Dom.hideElement(this._rightArrowDisabled);
        jsgtk.Dom.showElement(this._rightArrow);
    }

    jsgtk.Event.addDomListener(slide, "mouseover", function(e){
        jsgtk.Dom.showElement(this.lastChild);
        jsgtk.Event.stopBubble(e);
    });

    jsgtk.Event.addDomListener(slide, "mouseout", function(e){
        jsgtk.Dom.hideElement(this.lastChild);
        jsgtk.Event.stopBubble(e);
    });

    jsgtk.Event.addDomListener(slide.lastChild, "mousedown", function(e){
        self._removeSlide(slide, space);
        if(self._slides.length <= self._columns){
            jsgtk.Dom.hideElement(self._rightArrow);
            jsgtk.Dom.showElement(self._rightArrowDisabled);

            jsgtk.Dom.hideElement(self._leftArrow);
            jsgtk.Dom.showElement(self._leftArrowDisabled);
        }
        jsgtk.Event.stopBubble(e);
    });
};

gtk.Slider.prototype._removeSlide = function(slide, space){
    var self = this;
    for(var i = this._slides.length; i--;){
        if(this._slides[i].slide === slide) {
            this._slides.splice(i, 1);
            break;
        }
    }

    var width = parseInt(slide.style.width);
    var intervalID = window.setInterval(function(){
        width -= 10;
        slide.style.width = width + "px";
        if(width <= 0) {
            var slideWidth = self._slideWidth + self._spacing + 2;

            self._setSlideWidths(slideWidth * (self._slides.length));

            self._slidesContainer.style.width = self._slideWidths + "px";

            var left = self._currentLeft - slideWidth;

            if(slide.parentNode.lastChild === space) self._frame.scrollLeft -= 5;

            if(left >0) self._currentLeft = left;

            slide.parentNode.removeChild(space);
            slide.parentNode.removeChild(slide);


            clearInterval(intervalID);
        }
    }, 5);
};

gtk.Slider.prototype._setSlideWidths = function(width){
    this._slideWidths = width;
}

gtk.Slider.prototype._resizeSlides = function(width, height){
    var slide;

    this._slideWidth = this._getSlideWidth(width);

    var slideWidth = this._slideWidth + this._spacing + 2;
    this._setSlideWidths(slideWidth * (this._slides.length));

    for(var i = 0, len = this._slides.length; i<len; i++){
        slide = this._slides[i];
        this._resizeElement(slide["slide"], this._slideWidth, height - 13);
        this._resizeElement(slide["space"], this._spacing, height);
        slide["widget"].resizeWidthComposite(this._slideWidth);
        slide["widget"].resizeHeightComposite(height - 13);
    }
    this.resize(width, height);

    this._positionArrowLeft(this._leftArrow);
    this._positionArrowLeft(this._leftArrowDisabled);
    this._positionArrowRight(this._rightArrow);
    this._positionArrowRight(this._rightArrowDisabled);
};

gtk.Slider.prototype._getSlideWidth = function(width){
    width = ( (width - this._marginLeft * 2) - ( (this._columns - 1) * this._spacing) - this._columns * 2) / this._columns;
    return width;
}

gtk.Slider.prototype.resize = function(width, height){
    this._resizeWidth(width);
    this._resizeHeight(height);
};

gtk.Slider.prototype._resizeElement = function(element, width, height){
    element.style.width = width + "px";
    element.style.height= height + "px";
}

gtk.Slider.prototype._constructSpace = function(){
    var space = jsgtk.Dom.create({"append": this._slidesContainer, "tag": "div", "style": "float: left;"});
    return space;
};

gtk.Slider.prototype._constructSlide = function(scrolledWindow){
    var slide = jsgtk.Dom.create({"append": this._slidesContainer, "tag": "div", "class": "gtk_slider_slide", "style": "float: left;"});
    slide.appendChild(scrolledWindow._domObj);
	var closeButton = jsgtk.Dom.create({"append": slide, "tag": "div", "class": "gtk_slider_close_button"});
	jsgtk.Dom.hideElement(closeButton);
    return slide;
};

gtk.Slider.prototype._getScrolledWindow = function(widget){
    var viewport = new gtk.Viewport();
    viewport.show();
    viewport.add(widget);

    var scrolledWindow = new gtk.ScrolledWindow();
    scrolledWindow.show();
    scrolledWindow.add(viewport);
    scrolledWindow.disableHScrolled();

    return scrolledWindow;
};

gtk.Slider.prototype._moveRight = function(){
    var self = this;
    var left = this._currentLeft - (this._slideWidth + this._spacing + 2);

    var intervalID = window.setInterval(function(){
        self._currentLeft -= 10;
        self._isMoving = true;
        self._frame.scrollLeft = self._currentLeft;

        if(self._currentLeft <= left){
            self._frame.scrollLeft = left;
            self._currentLeft = left;
            clearInterval(intervalID);
            self._enableRightArrow();
            if(self._frame.scrollLeft === 0) self._disableRightArrow();
            self._isMoving = false;
        };
    }, 10);
};

gtk.Slider.prototype._moveLeft = function(){

    var self = this;
    var left = this._currentLeft + this._slideWidth + this._spacing + 2;
    var intervalID = window.setInterval(function(){
        self._currentLeft += 10;
        self._frame.scrollLeft = self._currentLeft;
        self._isMoving = true;
        if(self._currentLeft >= left){
            self._frame.scrollLeft = left;
            self._currentLeft = left;

            self._enableLeftArrow();

            var actualSlideWidth = self._slideWidth + self._spacing + 2;
            var width = Math.floor(self._slideWidths - self._frame.scrollLeft);

            if(width <= actualSlideWidth * self._columns) self._disableLeftArrow();
            clearInterval(intervalID);

            self._isMoving = false;
        };
    }, 10);
};

gtk.Slider.prototype._positionArrowLeft = function(leftArrow){
    leftArrow.style.width  = this._arrowWidth + "px";
    leftArrow.style.height = this._arrowHeight + "px";
    leftArrow.style.top = this._height / 2 - this._arrowHeight/2 + "px";
    leftArrow.style.left = "5px";
};

gtk.Slider.prototype._positionArrowRight = function(rightArrow){
    rightArrow.style.width  = this._arrowWidth + "px";
    rightArrow.style.height = this._arrowHeight + "px";
    rightArrow.style.top = this._height / 2 - this._arrowHeight/2 + "px";
    rightArrow.style.right = "0px"
};

gtk.Slider.prototype._enableRightArrow = function(){
    jsgtk.Dom.hideElement(this._rightArrowDisabled);
    jsgtk.Dom.showElement(this._rightArrow);
};

gtk.Slider.prototype._disableRightArrow = function(){
    jsgtk.Dom.hideElement(this._leftArrow);
    jsgtk.Dom.showElement(this._leftArrowDisabled);
};

gtk.Slider.prototype._enableLeftArrow = function(){
    jsgtk.Dom.hideElement(this._leftArrowDisabled);
    jsgtk.Dom.showElement(this._leftArrow);
};

gtk.Slider.prototype._disableLeftArrow = function(){
    jsgtk.Dom.showElement(this._rightArrowDisabled);
    jsgtk.Dom.hideElement(this._rightArrow);
};

gtk.Slider.prototype._resizeWidth = function(width){
    this._width = width;
    this._domObj.style.width  = this._width + "px";
    this._frame.style.width = this._width  - this._marginLeft * 2 + 6 + "px";
    this._slidesContainer.style.width = this._slideWidths + "px";
};

gtk.Slider.prototype._resizeHeight= function(height){
    this._height = height;
    this._frame.style.height= this._height + 25 + "px";
    this._domObj.style.height = this._height + "px";
    this._slidesContainer.style.height = this._height + "px";
};

gtk.Slider.prototype.getMinHeightComposite = function(){
    return this._minHeight;
};

gtk.Slider.prototype.getMinWidthComposite = function(){
    return this._minWidth;
};

gtk.Slider.prototype.resizeWidthComposite = function(width){
	var minWidthComposite = this.getMinWidthComposite();
	var minWidth = width > minWidthComposite ? width : minWidthComposite;
	this._resizeSlides(minWidth, this._height);
};

gtk.Slider.prototype.resizeHeightComposite = function(height){
	var minHeightComposite = this.getMinHeightComposite();
	var minHeight = height > minHeightComposite ? height : minHeightComposite;
	this._resizeSlides(this._width, minHeight);
};
/**
 * A widget with an entry which is able to create many tags
 * @constructor
 */

gtk.SmartEntry = function(allowLabel){
    gtk.Widget.apply(this);
    var self = this;
    this._minWidth = this._width = 150;
    this._minHeight = this._height = 75;
    this._entryWidth = 50;
    this._entry = null;
    this._allowLabel = allowLabel || false;
    this._isAllowOneTag = false;
    this._filter = false;
    this._eventStorage = [];
    this._keyEvent;
    this._selectedIndex = -1;
    this._index = 0;
	this._render = function(){
	    this._domObj.className += " gtk_smart_entry";
	    this._domObj.style.width = this._width + "px";
	    this._domObj.style.height = this._height + "px";
	    this._areaDom = jsgtk.Dom.create({"tag": "div", append: this._domObj, "className": "gtk_smart_entry_area"});
	    this._holder = jsgtk.Dom.create({"tag": "span", append: this._areaDom});

	    if(!this._allowLabel) this._createEntry();

	    this.hide();
	};

	this._render();

	jsgtk.Event.addDomListener(document.body, "click", function(){
	    self._hideDropDown();
	}, false);
};

gtk.SmartEntry.prototype = new gtk.Widget();
gtk.SmartEntry.prototype.constructor = gtk.SmartEntry;

/** @private */
gtk.SmartEntry.prototype._hideDropDown = function(){
    var dropDown = this._domObj.getElementsByClassName("gtk_smart_entry_drop_down_holder");
    for(var i = 0, len = dropDown.length; i < len; i++){
        dropDown[i].style.display = "none";
    }
}

/** @private */
gtk.SmartEntry.prototype._createEntry = function(){
    var self = this;

    var entryDiv = jsgtk.Dom.create({"tag": "div", append: this._areaDom, "className": "gtk_smart_entry_input_holder"});
        this._entry = jsgtk.Dom.create({"tag": "input", append: entryDiv, "className": "gtk_smart_entry_input"});

    entryDiv.style.width = "32px";

    this._bindEntryLostFocusEvent();

    this._bindEntryKeypressEvent();

    jsgtk.Event.addDomListener(this._areaDom, "click", function(e){
        self._entry.style.visibility = "visible";
	    self._entry.focus();
	    jsgtk.Event.stopBubble(e);
	});
};

/** @private */
gtk.SmartEntry.prototype._bindEntryLostFocusEvent = function(){
    var self = this;

    jsgtk.Event.addDomListener(this._entry, "blur", function(){
        if(self._isAllowOneTag){
            self._createTailTag(self._holder);
            return;
        }

        self._unSelectTags();

        self._createTag(self._holder);
    }, false);
};

gtk.SmartEntry.prototype._unSelectTags = function(){
    var tags = this._holder.childNodes;

    for(var i = 0, len = tags.length; i < len; i++){
        if(tags[i].selected == true){
            tags[i].selected = false;
            tags[i].className = "gtk_smart_entry_tag_holder";
        }
    }
}

/** @private */
gtk.SmartEntry.prototype._bindEntryKeypressEvent = function(){
    var self = this;
    var tempSpan = document.createElement("span");
    var tempWidth;

    jsgtk.Event.addDomListener(this._entry, "keypress", function(e){

        switch(e.keyCode){
            case gtk.ENTER_KEY:
                self._bindEntryEnterKeyEvent();
                break;
            case gtk.BACKSPACE_KEY:
                self._bindEntryBackspaceKeyEvent();
                break;
            case gtk.DELETE_KEY:
                self._bindEntryDeleteKeyEvent(e);
                break;
            default:
                if(!self._isAllowOneTag){
                    tempSpan.innerHTML = self._entry.value;
                    tempWidth = self._calculateTextWidth(tempSpan) + self._entryWidth - 2;
                    self._entry.style.width = (tempWidth) < self._width - 2? tempWidth + "px" : self._width - 2 + "px";
                }
        }

        if(e.which == gtk.A_KEY || e.which == gtk.CAP_A_KEY && e.ctrlKey){
            self._bindEntryCtrlAKeyEvent();
        }
    },false);
};

gtk.SmartEntry.prototype._bindEntryCtrlAKeyEvent = function(){
    if(this._entry.value != "") return;
    var tags = this._holder.childNodes;
    var len = tags.length;
    for(var i = 0; i < len; i++){
        if(tags[i].childNodes[0].className == "gtk_smart_entry_fixed_tag") continue;
        tags[i].className += " gtk_smart_entry_tag_selected";
        tags[i].selected = true;
    }
    this._entry.style.visibility = "hidden";
};

/** @private */
gtk.SmartEntry.prototype._bindEntryBackspaceKeyEvent = function(){
        var tags = this._holder.childNodes;
        var len = tags.length;
        if(len > 0 && this._entry.value == "" && tags[len-1].childNodes[0].className != "gtk_smart_entry_fixed_tag"){
            var tag = tags[len-1];
            if(tag.selected){
                tag.parentNode.removeChild(tag);
                this._entry.style.visibility = "visible";
                this._unSelectTags();
            }
            else{
                tag.selected = true;
                tag.className += " gtk_smart_entry_tag_selected";
                this._entry.style.visibility = "hidden";
            }
        }
        return;
}

/** @private */
gtk.SmartEntry.prototype._bindEntryDeleteKeyEvent = function(e){
    var tags = this._holder.childNodes;
    var len = tags.length;

    if(len > 0 && this._entry.value == "" && tags[len -1].selected){
        tags = this._holder.childNodes;
        var length = this._holder.childNodes.length;
        for(var i = length-1 ; i >= 0 ; i--){
            if(tags[i].selected) this._holder.removeChild(tags[i]);
        }
        this._entry.style.visibility = "visible";
    }
}

/** @private */
gtk.SmartEntry.prototype._bindEntryEnterKeyEvent = function(){
    if(this._isAllowOneTag){
        this._createTailTag(this._holder);
        return;
    }

    this._createTag(this._holder);
};

/** @private */
gtk.SmartEntry.prototype._createTag = function(holder){
    if(this._entry.value){
        var self = this;
        var tagHolder = jsgtk.Dom.create({"tag": "div", "append": holder, "className": "gtk_smart_entry_tag_holder"});
        var tag  = jsgtk.Dom.create({"tag": "span", "append": tagHolder , "text": this._entry.value});
        var closeButton = jsgtk.Dom.create({"tag": "div", append: tagHolder, "className": "gtk_smart_entry_close"});

        jsgtk.Event.addDomListener(closeButton, "click", function(){
            tagHolder.parentNode.removeChild(tagHolder);
            self._entry.blur();
        }, false);

        this._entry.value = "";
        this._entry.style.width = this._entryWidth + "px";
        window.setTimeout(function(){self._entry.focus()}, 1);
    }
};

gtk.SmartEntry.prototype.createFixedTag = function(fixedTag){
    var tagHolder = jsgtk.Dom.create({"tag": "div", "append": this._holder, "className": "gtk_smart_entry_tag_holder"});
    var tag  = jsgtk.Dom.create({"tag": "span", "append": tagHolder , "text": fixedTag, "className": "gtk_smart_entry_fixed_tag"});
};

/** @private */
gtk.SmartEntry.prototype._showInput = function(tagHolder){
    if(tagHolder.childNodes[2]) tagHolder.removeChild(tagHolder.childNodes[2]);
    var entryDiv = tagHolder.childNodes[1];

    tagHolder.childNodes[0].style.display = "none";
    entryDiv.style.display = "";
    entryDiv.value = "";

    window.setTimeout(function(){entryDiv.focus();}, 0);
    var self = this;

    jsgtk.Event.addDomListener(entryDiv, "blur", function(){
        self._bindInputLostFocusEvent(entryDiv, tagHolder);
    }, false);

    return entryDiv;
};

/** @private */
gtk.SmartEntry.prototype._bindInputLostFocusEvent = function(entryDiv, tagHolder){
    if(entryDiv.value){
        if(tagHolder.childNodes[2]) tagHolder.removeChild(tagHolder.childNodes[2]);
        var tagDiv = jsgtk.Dom.create({"append": tagHolder,"tag": "div", "className": "gtk_smart_entry_tag_holder"});
        var tag  = jsgtk.Dom.create({"tag": "span", "append": tagDiv , "text": entryDiv.value});
        var closeButton = jsgtk.Dom.create({"tag": "div", append: tagDiv, "className": "gtk_smart_entry_close"});

        entryDiv.style.display = "none";

        jsgtk.Event.addDomListener(closeButton, "click", function(){
            tagHolder.removeChild(tagDiv);
            tagHolder.childNodes[0].style.display = "";
        }, false);
    }
    else{
        tagHolder.childNodes[0].style.display = "";
        tagHolder.childNodes[1].style.display = "none";

        if(tagHolder.childNodes[2]) tagHolder.removeChild(tagHolder.childNodes[2]);
    }

};

/** @private */
gtk.SmartEntry.prototype._createTagHolder = function(tagHolder, entryDiv){
    var tagDiv = jsgtk.Dom.create({"tag": "div", "className": "gtk_smart_entry_tag_holder"});
    var tag  = jsgtk.Dom.create({"tag": "span", "append": tagDiv , "text": entryDiv.value});
    var closeButton = jsgtk.Dom.create({"tag": "div", append: tagDiv, "className": "gtk_smart_entry_close"});

    jsgtk.Event.addDomListener(closeButton, "click", function(){
        tagHolder.removeChild(tagDiv);
        tagHolder.childNodes[0].style.display = "";
    }, false);
};

/** @private */
gtk.SmartEntry.prototype._createKeypressEventForInput = function(entryDiv, tagHoldersss, index){
    var self = this;
    var tagHolders = this._holder.childNodes;

    jsgtk.Event.addDomListener(entryDiv, "keypress", function(e){
        if(e.keyCode == gtk.ENTER_KEY){
            entryDiv.blur();
            return;
        }

        if(e.which == gtk.A_KEY || e.which == gtk.CAP_A_KEY && e.ctrlKey){
            if(entryDiv.value != "") return;
            var tags = self._holder.childNodes;
            var len = tags.length;
            for(var i = 0; i < len; i++){
                if(tags[i].childNodes[0].className == "gtk_smart_entry_fixed_tag" || !tags[i].childNodes[2]) continue;
                if(tags[i].childNodes[2].tagName == "DIV") {
                    tags[i].childNodes[2].className += " gtk_smart_entry_tag_selected";
                    tags[i].selected = true;
                }
            }
            return;
        }

        if(e.keyCode == gtk.TAB_KEY && tagHolders[index+1]){
            var nextEntryDiv = self._showInput(tagHolders[index + 1]);

            self._createKeypressEventForInput(nextEntryDiv, tagHolders, index+1);

            window.setTimeout(function(){nextEntryDiv.focus();}, 0);
        }

        if(e.keyCode == gtk.BACKSPACE_KEY && entryDiv.parentNode.previousSibling && entryDiv.value == ""){
            if(entryDiv.parentNode.previousSibling){
                var previousSibling = entryDiv.parentNode.previousSibling;
                if(previousSibling.selected){
                    if(previousSibling.childNodes[2].selected == true)  previousSibling.removeChild(previousSibling.childNodes[2]);

                    for(var i = 0; i < tagHolders.length; i++){
                        tagHolders[i].selected = false;
                    }

                    var input = self._showInput(previousSibling);

                    previousSibling.childNodes[1].focus();
                }
                else{
                    if(previousSibling.childNodes[2]){
                        previousSibling.selected = true;
                        previousSibling.childNodes[2].className += " gtk_smart_entry_tag_selected";
                    }
                }
            }
        }

        if(e.keyCode == gtk.DELETE_KEY && entryDiv.parentNode.previousSibling){
            if(!entryDiv.parentNode.previousSibling.selected)
                return;
            var j;
            for(var i = self._holder.childNodes.length - 1; i >= 0; i--){
                if(self._holder.childNodes[i].selected){
                    self._holder.childNodes[i].removeChild(self._holder.childNodes[i].childNodes[2]);
                    self._holder.childNodes[i].selected = false;
                    self._holder.childNodes[i].childNodes[0].style.display = "";
                    j = i;
                }

            }
            var previousSibling = entryDiv.parentNode.previousSibling;

            entryDiv.blur();

            for(var i = 0; i < tagHolders.length; i++){
                if(tagHolders[i] == previousSibling)
                    break;
            }

            var input = self._showInput(self._holder.childNodes[j]);
self._holder.childNodes[j].focus();
        }
    });
};

/**
 * Set the fixed tag in the smart entry. Fixed tag cannot be deleted
 * @param {String} arguments Label string to be set
 */

gtk.SmartEntry.prototype.setLabel = function(){
    this._smartEntryLabelHolder = [];
    var self = this;
    for(var i = 0, len = arguments.length; i < len; i++){
        var label = arguments[i]
        var tagHolder = jsgtk.Dom.create({"tag": "div", "append": this._holder, "className": "gtk_smart_entry_label_holder"});
        var labelSpan  = jsgtk.Dom.create({"tag": "span", "append": tagHolder , "text": label, "className": "gtk_smart_entry_label"});
        var input = jsgtk.Dom.create({"append": tagHolder, "tag": "input", "type": "text", "value": "", "className": "gtk_smart_entry_input"});
        input.style.display = "none";
    }

    var tagHolders = this._holder.childNodes;
    this._smartEntryLabelHolder = tagHolders;

    for(var i = 0, len = tagHolders.length; i< len; i++){
        (function(){
            var j = i;
            jsgtk.Event.addDomListener(tagHolders[j], "click", function(){
                var entryDiv = self._showInput(tagHolders[j]);
                self._index = j;

                self._createKeypressEventForInput(entryDiv, tagHolders, self._index);

                jsgtk.Event.addDomListener(entryDiv, "blur", function(){
                    self._createTagHolder(tagHolders[j], entryDiv)

                }, false);

            }, false);
        })();
    }
};

/**
 * Set the minimum size of SmartEntry
 * @param {Integer} width the minimum width to be set
 * @param {Integer} height the minimum height to be set
 */
gtk.SmartEntry.prototype.setSize = function(width, height){
    this._width = this._minWidth = width;
    this._height = this._minHeight = height;
    this._domObj.style.width = this._width + "px";
    this._domObj.style.height = this._height + "px";

    this.emit('bubble', this._width, this._height);
};

gtk.SmartEntry.prototype.setDropDown = function(filterable, dropDown){
    var self = this;
    var fragment = document.createDocumentFragment();
    var width = this._width;
    var dom = null;

    if(filterable){
        for(var i = 0, len = dropDown.length; i < len; i ++){
            dom = jsgtk.Dom.create({"tag":"div", "append": fragment, "text": dropDown[i]});
            var textWidth = this._calculateTextWidth(dom);
            if(width < textWidth) width = textWidth;

            (function(){
                var j = i;
                jsgtk.Event.addDomListener(dom, "click", function(){
                    self._createTagFromDropDown(dropDown[j]);
                    dropDownDom.style.display = "none";
                });
            })();
        }

        var dropDownDom = this._createDropDown(fragment, width);

        jsgtk.Event.addDomListener(this._entry, "keyup", function(e){
            if(e.keyCode == gtk.UP_ARROW_KEY || e.keyCode == gtk.DOWN_ARROW_KEY) return;
            var dropDownChildren = dropDownDom.childNodes;
            var re = new RegExp("^" + self._entry.value.toLowerCase());
            var result = null;
            var results = [];

            if(self._domObj.childNodes[2]) self._domObj.removeChild(self._domObj.childNodes[2]);

            for(var k = 0, len = dropDownChildren.length; k < len; k++){
                var child = dropDownChildren[k];
                result = child.innerHTML.toLowerCase().match(re);
                if(result){
                    results.push(child.cloneNode(true));
                }
            }

            self._displayDropDownResult(results, dropDownDom);
        }, false);

        var list = self._domObj.childNodes;
        var dropDownList = list[list.length - 1].childNodes;

        jsgtk.Event.addDomListener(this._areaDom, "click", function(){
            dropDownDom.style.display = "";
            if(self._domObj.childNodes[2]) self._domObj.removeChild(self._domObj.childNodes[2]);
                self._bindDropDownMouseEvent(dropDownList);
                self._bindDropDownKeydownEvent(dropDownList, dropDown, list);
        }, false);
    }
    else{
        for(var i = 0, len = dropDown.length; i < len; i ++){
            dom = jsgtk.Dom.create({"tag":"div", "append": fragment, "text": dropDown[i]});
            var textWidth = this._calculateTextWidth(dom);
            if(width < textWidth) width = textWidth;

            (function(){
                var j = i;
                jsgtk.Event.addDomListener(dom, "click", function(){
                    self._createTagFromDropDown(dropDown[j])
                    dropDownDom.style.display = "none";
                });
            })();
        }

        var dropDownDom = this._createDropDown(fragment, width);

        jsgtk.Event.addDomListener(this._areaDom, "click", function(){
            dropDownDom.style.display = "";
            self._entry.style.display = "";
            self._entry.maxLength = "0";
        }, false);

        var list = self._domObj.childNodes
        var dropDownList = list[list.length - 1].childNodes;

        this._bindDropDownMouseEvent(dropDownList);
        this._bindDropDownKeydownEvent(dropDownList, dropDown, list);
    }
};

/** @private */
gtk.SmartEntry.prototype._bindDropDownMouseEvent = function(dropDownList){
    var self = this;

    for(var i = 0, len = dropDownList.length; i < len; i++){
        (function(){
            var j = i;
            var eventId = jsgtk.Event.addDomListener(dropDownList[j], "mouseover", function(){
                if(self._selectedIndex != -1) dropDownList[self._selectedIndex].className = "";
                self._selectedIndex = j;
                dropDownList[self._selectedIndex].className = "gtk_smart_entry_drop_down";
            });

            self._eventStorage.push(eventId);
        })();
    }
};

/** @private */
gtk.SmartEntry.prototype._bindDropDownKeydownEvent = function(dropDownList, dropDown, list){
    var self = this;
    var len = dropDownList.length;
    self._selectedIndex = -1;

    for(var i = 0; i<len; i++){
        dropDownList[i].className = "";
    }

    if(this._keyEvent) jsgtk.Event.removeListener(this._keyEvent);

    this._keyEvent = jsgtk.Event.addDomListener(this._entry, "keydown", function(e){
        if(e.keyCode == gtk.DOWN_ARROW_KEY){
            if(self._selectedIndex < len - 1){
                if(self._selectedIndex != -1) dropDownList[self._selectedIndex].className = "";
                self._selectedIndex++;
                dropDownList[self._selectedIndex].className = "gtk_smart_entry_drop_down";
            }
        }
        else if(e.keyCode == gtk.UP_ARROW_KEY){
            if(self._selectedIndex > 0) {
                dropDownList[self._selectedIndex].className = "";
                self._selectedIndex--;
                dropDownList[self._selectedIndex].className = "gtk_smart_entry_drop_down";
            }
        }

        else if(e.keyCode == gtk.ENTER_KEY){
            dropDownList[self._selectedIndex].className = "";
            self._entry.value = dropDown[self._selectedIndex];
            self._selectedIndex = -1;
            self._entry.blur();
            window.setTimeout(function(){
                self._entry.blur();
                list[list.length - 1].style.display = "none";
            }, 2);
        }
    }, false);
};

/** @private */
gtk.SmartEntry.prototype._createDropDown = function(fragment, width){
    var self = this;
    var dropDownDom = jsgtk.Dom.create({"tag": "div", "className": "gtk_smart_entry_drop_down_holder"});
    dropDownDom.appendChild(fragment);
    dropDownDom.style.width = width + "px";
    dropDownDom.style.display = "none";
    this._domObj.appendChild(dropDownDom);

    return dropDownDom;
}

/** @private */
gtk.SmartEntry.prototype._createTagFromDropDown = function(value){
    var tagHolder = jsgtk.Dom.create({"tag": "div", "append": this._holder, "className": "gtk_smart_entry_tag_holder"});
    var tag  = jsgtk.Dom.create({"tag": "span", "append": tagHolder , "text": value});
    var closeButton = jsgtk.Dom.create({"tag": "div", append: tagHolder, "className": "gtk_smart_entry_close"});

    jsgtk.Event.addDomListener(closeButton, "click", function(e){
        tagHolder.parentNode.removeChild(tagHolder);
        jsgtk.Event.stopBubble(e);
    }, false);
};

/** @private */
gtk.SmartEntry.prototype._calculateTextWidth = function(dom){
    var tempDom = dom.cloneNode(true);
    tempDom.style.display = "none";
    document.body.appendChild(tempDom);
    return jsgtk.Util.fullWidth(tempDom);
};

/** @private */
gtk.SmartEntry.prototype._displayDropDownResult = function(results, dropDownDom){
    var self = this;
    if(results){
        dropDownDom.style.display = "none";
        var resultsDom = jsgtk.Dom.create({"tag":"div", "append": this._domObj, "className": "gtk_smart_entry_drop_down_holder"});
        resultsDom.style.width = this._width + "px";

        for(var i = 0, len = this._eventStorage.length; i < len; i++){
            jsgtk.Event.removeListener(this._eventStorage[i]);
        }

        this._eventStorage = [];
        var resultList = [];
        for(var i = 0, len = results.length; i < len; i++){
            resultsDom.appendChild(results[i]);
            resultList.push(results[i].innerHTML);
            (function(){
                var j = i;
                jsgtk.Event.addDomListener(results[j], "click", function(){
                    var parent = self._domObj.childNodes[0].childNodes[0];
                    parent.removeChild(parent.childNodes[parent.childNodes.length - 1]);
                    self._createTagFromDropDown(results[j].innerHTML);
                    self._domObj.removeChild(self._domObj.childNodes[2]);
                });
            })();
        }
        this._selectedIndex = -1;
        this._bindDropDownMouseEvent(resultsDom.childNodes);
        this._bindDropDownKeydownEvent(resultsDom.childNodes, resultList, this._domObj.childNodes);
    }
};

/**
 * Add the tail to smartEntry
 * @param {String} rightTail The value of right tail to be set
 * @param {String} label (Optional) The value of label to be set in entry before tail
 */
gtk.SmartEntry.prototype.setTailLabel = function(rightTail, label){
    var self = this;
    this._isAllowOneTag = true;
    this.createFixedTag(rightTail);
    this._holder.childNodes[0].className = "gtk_smart_entry_right_label_holder";
    if(label){
        this._entry.style.display = "none";
        var tagHolder = jsgtk.Dom.create({"tag": "div", "append": this._holder, "className": "gtk_smart_entry_label_holder"});
        var labelSpan  = jsgtk.Dom.create({"tag": "span", "append": tagHolder , "text": label, "className": "gtk_smart_entry_label"});
        tagHolder.style.cssFloat = "right";

        jsgtk.Event.addDomListener(this._areaDom, "click", function(){
            if(labelSpan.style.display == "none"){
                var tag = self._holder.getElementsByClassName("gtk_smart_entry_tag_with_tail")[0]
                if(tag){
                    var value = tag.childNodes[0].innerHTML;
                    tag.parentNode.removeChild(tag);
                    self._entry.style.display = "";
                    self._entry.value = value;
                    self._entry.focus();
                }

                return;
            }
            self._entry.style.display = "";
            self._entry.style.position = "absolute";
            self._entry.style.top = "3px";
            labelSpan.style.display = "none";
            self._entry.focus();
        });
    }

    var tempWidth = this._calculateTextWidth(this._holder.childNodes[0]);
    this._entry.style.width = this._width - tempWidth - 6 + "px";
    this._entry.style.textAlign = "right";
};

/** @private */
gtk.SmartEntry.prototype._createTailTag = function(holder){
    var self = this;
    if(this._entry.value){
        var tagHolder = jsgtk.Dom.create({"tag": "div", "append": holder, "className": "gtk_smart_entry_tag_with_tail"});
        var tag  = jsgtk.Dom.create({"tag": "span", "append": tagHolder , "text": this._entry.value});

        this._entry.value = "";
        this._entry.style.display = "none";

    }else{
        this._entry.style.display = "none";
        self._holder.childNodes[1].childNodes[0].style.display = "";
    }
};

/**
 * Set the input value of smartEntry with tail
 * @param {String} value The value to be set as smartEntry tag
 */

gtk.SmartEntry.prototype.setTailInput = function(value){
    this._entry.value = value;
    if(this._holder.childNodes[1]) this._holder.childNodes[1].childNodes[0].style.display = "none";
    this._createTailTag(this._holder);
    this._entry.style.position = "absolute";
    this._entry.style.top = "3px";
};

/**
 * set the entry to accept only number
 * @param {Integer} index The index of entry to be set. set index = -1 to set all the input in smart entry to accept only number
 */
gtk.SmartEntry.prototype.setAcceptNumber = function(index){
    var self = this;

    if(index == -1){
        this._bindEntryNumberOnlyEvent(this._entry);
        return;
    }

    if(this._allowLabel){
        var indexDom = this._holder.childNodes[index];

        if(indexDom)
            var eventId = jsgtk.Event.addDomListener(indexDom, "click", function(){
                self._bindEntryNumberOnlyEvent(indexDom.childNodes[1]);
            }, false);
    }

};

/** @private */
gtk.SmartEntry.prototype._bindEntryNumberOnlyEvent = function(entry){
    var self = this;
    var value = "";
    jsgtk.Event.addDomListener(entry, "keypress", function(e){
        if (e.charCode > 31 && (e.charCode < 48 || e.charCode > 57)){
            window.setTimeout(function(){entry.value = value;}, 1);
        }
        else{
            window.setTimeout(function(){value = entry.value;}, 1);
        }
    });
    return;
};

/**
 * set the entry to accept limited characters
 * @param {Integer} index The index of entry to be set. set index = -1 to apply to all the input in smart entry
 * @param {Integer} limitedChar The limited number of characters which is abled to be type to entry
 */
gtk.SmartEntry.prototype.setLimitCharacter = function(index, limitedChar){
    var self = this;

    if(index == -1){
        this._entry.setAttribute("maxlength", limitedChar);
        return;
    }

    if(this._allowLabel){
        var indexDom = this._holder.childNodes[index];

        if(indexDom)
            var eventId = jsgtk.Event.addDomListener(indexDom, "click", function(){
                indexDom.childNodes[1].setAttribute("maxLength", limitedChar);
            }, false);
    }
};
gtk.Item = function(){
	gtk.Bin.apply(this);
	var self = this;
	this._toggle = false;

	this._render = function(){
		this._domObj.className += ' item';
	}

	this._render();
};

gtk.Item.prototype = new gtk.Bin();
gtk.Item.prototype.constructor = gtk.Item;

gtk.Item.prototype.select = function(){
	this.emit('select');
};

gtk.Item.prototype.deselect = function(){
	this.emit('deselect');
};

gtk.Item.prototype.toggle = function(){
	this.emit('toggle');
	if(this._toggle) this._toggle = false;
	else this._toggle = true;
};

gobject.signalNew('select', gtk.Button, null, null, []);
gobject.signalNew('deselect', gtk.Button, null, null, []);
gobject.signalNew('toggle', gtk.Button, null, null, []);


gtk.MenuShell = function() {
	gtk.Container.apply(this);

	this._menuItem = [];
	this._menuDomItem = [];
	this._minWidth = 20;
	this._minHeight = 20;
	this._menuItemActive = false;
	this._menuItemDeactive = true;
	this._width = this._minWidth;
	this._height = this._minHeight;
	this._selectedItem = null;
	this._render = function(){
		this._domObj.className += " gtk_menu_shell";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this.hide();
	};

	jsgtk.Event.addDomListener(this._domObj, 'click', function(){
	   console.log(2)
	}, false);

	this._render();
};

gtk.MenuShell.prototype = new gtk.Container();
gtk.MenuShell.prototype.constructor = gtk.MenuShell;

gtk.MenuShell.prototype.append = function(menuItem){
	var self = this;
	var domItem = menuItem.getNode();
	this._domObj.appendChild(domItem);
	this._menuItem.push(menuItem);
	this._menuDomItem.push(domItem);
	var childNodeLen = this._domObj.childNodes.length;
	var maxLength = this._getTheLongestChildLength(this._menuItem) + 15;
	var newHeight = menuItem._height;
	this.setSizeRequest(maxLength,newHeight);
	this.resize(maxLength,(newHeight*childNodeLen));
	for(var i = 0; i < childNodeLen; i++){
		this._menuItem[i].setSizeRequest(maxLength,newHeight);
		this._menuItem[i].resize(maxLength,newHeight);;
	}
};

gtk.MenuShell.prototype.selectItem = function(menuItem){
	var index = 0;
	for (var i = 0; i < this._menuItem.length; i++){
			if(this._menuItem[i] === menuItem) index = i;
	}
	this._selectedItem = this._menuDomItem[index];
	this._menuDomItem[index].style.backgroundColor = '#FFFF99';
	this._menuDomItem[index].style.color = '#EFB34A';
};

gtk.MenuShell.prototype.deselectItem = function(){
	this._selectedItem.style.backgroundColor = '';
	this._selectedItem.style.color = '';
};

gtk.MenuShell.prototype.deactivate = function(){
	this.hide();
};

gtk.MenuShell.prototype._getTheLongestChildLength = function(array){
	var maxLength = 0;
	for(var i = 0; i <array.length; i++){
		if(array[i]._width > maxLength){
			maxLength = array[i]._width;
		}
	}
	return maxLength;
};

gtk.MenuShell.prototype.resize = function(width,height){
	this._resizeWidth(width);
    this._resizeHeight(height);
};

/** @private */
gtk.MenuShell.prototype.resizeWidthComposite = function(width){
    this.setWidth(width);
    this.resize(this._width, this._height);
};

/** @private */
gtk.MenuShell.prototype.resizeHeightComposite = function(height){
    this.setHeight(height);
    this.resize(this._width, this._height);
};

gobject.signalNew("activatemenu", gtk.MenuShell, null, null, []);
gobject.signalNew("deactivatemenu", gtk.MenuShell, null, null, []);

gtk.Menu = function() {
	gtk.Container.apply(this);

	this._menuItems        = [];
	this._separatorDoms     = [];
	this._minWidth         = 20;
	this._minHeight        = 20;
	this._menuItemActive   = false;
	this._menuItemDeactive = true;
	this._isActive         = false;
	this._width            = this._minWidth;
	this._height           = this._minHeight;
	this._selectedItem     = null;
	this._cellHeight       = 22;
	this._zIndex           = 9000;
	this._render = function(){
		this._domObj.className += " gtk_menu_shell";
		this._domObj.style.width = this._width + 'px';
		this._domObj.style.height = this._height + 'px';
		this._domObj.style.zIndex = this._zIndex;
		this._domObj.style.position = "absolute";
		this.hide();
	};

	this._render();
};

gtk.Menu.prototype = new gtk.Container();
gtk.Menu.prototype.constructor = gtk.Menu;

gtk.Menu.prototype.append = function(menuItem){
	var self = this;
	var domItem = menuItem.getNode();
	var separatorMargin = 0;
	this._domObj.appendChild(domItem);

	this._menuItems.push(menuItem);
	this._minWidth  = this._getMaxChildWidth();

	if(this._separatorDoms.length > 0){
		separatorMargin = (3 * this._separatorDoms.length) ;
	}

	this._minHeight = (this._cellHeight * this._menuItems.length) + separatorMargin;

	this.resize(this._minWidth, this._minHeight);

	menuItem.connect("menuitemmouseovered", function(){
        self._hideSubMenu(menuItem);
	})
};

gtk.Menu.prototype.selectItem = function(menuItem){
	var index = 0;
	for (var i = 0; i < this._menuItems.length; i++){
			if(this._menuItems[i] === menuItem) index = i;
	}
	this._selectedItem = this._menuItems[index].getNode();
	this._selectedItem.style.backgroundColor = '#FFDD00';
};

gtk.Menu.prototype.deselectItem = function(){
	this._selectedItem.style.backgroundColor = '';
	this._selectedItem.style.color = '';
    this._selectedItem = null;
};

gtk.Menu.prototype.deactivate = function(){
	this.hide();
};

gtk.Menu.prototype.addSeparator = function(){
	var separator = jsgtk.Dom.create({'append':this._domObj, 'tag' : 'div'});
	separator.className += ' separator';
	this._separatorDoms.push(separator);
};

gtk.Menu.prototype._getMaxChildWidth = function(){
	var maxWidth = 0;
	for(var i = this._menuItems.length; i--;){
	    var itemWidth = this._menuItems[i].getMinWidthComposite();
		if(itemWidth > maxWidth) maxWidth = itemWidth;
	}
	return maxWidth;
};

gtk.Menu.prototype.resize = function(width,height){
	this._resizeWidth(width);
    this._resizeHeight(height);

    for(var i = this._menuItems.length; i--;){
        var item = this._menuItems[i];
        item.resizeWidthComposite(width);
    }
};

gtk.Menu.prototype._hideSubMenu = function(menuItem){
    var subMenu;
    for(var i = 0, len = this._menuItems.length; i < len; i++){
        var item = this._menuItems[i];
        if(item !== menuItem){
            subMenu = item.getSubMenu();
            if(subMenu) subMenu.hideMenuComposite();
        }
    }
}

gtk.Menu.prototype.hideMenuComposite = function(){
    var subMenu;
    this.hide();
    for(var i = this._menuItems.length; i--;){
        var item = this._menuItems[i];
        subMenu = item.getSubMenu();
        if(subMenu) subMenu.hideMenuComposite();
    }
};

gtk.Menu.prototype.showMenuComposite = function(){
    var subMenu;
    this.show();
    for(var i = this._menuItems.length; i--;){
        var item = this._menuItems[i];
        subMenu = item.getSubMenu();
        if(subMenu) subMenu.showMenuComposite();
    }
};

gtk.Menu.prototype.anchorTo = function(x,y, index){
    index = index || 0;
    this.show();
    var left,top;

    this._zIndex += index;
    this._domObj.style.zIndex = this._zIndex;

    var windowWidth = jsgtk.Util.getWindowWidth();
    var newX = windowWidth - x;

    if(this._width > newX) left = x - this._width;
    else left = x;

    var windowHeight = jsgtk.Util.getWindowHeight();
    var newY = windowHeight - y;

    if(this._height > newY) top = y - this._height;
    else top = y;

    this._domObj.style.top = top + "px";
    this._domObj.style.left = left + "px";
}

/** @private */
gtk.Menu.prototype.resizeWidthComposite = function(width){
    var minWidth = this._minWidth < width ? width : this._minWidth;
    this.resize(minWidth, this._height);
};

/** @private */
gtk.Menu.prototype.resizeHeightComposite = function(height){
    var minHeight = this._minHeight < height ? height : this._minHeight;
    this.resize(this._width, minHeight);
};

gobject.signalNew("activatemenu", gtk.Menu, null, null, []);
gobject.signalNew("deactivatemenu", gtk.Menu, null, null, []);
gtk.MenuItem = function(img, label){
	gtk.Item.apply(this);
    var self = this;
    this._width            = this._minWidth  = 50;
    this._height           = this._minHeight = 22;
    this._imageWidgetWidth = 16;
	this._imageWidget      = img || null;
    this._labelWidget      = label || null;
	this._toggle           = false;
	this._domMenuItemLabel = null;
	this._isSubMenu        = false;
	this._subMenu          = null;
	this._callBack		   = function(){};
	this._leftPadding      = 5;
	this._rightPadding     = 10;
	this._labelPadding     = 5;

	this._render = function(){
		this._domObj.className += ' menu_item';
		this._domObj.style.width = this._width + "px";
		this._domObj.style.height = this._height + "px";

		this._appendChildren();
	}

	this._render();

	jsgtk.Event.addDomListener(this._domObj,'mouseover',function(e){
	    self.emit("menuitemmouseovered", self);
	    jsgtk.Event.stopBubble(e);
	    if(self._subMenu){
	        self._subMenu.show();
	        var menuItems = this.parentNode.childNodes;
		    var left = ( parseInt(this.parentNode.style.left) || 0) + parseInt(this.style.width) + 6;
		    var parentTop  = parseInt(this.parentNode.style.top);
		    var index;

		    var windowWidth = jsgtk.Util.getWindowWidth();
			var windowHeight = jsgtk.Util.getWindowHeight();
		    var newLeft = windowWidth - left;
		    var subMenuWidth = self._subMenu.getMinWidthComposite();
			var subMenuHeight = self._subMenu.getMinHeightComposite();

	        for(var i = 0; i < menuItems.length; i++){
	            if(self._domObj === menuItems[i]) index = i;
	        }

            var top = self._height * index + parentTop;
			var newTop = windowHeight - top;
			if(newLeft < subMenuWidth){
		        left = (parseInt(this.parentNode.style.left) || 0) - subMenuWidth;
		    }
			if(newTop < subMenuHeight){
				top = (windowHeight || 0) - subMenuHeight;
			}
		    self._subMenu.anchorTo(left-3, top-3, 1);

	    }
	}, false);

	jsgtk.Event.addDomListener(this._domObj, 'click', function(e){
		self.emit("activateitem");
		jsgtk.Event.stopBubble(e);
	}, false);
};

gtk.MenuItem.prototype = new gtk.Item();
gtk.MenuItem.prototype.constructor = gtk.MenuItem;

gtk.MenuItem.prototype._appendChildren = function(){
    var width = this._labelWidget.getMinWidthComposite() + this._imageWidgetWidth + this._leftPadding + this._rightPadding + this._labelPadding;
    this._minWidth = width > this._minWidth ? width : this._minWidth;
    this.resize(this._minWidth, this._minHeight);

    if(this._imageWidget) {
        var imageNode = this._imageWidget.getNode();
        imageNode.style.left = this._leftPadding + "px";
        imageNode.style.top  = "2px";
        this._domObj.appendChild(imageNode);
    }

    var labelNode = this._labelWidget.getNode();
    this._domObj.appendChild(labelNode);
    labelNode.style.position = "absolute";
    labelNode.style.left = this._leftPadding + this._imageWidgetWidth + this._labelPadding + "px";
    labelNode.style.top  = "1px";
};

gtk.MenuItem.prototype.setSubMenu = function(menu){
	var self = this;
	this._isSubMenu = true;
	this._subMenu = menu;

	this._subMenu.getNode().className += ' sub_menu';
	document.body.appendChild(this._subMenu.getNode());

	this._imageSubMenu = jsgtk.Dom.create({'append' : this._domObj, 'tag' : 'img', 'src' : '../../src/images/test/toSubmenu.png'});
	this._imageSubMenu.className = 'image_sub_menu';
	this._imageSubMenu.style.left = parseInt(this._domObj.style.width) - 10 + "px";
};

gtk.MenuItem.prototype._setSubMenuImage = function(imagePath){
	this._imageSubMenu.src = imagePath;
};

gtk.MenuItem.prototype.getSubMenu = function(){
    return this._subMenu;
};

gtk.MenuItem.prototype.resize = function(width, height){
	this._resizeWidth(width);
	this._resizeHeight(height);
};

gtk.MenuItem.prototype.removeSubMenu = function(){
	document.body.removeChild(this._subMenu.getNode());
	this._domObj.removeChild(this._imageSubMenu);
	this._subMenu = null;
};

gtk.MenuItem.prototype.activateItem = function(callback){
	this._callBack = callback;
	this.connect('activateitem', function(){
		callback();
	});
};

gtk.MenuItem.prototype._setImage = function(img){

}

gtk.MenuItem.prototype._setText = function(text){
	this._text = text;
	this._domMenuItemLabel.innerHTML = text;
	var size = this._calculateMinWidthMinHeight();
	this._minWidth = this._width = size[0];
	this._minHeight = this._height = size[1];
	this.resize(size[0], size[1]);
	this.emit("bubble", this._width, this._height);
};

/** @private */
gtk.MenuItem.prototype.resizeWidthComposite = function(width){
    var minWidth = width > this._minWidth ? width : this._minWidth;
    this.resize(minWidth, this._height);
};

gobject.signalNew("menuitemmouseovered", gtk.MenuItem, null, null, []);
gobject.signalNew("activateitem", gtk.MenuItem, null, null, []);


Documentation generated by JSDoc on Thu Jan 21 18:07:55 2010