Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 107 additions & 25 deletions src/ПрогрессБар.os
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
Перем КурсорУправляем;
Перем ВыводВозможен;

Перем ДлинаБараПоУмолчанию;
Перем МинимальнаяДлинаБара;

///////////////////////////////////////////////////////////////////////////////

// Начать
Expand Down Expand Up @@ -154,49 +157,76 @@
КонецЦикла;
Консоль.КурсорЛево = 0;

// Подписи считаются до отрисовки: по ним видно, сколько места остаётся бару.
// Не уместившийся в ширину бар терминал переносит на следующую строку, и очистка
// следующего кадра стирает только её - предыдущая остаётся на экране, а вместо
// строки прогресса получается лестница из хвостов
ТекстНомера = ?(НадоВыводитьНомерИКоличество,
СтрШаблон("(%1 из %2) ", ПоследнийШаг, КоличествоШаговПрогресса),
"");

ТекстПроцентов = ?(НадоВыводитьПроценты,
"" + Цел(ПоследнийШаг / КоличествоШаговПрогресса * 100) + "% ",
"");

Если НадоВыводитьВремя Тогда

ДлительностьСтрока = ВремяВСтроку(Длительность);
Прогноз = (Длительность * КоличествоШаговПрогресса) / ПоследнийШаг - Длительность;
ТекстВремени = "t " + ДлительностьСтрока + " ~" + ВремяВСтроку(Прогноз);

Иначе

ТекстВремени = "";

КонецЕсли;

// 5 - это значок, пробел и рамка бара из двух вертикальных черт с пробелом
ЗанятоПодписями = СтрДлина(ТекстПодсказки) + СтрДлина(ТекстНомера)
+ СтрДлина(ТекстПроцентов) + СтрДлина(ТекстВремени) + 5;

ДлинаБара = ДлинаБара(ЗанятоПодписями);

Если ЗначениеЗаполнено(ТекстПодсказки) Тогда

Консоль.ЦветТекста = ЦветКонсоли.Green;
Консоль.Вывести(ТекстПодсказки);

КонецЕсли;
Если НадоВыводитьНомерИКоличество Тогда

Если ЗначениеЗаполнено(ТекстНомера) Тогда

Консоль.ЦветТекста = ЦветКонсоли.Yellow;
Консоль.Вывести(СтрШаблон("(%1 из %2) ", ПоследнийШаг, КоличествоШаговПрогресса));
Консоль.Вывести(ТекстНомера);

КонецЕсли;

Консоль.ЦветТекста = ЦветБара;
Позиция = Цел(ПоследнийШаг / КоличествоШаговПрогресса * 100 / 2);

Позиция = Цел(ПоследнийШаг / КоличествоШаговПрогресса * ДлинаБара);

Значек = Сред("/-\|", ПоследнийШаг % 4 + 1, 1);
СтрокаЗаполненногоПрогресса = Сред(СтрокаЗаполненногоБара, 1, Позиция);
СтрокаНеЗаполненногоПрогресса = Сред(СтрокаПустогоБара, Позиция);
СтрокаНеЗаполненногоПрогресса = Сред(СтрокаПустогоБара, 1, ДлинаБара - Позиция);

Консоль.Вывести(СтрШаблон("%1 |%2%3| ", Значек, СтрокаЗаполненногоПрогресса, СтрокаНеЗаполненногоПрогресса));

Если НадоВыводитьПроценты Тогда
Если ЗначениеЗаполнено(ТекстПроцентов) Тогда

Консоль.ЦветТекста = ЦветКонсоли.Yellow;
Консоль.Вывести("" + Цел(ПоследнийШаг / КоличествоШаговПрогресса * 100) + "% ");
Консоль.Вывести(ТекстПроцентов);

КонецЕсли;

Если НадоВыводитьВремя Тогда

ДлительностьСтрока = ВремяВСтроку(Длительность);
Прогноз = (Длительность * КоличествоШаговПрогресса) / ПоследнийШаг - Длительность;
ПрогнозСтрока = ВремяВСтроку(Прогноз);
Если ЗначениеЗаполнено(ТекстВремени) Тогда

Консоль.ЦветТекста = ЦветКонсоли.Yellow;
Консоль.Вывести("t ");
Консоль.ЦветТекста = ЦветКонсоли.Cyan;
Консоль.Вывести("" + ДлительностьСтрока + " ~" + ПрогнозСтрока);
Консоль.Вывести(Сред(ТекстВремени, 3));

КонецЕсли;

СкрытьКурсор(Истина);
Консоль.ЦветТекста = ЦветТекстаКонсоли;

Expand Down Expand Up @@ -262,8 +292,9 @@
//
Процедура УстановитьСимволыБара(СимволПустогоБара = " ", СимволЗаполненногоБара = "-") Экспорт

