function ProcessColumn(x, y, w, h) {
	//Основной прямоугольник
	var rAll = new Rectangle(x, y, w, h);
	//Массив элементов под статусы
	var rStat = [];
	//Массив элементы под коэффициенты
	var point = [];
	//Проценты статуса
	var percent = 0;
	//Номер статуса
	var status = -1;
	/*Проценты поднимаются снизу вверх (false)
	 *или слева направо (true)*/
	var rotate = false;
	/*Функции для работы с координатами
	* основного прямоугольника */
	this.X = function (val) {
		if (val === undefined) return rAll().X();
		rAll().X(val);
	};
	this.Y = function (val) {
		if (val === undefined) return rAll().Y();
		rAll().Y(val);
	};
	this.W = function (val) {
		if (val === undefined) return rAll().W();
		rAll().W(val);
	};
	this.H = function (val) {
		if (val === undefined) return rAll().H();
		rAll().H(val);
	};
	//Установка процента от 0 до 100
	this.Percent = function (val) {
		if (val === undefined) return percent;
		var v = parseFloat(val);
		percent = (isNaN(v) || v < 0) ? 0 :
			(v > 100) ? 100 : v;
	};
	//Установка статуса от 0 до (кол-во элементов в массиве статусов - 1)
	this.Status = function (val) {
		if (val === undefined) return status;
		var v = parseInt(val);
		status = (isNaN(v) || v < -1 || rStat.length === 0) ? -1 :
			(v >= rStat.length) ? (rStat.length - 1) : v;
	};
	//Функция изменения начальной координаты и размеров прямоугольника
	this.RectParam = function (_x, _y, _w, _h) {
		rAll.RectParam(_x, _y, _w, _h);
	};
	//Функция изменения прямоугольника по другому прямоугольнику
	this.Rect = function (val) {
		if (val === undefined) return rAll;
		rAll.Rect(val);
	};
	//Изменение направления отрисовки процентов
	this.Rotate = function (val) {
		if (val === undefined) return rotate;
		rotate = (typeof val === 'boolean') ? val : false;
		for (var i = 0; i < rStat.length; i++)
			rStat[i].Rotate(rotate);
	};
	//Количество статусов
	this.StatCount = function () {
		return rStat.length;
	};
	//Установка коеффициента
	function Point(_index, _point) {
		var idx = parseInt(_index);
		var pnt = parseFloat(_point);
		if (!isNaN(idx)) {
			while (idx >= point.length)
				point.push(1);
			point[idx] = isNaN(pnt) || pnt <= 0 ? 1 : pnt;
		}
	}
	//Установка нового статуса
	this.AddRStat = function (index, point, color) {
		var idx = parseInt(index);
		if (isNaN(idx) || idx < 0 || idx - 1 > rStat.length) {
			rStat.push(new PercentColumn());
			idx = rStat.length - 1;
		}
		else
			rStat.splice(idx, 0, new PercentColumn());
		rStat[idx].Color(color);
		Point(idx, point);
	};
	//Изменение статуса
	this.ChangeRStat = function (index, point, color) {
		var idx = parseInt(index);
		if (!isNaN(idx) && idx >= 0 && idx < rStat.length) {
			rStat[idx].Color(color);
			Point(idx, point);
		}
	};
	//Удаление статуса
	this.DelRStat = function (index) {
		var idx = parseInt(index);
		if (!isNaN(idx) && idx >= 0 && idx < rStat.length) {
			rStat.splice(idx, 1);
			point.splice(idx, 1);
		}
		else if (rStat.length > 0) {
			rStat.pop();
			point.pop();
		}
	};
	//Заполнение столбца процесса по умолчанию
	this.BuildDefault = function () {
		var defaultPoint = [57, 49, 49, 71, 28, 49, 21, 171, 114, 103];
		var defaultColor = ["#0ff", "#00f", "#f00", "#0f0", "#0ff", "#00f", "#8500b6", "#f00", "#f0f", "#0f0"];
		while (rStat.length > 0)
			this.DelRStat();
		for (var i = 0; i < defaultPoint.length; i++)
			this.AddRStat(i, defaultPoint[i], defaultColor[i]);
	};
	//Сумма всех коэффициентов
	function AllPoint() {
		var count = 0;
		for (var i = 0; i < point.length; i++)
			count += point[i];
		return count;
	}
	//
	function PointSize() {
		var res = ((rotate) ? rAll.W() : rAll.H()) - (1 + rStat.length);
		res = (res < 0) ? 0 : res;
		return (AllPoint() <= 0) ? 0 : (res / AllPoint());
	}
	//Перерасчет статусов и процентов
	function Restat() {
		for (var i = 0; i < rStat.length; i++) {
			rStat[i].Percent(i < status ? 100 : i == status ? percent : 0);
		}
	}
	//Перерасчет размеров статусов
	function Rebuild() {
		var _x = rAll.X() + 1;
		var _y = rAll.Y() + 1;

		for (var i = 0; i < rStat.length; i++) {
			var currStat = (rotate) ? i : rStat.length - (i + 1);
			var _w = (!rotate) ? rAll.W() - 2 : point[currStat] * PointSize();
			var _h = (rotate) ? rAll.H() - 2 : point[currStat] * PointSize();
			rStat[currStat].RectParam(_x, _y, _w, _h);
			_x = (!rotate) ? _x : _x + 1 + _w;
			_y = (rotate) ? _y : _y + 1 + _h;
		}
	}
	//Печать столбца процесса
	this.Print = function (ctx) {
		this.Rotate(rotate);
		Restat();
		Rebuild();
		ctx.clearRect(rAll.X(), rAll.Y(), rAll.W(), rAll.H());
		ctx.fillStyle = '#ddd';
		ctx.fillRect(rAll.X(), rAll.Y(), rAll.W(), rAll.H());
		for (var i = 0; i < rStat.length; i++)
			if (i <= status)
				rStat[i].Print(ctx);
		ctx.strokeStyle = '#000'; //'#333'
		ctx.strokeRect(rAll.X(), rAll.Y(), rAll.W(), rAll.H());
	};
	//Печать текста столбца процесса
	this.PrintText = function (ctx) {
		this.Rotate(rotate);
		Restat();
		Rebuild();
		ctx.save();
		ctx.translate(rAll.X() + rAll.W() / 2, rAll.Y() + rAll.H() / 2);
		if (!rotate) ctx.rotate(3 * Math.PI / 2);
		ctx.fillStyle = '#888';
		ctx.textAlign = 'center';
		ctx.textBaseline = 'middle';
		if (!rotate)
			ctx.font = (rAll.W() - 10 < 0 ? 0 : rAll.W() - 10) + 'px Arial';
		else
			ctx.font = (rAll.H() - 10 < 0 ? 0 : rAll.H() - 10) + 'px Arial';
		ctx.fillText((Math.floor(percent * 100) / 100) + '% ' + (status + 1) + '/' + rStat.length, 0, 0);
		ctx.restore();
	};
}