function Diagram(x, y, w, h) { // \|/Константы для расчетов\|/ // //Расстояние между столбцами var stI = 2; //Расстояние между элементами var stE = 2; //Минимальная ширина столбца var szE = 4; //Высота мигалки var szB = 10; //Высота номера var szN = 17; //Минимальная высота статуса var szP = 40; //Интервал обновления var timeCycle = 1000; // /|\Константы для расчетов/|\ // //Основной прямоугольник var rAll = new Rectangle(x, y, w, h); //Массив элементов под процессы var rProc = []; //Массив элементов под мигалки var rBlink = []; //Массив элементов под номера var rNumb = []; //Массив элементов под время начала процесса var rDStart = []; //Массив элементов под время конца процесса var rDEnd = []; //Флаг поворения цикла var cCycle = false; //Индекс цикла для управления var wCycle = -1; /*Проценты поднимаются снизу вверх (false) *или слева направо (true)*/ var rotate = false; //Расчет минимальной ширины this.minBoardW = function () { return (stW + 1) * (rProc.length + 1) + (rProc.length * 5); }; //Расчет минимальной высоты this.minBoardH = function () { return (stH + 1) * 4 + szHP + szHB + szHN; }; /*Функции для работы с координатами * основного прямоугольника */ 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); }; //Функция изменения начальной координаты и размеров прямоугольника 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.ProcCount = function () { return rProc.length; }; //Установка нового процесса this.AddProc = function (index, proc, blink, numb) { var idx = parseInt(index); idx = (isNaN(idx) || idx < 0 || idx >= rProc.length) ? -1 : idx; var date = new Date(); if (idx == -1) { rProc.push(proc); rBlink.push(blink); rNumb.push(numb); rDStart.push(date); rDEnd.push(date); } else { rProc.splice(idx, 0, proc); rBlink.splice(idx, 0, blink); rNumb.splice(idx, 0, numb); rDStart.splice(idx, 0, date); rDEnd.splice(idx, 0, date); } }; //Изменение процесса this.ChangeProc = function (index, proc, blink, numb) { var idx = parseInt(index); idx = (isNaN(idx) || idx < 0 || idx >= rProc.length) ? -1 : idx; var date = new Date(); if (idx == -1) return; rProc.splice(idx, 1, proc); rBlink.splice(idx, 1, blink); rNumb.splice(idx, 1, numb); rDStart.splice(idx, 1, date); rDEnd.splice(idx, 1, date); }; //Удаление процесса this.DelStove = function (index) { if (rProc.length == 0) return; var idx = parseInt(index); idx = (isNaN(idx) || idx < 0 || idx >= rProc.length) ? -1 : idx; if (idx == -1) { rProc.pop(); rBlink.pop(); rNumb.pop(); rDStart.pop(); rDEnd.pop(); } else { rProc.splice(idx, 1); rBlink.splice(idx, 1); rNumb.splice(idx, 1); rDStart.splice(idx, 1); rDEnd.splice(idx, 1); } }; //Установка времени начала процесса this.StartDate = function (index, date) { var idx = parseInt(index); idx = (isNaN(idx) || idx < 0 || idx >= rDStart.length) ? -1 : idx; if (idx == -1) return; rDStart[idx] = date; }; //Установка времени конца процесса this.EndDate = function (index, date) { var idx = parseInt(index); idx = (isNaN(idx) || idx < 0 || idx >= rDStart.length) ? -1 : idx; if (idx == -1) return; rDEnd[idx] = date; }; //Изменение параметров процесса this.ChangeStatProc = function (index, stat, percent) { var idx = parseInt(index); if (!isNaN(idx) && idx >= 0 && idx < rProc.length) { rProc[idx].Status(stat); rProc[idx].Percent(percent); } }; //Изменение параметров мигалки this.ChangeStatBlink = function (index, stat) { var idx = parseInt(index); if (!isNaN(idx) && idx >= -1 && idx < rBlink.length) rBlink[idx].Status(stat); }; //Изменение параметров номера this.ChangeStatNumb = function (index, prostoy) { var idx = parseInt(index); if (!isNaN(idx) && idx >= 0 && idx < rNumb.length) rNumb[idx].Prostoy(prostoy); }; //Изменение направления отрисовки процентов this.Rotate = function (val) { if (val === undefined) return rotate; rotate = (typeof val === 'boolean') ? val : false; for (var i = 0; i < rProc.length; i++) { rProc[i].Rotate(rotate); rNumb[i].Rotate(rotate); rBlink[i].Rotate(rotate); } }; //Заполнение диаграммы по умолчанию this.BuildDefault = function () { while (rProc.length < 48) { rProc.push(new ProcessColumn(0, 0, 0, 0)); rProc[rProc.length - 1].BuildDefault(); rBlink.push(new BlinkStatus(0, 0, 0, 0)); rBlink[rProc.length - 1].BuildDefault(); rNumb.push(new NumberColumn(0, 0, 0, 0, rProc.length)); var date = new Date; rDStart.push(date); rDEnd.push(date); } }; //Перерасчет this.Rebuild = function () { var x = rAll.X() + stE + 1; var y = rAll.Y() + stE + 1; var wAll = rAll.W() - (rProc.length + 1) * (stE + 1); var hAll = rAll.H() - (rProc.length + 1) * (stE + 1); for (var i = 0; i < rProc.length; i++) { var xP = 0, xB = 0, xN = 0; var yP = 0, yB = 0, yN = 0; var wP = 0, wB = 0, wN = 0; var hP = 0, hB = 0, hN = 0; if (!rotate) { xP = x; xB = x; xN = x; var w = Math.ceil(wAll / (rProc.length - i)); w = (w < szE) ? szE : w; wAll -= w; wP = w; wB = w; wN = w; hB = szB; hN = szN; hP = rAll.H() - (stI + 1) * 4 - szB - szN; hP = (hP < szP) ? szP : hP; yP = y; yB = yP + hP + (stI + 1); yN = yB + szB + (stI + 1); } else { yP = y; yB = y; yN = y; var h = Math.ceil(hAll / (rProc.length - i)); h = (h < szE) ? szE : h; hAll -= h; hP = h; hB = h; hN = h; wB = szB; wN = szN; wP = rAll.W() - (stI + 1) * 4 - szB - szN; wP = (wP < szP) ? szP : wP; xP = x; xB = xP + wP + (stI + 1); xN = xB + szB + (stI + 1); xN = x; xB = xN + wN + (stI + 1); xP = xB + szB + (stI + 1); } rProc[i].RectParam(xP, yP, wP, hP); rBlink[i].RectParam(xB, yB, wB, hB); rNumb[i].RectParam(xN, yN, wN, hN); if (!rotate) x += wP + stE + 1; else y += hP + stE + 1; } }; //Печать this.Print = function (a) { updateCycle(); this.Rotate(rotate); this.Rebuild(); a.clearRect(rAll.X(), rAll.Y(), rAll.W(), rAll.H()); a.fillStyle = "#ddd"; a.fillRect(rAll.X(), rAll.Y(), rAll.W(), rAll.H()); for (var i = 0; i < rProc.length; i++) { rProc[i].Print(a); rBlink[i].Print(a); rNumb[i].Print(a); } a.strokeStyle = "#333"; a.strokeRect(rAll.X(), rAll.Y(), rAll.W(), rAll.H()); }; //Печать текста this.PrintText = function (a) { for (var i = 0; i < rProc.length; i++) { rProc[i].PrintText(a); rBlink[i].PrintText(a); } }; //Обновление процентов function updateCycle(currDate) { var date = (currDate == undefined) ? new Date() : currDate; var cycle = false; for (var i = 0; i < rProc.length; i++) { if (rDStart[i] == rDEnd[i]) continue; var d = rDEnd[i] - rDStart[i]; var t = date - rDStart[i]; d = 100 * (date - rDStart[i]) / d; rProc[i].Percent(d); rNumb[i].Prostoy(d >= 100); cycle = cycle || d < 100; } cCycle = cCycle && cycle; date.setMilliseconds(date.getMilliseconds() + timeCycle); if (cCycle) if (currDate == undefined) wCycle = setTimeout(updateCycle, timeCycle); else wCycle = setTimeout(updateCycle, timeCycle, date); }; //Запуск цикла обновлений процентов this.Cycle = function (start, currDate) { if (start == undefined || !(typeof start === 'boolean')) return cCycle; if (start) { this.CheckDate(); clearTimeout(wCycle); cCycle = true; updateCycle(currDate); } }; //Проверка времени для работы цикла this.CheckDate = function () { for (var i = 0; i < rProc.length; i++) { if (rDStart[i] > rDEnd[i]) { var tmp = rDStart[i]; rDStart[i] = rDEnd[i]; rDEnd[i] = tmp; } } }; };