function areaBox(_onModify, _unit = noone) : widget() constructor {
	onModify = _onModify;
	unit	 = _unit;
	onSurfaceSize = -1;
	
	link_value	 = false;
	current_data = [ 0, 0, 0, 0 ];
	adjust_shape = true;
	mode		 = AREA_MODE.area;
	tooltip		 = new tooltipSelector("Area type", [
		__txtx("widget_area_center_Span", "Center + Span"),
		__txtx("widget_area_padding",     "Padding"),
		__txtx("widget_area_two_points",  "Two points"),
	]);
	
	onModifySingle[0] = function(val) {
		var v = toNumber(val);
		var m = onModify(v, 0);
		
		if(mode == AREA_MODE.area || mode == AREA_MODE.two_point || !link_value) 
			return m;
		
		m |= onModify(v, 1);
		m |= onModify(v, 2);
		m |= onModify(v, 3);
		
		return m;
	}
	
	onModifySingle[1] = function(val) {
		var v = toNumber(val);
		var m = onModify(v, 1);
		
		if(mode == AREA_MODE.area || mode == AREA_MODE.two_point || !link_value) 
			return m;
		
		m |= onModify(v, 0);
		m |= onModify(v, 2);
		m |= onModify(v, 3);
		
		return m;
	}
	
	onModifySingle[2] = function(val) {
		var v = toNumber(val);
		var m = onModify(v, 2);
		
		if(mode == AREA_MODE.area || mode == AREA_MODE.two_point || !link_value) 
			return m;
		
		m |= onModify(v, 0);
		m |= onModify(v, 1);
		m |= onModify(v, 3);
		
		return m;
	}
	
	onModifySingle[3] = function(val) {
		var v = toNumber(val);
		var m = onModify(v, 3);
		
		if(mode == AREA_MODE.area || mode == AREA_MODE.two_point || !link_value) 
			return m;
		
		m |= onModify(v, 0);
		m |= onModify(v, 1);
		m |= onModify(v, 2);
		
		return m;
	}
	
	for(var i = 0; i < 4; i++) {
		tb[i] = new textBox(TEXTBOX_INPUT.number, onModifySingle[i]);
		tb[i].slidable = true;
		tb[i].hide     = true;
	}
	
	static setInteract = function(interactable = noone) {
		self.interactable = interactable;
		for(var i = 0; i < 4; i++) 
			tb[i].interactable = interactable;
	}
	
	static register = function(parent = noone) {
		switch(mode) {
			case AREA_MODE.two_point :
			case AREA_MODE.area :	   
				for(var i = 0; i < 4; i++) 
					tb[i].register(parent);
				break;
			case AREA_MODE.padding : 
				tb[1].register(parent);
				tb[2].register(parent);
				tb[0].register(parent);
				tb[3].register(parent);
				break;
		}
		
		if(unit != noone && unit.reference != noone)
			unit.triggerButton.register(parent);
	}
	
	static isHovering = function() {
		for( var i = 0, n = array_length(tb); i < n; i++ ) if(tb[i].isHovering()) return true;
		return false;
	}
	
	static drawParam = function(params) {
		setParam(params);
		for(var i = 0; i < 4; i++) tb[i].setParam(params);
		
		return draw(params.x, params.y, params.w, params.h, params.data, params.display_data, params.m);
	}
	
	static draw = function(_x, _y, _w, _h, _data, _display_data, _m) { 
		x = _x;
		y = _y;
		w = _w;
		h = _h * 2 + ui(4);
		mode = array_safe_get_fast(_data, 5);
		
		onSurfaceSize = struct_try_get(_display_data, "onSurfaceSize", -1);
		useShape      = struct_try_get(_display_data, "useShape", true);
		
		var _bs = min(_h, ui(32));
		var _bx   = _x;
		var _by   = _y + _h / 2 - _bs / 2;
		var _bact = adjust_shape && active;
		var _bhov = adjust_shape && hover;
		var _bind = array_safe_get_fast(_data, 4);
		  
		if(_w - _bs > ui(100) && onSurfaceSize != -1) {
			tooltip.index = mode;
			
			if(unit != noone && unit.reference != noone) {
				var _bx   = _x + _w - _bs;
				var _by   = _y + h / 2 - _bs / 2;
			
				unit.triggerButton.setFocusHover(iactive, ihover);
				unit.draw(_bx, _by, _bs, _bs, _m);
				
				_w -= _bs + ui(4);
			}
		
			var _bx   = _x + _w - _bs;
			var _by   = _y + _h / 2 - _bs / 2;
			
			if(buttonInstant(THEME.button_hide, _bx, _by, _bs, _bs, _m, active, hover, tooltip, THEME.inspector_area_type, mode) == 2) { 
				switch(mode) {
					case AREA_MODE.area : //area to padding
						var cx = array_safe_get_fast(_data, 0);
						var cy = array_safe_get_fast(_data, 1);
						var sw = array_safe_get_fast(_data, 2);
						var sh = array_safe_get_fast(_data, 3);
						var ss = unit.mode == VALUE_UNIT.reference? [ 1, 1 ] : onSurfaceSize();
						
						onModify(ss[0] - (cx + sw), 0);
						onModify(cy - sh,           1);
						onModify(cx - sw,           2);
						onModify(ss[1] - (cy + sh), 3);
						break;
						
					case AREA_MODE.padding : //padding to two points
						var r  = array_safe_get_fast(_data, 0);
						var t  = array_safe_get_fast(_data, 1);
						var l  = array_safe_get_fast(_data, 2);
						var b  = array_safe_get_fast(_data, 3);
						var ss = unit.mode == VALUE_UNIT.reference? [ 1, 1 ] : onSurfaceSize();
						
						onModify(l,         0);
						onModify(t,         1);
						onModify(ss[0] - r, 2);
						onModify(ss[1] - b, 3);
						break;
						
					case AREA_MODE.two_point : //twp points to area
						var x0 = array_safe_get_fast(_data, 0);
						var y0 = array_safe_get_fast(_data, 1);
						var x1 = array_safe_get_fast(_data, 2);
						var y1 = array_safe_get_fast(_data, 3);
						
						onModify(   (x0 + x1) / 2, 0);
						onModify(   (y0 + y1) / 2, 1);
						onModify(abs(x0 - x1) / 2, 2);
						onModify(abs(y0 - y1) / 2, 3);
						break;
				}
				
				onModify((mode + 1) % 3, 5);
			} 
			
			var _bx   = _x + _w - _bs;
			var _by   = _y + _h + ui(4) + _h / 2 - _bs / 2;
			var _btxt = __txtx("widget_area_fill_surface", "Fill surface");
			
			if(buttonInstant(THEME.button_hide, _bx, _by, _bs, _bs, _m, active, hover, _btxt, THEME.fill, 0) == 2) { 
				var cnvt = unit != noone && unit.mode == VALUE_UNIT.reference;
				
				switch(mode) {
					case AREA_MODE.area :
						var ss = onSurfaceSize();
						onModify(cnvt? 0.5 : ss[0] / 2, 0);
						onModify(cnvt? 0.5 : ss[1] / 2, 1);
						onModify(cnvt? 0.5 : ss[0] / 2, 2);
						onModify(cnvt? 0.5 : ss[1] / 2, 3);
						break;
					case AREA_MODE.padding :   
						var ss = onSurfaceSize();
						onModify(0, 0);
						onModify(0, 1);
						onModify(0, 2);
						onModify(0, 3);
						break;
					case AREA_MODE.two_point : 
						var ss = onSurfaceSize();
						onModify(0,               0);
						onModify(0,               1);
						onModify(cnvt? 1 : ss[0], 2);
						onModify(cnvt? 1 : ss[1], 3);
						break;
				}
			} 
			
			_w -= _bs + ui(4);
		} 
		
		if(_w - _bs > ui(100)) { 
			var _bx   = _x;
			var _by   = _y + _h / 2 - _bs / 2;
				
			if(useShape && !is_array(_bind) && buttonInstant(THEME.button_hide, _bx, _by, _bs, _bs, _m, _bact, _bhov,, THEME.inspector_area, _bind) == 2) {
				var val = (array_safe_get_fast(_data, 4) + 1) % 2;
				onModify(val, 4);
			}
		  
			if(mode == AREA_MODE.padding) {
				var cc    = link_value? COLORS._main_accent : COLORS._main_icon;
				var _btxt = __txt("Link values");
				var _bby  = useShape? _by + _h + ui(4) : _y + h / 2 - _bs / 2;
			
				if(buttonInstant(THEME.button_hide, _bx, _bby, _bs, _bs, _m, active, hover, _btxt, THEME.value_link, link_value, cc) == 2)
					link_value = !link_value;
			}
			
			if(useShape || mode == AREA_MODE.padding) {
				_w -= _bs + ui(4);
				_x +=_bs + ui(4);
			}
			
		} 
		
		draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, boxColor, 1);
		draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, boxColor, 0.5 + 0.5 * interactable);	
		
		draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y + _h + ui(4), _w, _h, boxColor, 1);
		draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y + _h + ui(4), _w, _h, boxColor, 0.5 + 0.5 * interactable);	
		
		for(var i = 0; i < 4; i++)
			tb[i].setFocusHover(active, hover);
		
		current_data = _data;
		
		var tb_w = _w / 2;
		var tb_h = _h;
			
		if(mode == AREA_MODE.area) { 
			var tb_x0 = _x;
			var tb_y0 = _y;
			
			var tb_x1 = _x + tb_w;
			var tb_y1 = _y + _h + ui(4);
			
			tb[0].label = "x";
			tb[1].label = "y";
						  
			tb[2].label = "w";
			tb[3].label = "h";
			
			tb[0].draw(tb_x0, tb_y0, tb_w, tb_h, array_safe_get_fast(_data, 0), _m);
			tb[1].draw(tb_x1, tb_y0, tb_w, tb_h, array_safe_get_fast(_data, 1), _m);
		
			tb[2].draw(tb_x0, tb_y1, tb_w, tb_h, array_safe_get_fast(_data, 2), _m);
			tb[3].draw(tb_x1, tb_y1, tb_w, tb_h, array_safe_get_fast(_data, 3), _m);
		
		
		} else if(mode == AREA_MODE.padding) { 
			var tb_lx = _x;
			var tb_ly = _y;
			
			var tb_rx = _x + tb_w;
			var tb_ry = _y;
			
			var tb_tx = _x;
			var tb_ty = _y + _h + ui(4);
			
			var tb_bx = _x + tb_w;
			var tb_by = _y + _h + ui(4);
			
			tb[2].label = "l";
			tb[0].label = "r";
						   
			tb[1].label = "t";
			tb[3].label = "b";
			
			tb[2].draw(tb_lx, tb_ly, tb_w, tb_h, array_safe_get_fast(_data, 2), _m);
			tb[0].draw(tb_rx, tb_ry, tb_w, tb_h, array_safe_get_fast(_data, 0), _m);
			
			tb[1].draw(tb_tx, tb_ty, tb_w, tb_h, array_safe_get_fast(_data, 1), _m);
			tb[3].draw(tb_bx, tb_by, tb_w, tb_h, array_safe_get_fast(_data, 3), _m);
		
		
		} else if(mode == AREA_MODE.two_point) { 
			var tb_x0 = _x;
			var tb_y0 = _y;
			
			var tb_x1 = _x + tb_w;
			var tb_y1 = _y + _h + ui(4);
			
			tb[0].label = "x0";
			tb[1].label = "y0";
						   
			tb[2].label = "x1";
			tb[3].label = "y1";
			
			tb[0].draw(tb_x0, tb_y0, tb_w, tb_h, array_safe_get_fast(_data, 0), _m);
			tb[1].draw(tb_x1, tb_y0, tb_w, tb_h, array_safe_get_fast(_data, 1), _m);
		
			tb[2].draw(tb_x0, tb_y1, tb_w, tb_h, array_safe_get_fast(_data, 2), _m);
			tb[3].draw(tb_x1, tb_y1, tb_w, tb_h, array_safe_get_fast(_data, 3), _m);
		
		}
		
		resetFocus();
		
		return h;
	} 
	
	static clone = function() { 
		var cln = new areaBox(onModify, unit);
		
		return cln;
	} 
}