СтрокаПустогоБара = ЗаполнитьБар(СимволПустогоБара);
СтрокаЗаполненногоБара = ЗаполнитьБар(СимволЗаполненногоБара);
// Заготовки строятся на самый широкий бар: узкая консоль берёт от них начало
СтрокаПустогоБара = ЗаполнитьБар(СимволПустогоБара, ДлинаБараПоУмолчанию);
СтрокаЗаполненногоБара = ЗаполнитьБар(СимволЗаполненногоБара, ДлинаБараПоУмолчанию);

КонецПроцедуры // УстановитьСимволыБара()

Expand Down Expand Up @@ -342,6 +373,55 @@

КонецПроцедуры // СкрытьКурсор()

// ДлинаБара
// Возвращает длину бара, при которой строка помещается в ширину консоли.
//
// Полная ширина не занимается: последняя колонка оставляется пустой, иначе вывод
// в неё сам по себе переводит строку. Узкая консоль ужимает бар до минимума,
// а неизвестная ширина оставляет прежние 50 - там, где ширину узнать нельзя,
// перенос всё равно не грозит.
//
// Параметры:
// ЗанятоПодписями - Число - Сколько символов строки занято всем, кроме самого бара
//
// Возвращаемое значение:
// Число - Длина бара в символах
//
Функция ДлинаБара(Знач ЗанятоПодписями)

Попытка
ШиринаКонсоли = Консоль.Ширина;
Исключение
ШиринаКонсоли = 0;
КонецПопытки;

Возврат ДлинаБараДляШирины(ШиринаКонсоли, ЗанятоПодписями);

КонецФункции

// ДлинаБараДляШирины
// Длина бара для заданной ширины консоли. Вынесена отдельно от чтения консоли,
// чтобы проверяться без неё: в сборке консоли нет.
//
// Параметры:
// ШиринаКонсоли - Число - Ширина консоли в символах, 0 - ширина неизвестна
// ЗанятоПодписями - Число - Сколько символов строки занято всем, кроме самого бара
//
// Возвращаемое значение:
// Число - Длина бара в символах
//
Функция ДлинаБараДляШирины(Знач ШиринаКонсоли, Знач ЗанятоПодписями) Экспорт

Если ШиринаКонсоли <= 0 Тогда
Возврат ДлинаБараПоУмолчанию;
КонецЕсли;

Возврат Макс(
МинимальнаяДлинаБара,
Мин(ДлинаБараПоУмолчанию, ШиринаКонсоли - 1 - ЗанятоПодписями));

КонецФункции

Функция ЗаполнитьБар(СимволШаблона, Длина = 50);

МассивСимволов = Новый Массив;
Expand All @@ -359,5 +439,7 @@
Длительность = 0;
КурсорУправляем = ИСТИНА;
ВыводВозможен = ИСТИНА;
ДлинаБараПоУмолчанию = 50;
МинимальнаяДлинаБара = 10;
ЦветБара = ЦветКонсоли.Magenta;
УстановитьСимволыБара();
44 changes: 44 additions & 0 deletions tests/ПрогрессБар.os
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,50 @@

КонецПроцедуры

&Тест
Процедура БарУжимаетсяПодУзкуюКонсоль() Экспорт

// Не уместившуюся строку терминал переносит, а очистка следующего кадра стирает
// только последнюю строку - предыдущая остаётся на экране, и вместо прогресса
// получается лестница из хвостов

// подписи занимают 45 символов из 80, последняя колонка не занимается
Ожидаем.Что(Бар().ДлинаБараДляШирины(80, 45), "Бар в узкой консоли")
.Равно(34);

КонецПроцедуры

&Тест
Процедура БарНеРастетШире50() Экспорт

// Широкая консоль бар не растягивает: привычный размер остаётся прежним

Ожидаем.Что(Бар().ДлинаБараДляШирины(200, 45), "Бар в широкой консоли")
.Равно(50);

КонецПроцедуры

&Тест
Процедура БарНеСхлопываетсяВНичто() Экспорт

// Подписи бывают шире всей консоли. Бар тогда бесполезен, но и рисовать
// отрицательное число символов нельзя

Ожидаем.Что(Бар().ДлинаБараДляШирины(30, 45), "Бар в очень узкой консоли")
.Равно(10);

КонецПроцедуры

&Тест
Процедура БезИзвестнойШириныБарПрежний() Экспорт

// В сборке ширины нет, но там и переноса не будет: вывод идёт в файл

Ожидаем.Что(Бар().ДлинаБараДляШирины(0, 45), "Бар при неизвестной ширине")
.Равно(50);

КонецПроцедуры

&Тест
Процедура СимволыИЦветБараНастраиваются() Экспорт

Expand Down
Loading