Программное создание графических схем (v.2): API для ГрафическойСхемы

Публикация № 551576 27.09.16

Разработка - Практика программирования

ГрафическаяСхема Графическая Схема Структура Соответствие JSON ЗаписьJSON ЧтениеJSON ЗаписатьJSON ПрочитатьJSON СериализаторXDTO

Пример динамического создания графических схем, добавления элементов любых видов. Любые схемы без бизнес-процессов. Программная работа со схемой. Отличие от существующей статьи в том, что здесь используется объектная модель. Исправил и упростил некоторые моменты - результат соответствует схеме, созданной руками. Добавил возможность рисования произвольных форм для существующих фигур.

Создано по мотивам статьи: Программное создание графических схем от Yashazz

Увидев решение об XML-сериализации ГрафическойСхемы (и десериализации ее) мелькнула мысль: "А ведь можно сделать и JSON-сериализацию". Но ведь JSON можно и десериализовать в Массивы и Соответствия. Вот она - объектная модель! Оперируем Структурами, Массивами и Соответствиями, далее делаем JSON сериализацию и десериализацию в ГрафическуюСхему.

Мой код, создающий ту же самую схему из статьи:

	// Здесь только для понимания. Вообще везде передаются коды типов, цифры
	ТипЭлементаГрафическойСхемы = Новый Структура;
	ТипЭлементаГрафическойСхемы.Вставить("Декорация",0);		//0		"Декорация"
	ТипЭлементаГрафическойСхемы.Вставить("ДекоративнаяЛиния",1);//1		"ДекоративнаяЛиния"
	ТипЭлементаГрафическойСхемы.Вставить("Старт",2);			//2		"Старт"
	ТипЭлементаГрафическойСхемы.Вставить("Завершение",3);		//3		"Завершение"
	ТипЭлементаГрафическойСхемы.Вставить("Условие",4);			//4		"Условие"
	ТипЭлементаГрафическойСхемы.Вставить("Действие",5);			//5		"Действие"
	ТипЭлементаГрафическойСхемы.Вставить("ВыборВарианта",6);	//6		"ВыборВарианта"
	ТипЭлементаГрафическойСхемы.Вставить("Разделение",7);		//7		"Разделение"
	ТипЭлементаГрафическойСхемы.Вставить("Слияние",8);			//8		"Слияние"
	ТипЭлементаГрафическойСхемы.Вставить("Обработка",9);		//9		"Обработка"
	ТипЭлементаГрафическойСхемы.Вставить("ВложенныйПроцесс",10);//10	"ВложенныйПроцесс"
	
	// Инициализация
	Схема = ИнициализироватьСхему();
	
	// Добавляем элементы один за другим
	_старт = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Старт,"ТестСтарта");
	_старт.itemTitle.Добавить(Новый Структура("lang,content","#","Погнали!"));
	_id_старт = ДобавитьЭлемент(Схема,_старт,100,30,100,40);
	
	_действие = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Действие,"ТестДействия");
	_действие.itemTitle.Добавить(Новый Структура("lang,content","#","Это действие"));
	_действие.taskDescription = "Некое действие в системе";
	_действие.explanation = "И.И.Иванов";
	_id_действие = ДобавитьЭлемент(Схема,_действие,100,120,100,60);
	
	_условие = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Условие,"ТестУсловия");
	_условие.itemTitle.Добавить(Новый Структура("lang,content","#","А я знаю?"));
	_id_условие = ДобавитьЭлемент(Схема,_условие,100,220,100,40);
	
	_действие2 = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Действие,"ТестДействия2");
	_действие2.itemTitle.Добавить(Новый Структура("lang,content","#","Тоже что-то"));
	_действие2.taskDescription = "Некое действие в системе";
	_действие2.explanation = "Петров";
	_id_действие2 = ДобавитьЭлемент(Схема,_действие2,10,280,100,60);
	
	_линия2 = ПодготовитьСтруктуруЛинии(Схема,_id_условие,_id_действие2,1,2,Ложь,"ТестЛинии2");
	_линия2.itemTitle.Добавить(Новый Структура("lang,content","#","Нет"));
	ДобавитьЭлемент(Схема,_линия2);
	
	_обработка = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Обработка,"ТестОбработки");
	_обработка.itemTitle.Добавить(Новый Структура("lang,content","#","Зашли сюды"));
	_id_обработка = ДобавитьЭлемент(Схема,_обработка,180,290,100,60);
	
	_линия3 = ПодготовитьСтруктуруЛинии(Схема,_id_условие,_id_обработка,3,2,Ложь,"ТестЛинии3");
	_линия3.itemTitle.Добавить(Новый Структура("lang,content","#","Да"));
	ДобавитьЭлемент(Схема,_линия3);
	
	_завершение = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Завершение,"ТестСтопа");
	_завершение.itemTitle.Добавить(Новый Структура("lang,content","#","Тпрууу!"));
	_id_завершение = ДобавитьЭлемент(Схема,_завершение,740,210,100,40);
	
	_процесс = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.ВложенныйПроцесс,"ТестБП");
	_процесс.itemTitle.Добавить(Новый Структура("lang,content","#","Вложенный БП"));
	_процесс.taskDescription = "Нечто внутри!";
	_id_процесс = ДобавитьЭлемент(Схема,_процесс,560,290,100,60);
	
	_выбор = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.ВыборВарианта,"ТестВарианта");
	_выбор.itemTitle.Добавить(Новый Структура("lang,content","#","Так как, собственно?"));
	__вар1 = Новый Структура("name,description,backColor","Вариант1",Новый Массив,_выбор.backColor);
	__вар1.description.Добавить(Новый Структура("lang,content","#","Превосходно!"));
	__вар2 = Новый Структура("name,description,backColor","Вариант2",Новый Массив,_выбор.backColor);
	__вар2.description.Добавить(Новый Структура("lang,content","#","Замечательно!"));
	_выбор.transition.Добавить(__вар1);
	_выбор.transition.Добавить(__вар2);
	_id_выбор = ДобавитьЭлемент(Схема,_выбор,440,100,140,100);
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_выбор,_id_завершение,7,2,Ложь)); 	// тут 7 это правая сторона 1-го варианта
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_выбор,_id_процесс,9,2,Ложь));		// тут 9 это правая сторона 2-го варианта
	// про 7 и 9 порты нужно пояснить...
	// у каждого элемента есть 5 основных портов (точек соединения): 1,2,3,4,5 (Лево, Верх, Право, Низ, Центр)
	// А далее идут стороны вариантов (только для элемента ВыборВарианта):
	// четные - левые стороны, нечетные - правые
	// поэтому 1 вариант левая сторона - это 6, а 1 вариант правая сторона - 7
	// для 2 варианта: 8 (лево) и 9 (право) соответственно
	// общая формула вычисления стороны (1 или 3 - лево или право) для портов > 5 следующая: portIndex = 1 + (portIndex%2)*2;
	
	_линия4 = ПодготовитьСтруктуруЛинии(Схема,_id_обработка,_id_выбор,3,2,Ложь,"ТестЛинии4");
	ДобавитьЭлемент(Схема,_линия4);
	
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_старт,_id_действие,4,2,Ложь));
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_действие,_id_условие,4,2,Ложь));
	
	// Вывод схемы
	ЗаписьJSON = Новый ЗаписьJSON;
	ЧтениеJSON = Новый ЧтениеJSON;
	
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON,Схема);
	стрJSON = ЗаписьJSON.Закрыть();
	Сообщить(стрJSON);
	ЧтениеJSON.УстановитьСтроку(стрJSON);
	зн = СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON,Тип("ГрафическаяСхема")); // Вот он результат!
	ЭлементыФормы.ГС.УстановитьСхему(зн); // Мой элемент на форме называется ГС

Можно оценить экономию места в модуле.

Модуль, который реализует API для работы с ГрафическимиСхемами
#Область ОБЪЕКТНАЯ_МОДЕЛЬ
Функция ИнициализироватьСхему() Экспорт
	стрСхема = Новый Структура;
	стрСхема.Вставить("backColor"			, Новый Соответствие);
	стрСхема.backColor.Вставить("#type"		, "jv8ui:Color");
	стрСхема.backColor.Вставить("#value"	, "{http://v8.1c.ru/8.1/data/ui/style}FieldBackColor");
	стрСхема.Вставить("enableGrid"			, Истина); // Включить сетку
	стрСхема.Вставить("drawGridMode"		, "Lines"); // Сетка. Варианты: None,Dots,Chess,Lines
	стрСхема.Вставить("gridVerticalStep"	, 20);
	стрСхема.Вставить("gridHorizontalStep"	, 20);
	стрСхема.Вставить("bpUUID"				, "00000000-0000-0000-0000-000000000000");
	стрСхема.Вставить("useOutput"			, "Auto");
	стрСхема.Вставить("printPropItem"		, Новый Массив);
	стрСхема.printPropItem.Добавить(Новый Структура("key,val",6	,10	));
	стрСхема.printPropItem.Добавить(Новый Структура("key,val",7	,10	));
	стрСхема.printPropItem.Добавить(Новый Структура("key,val",8	,10	));
	стрСхема.printPropItem.Добавить(Новый Структура("key,val",9	,10	));
	стрСхема.printPropItem.Добавить(Новый Структура("key,val",13,0	));
	стрСхема.printPropItem.Добавить(Новый Структура("key,val",16,0	));
	//стрСхема.Вставить("item"				, Новый Массив); // добавлять только если есть хотя бы один элемент
	
	значСхема = Новый Соответствие;
	значСхема.Вставить("#value",стрСхема);
	Возврат значСхема;
КонецФункции

Функция ДобавитьЭлемент(Схема,СтруктураЭлемента,x=Неопределено,y=Неопределено,dx=40,dy=40) Экспорт // dx,dy - тут для упрощения
	
	структураСхемы = Схема.Получить("#value");
	Если НЕ структураСхемы.Свойство("item") Тогда
		структураСхемы.Вставить("item", Новый Массив); // добавлять только если есть хотя бы один элемент
	КонецЕсли;
	
	Если НайтиПоЗначениюКлючаВМассивеСтруктур(структураСхемы.item,"itemCode",СтруктураЭлемента.itemCode) = СтруктураЭлемента Тогда
		Возврат СтруктураЭлемента.itemid;
	КонецЕсли;
	
	// Ищем максимальный itemid
	СтруктураЭлемента.itemid = ПолучитьМаксимальноеЗначениеКлючаВМассивеСтруктур(структураСхемы.item,"itemid") + 1;
	
	// Ищем такой же itemCode
	Если НайтиПоЗначениюКлючаВМассивеСтруктур(структураСхемы.item,"itemCode",СтруктураЭлемента.itemCode) <> Неопределено Тогда
		_базоваяЧасть = СтруктураЭлемента.itemCode;
		_нс = 1;
		Пока НайтиПоЗначениюКлючаВМассивеСтруктур(структураСхемы.item,"itemCode",_базоваяЧасть + Формат(_нс,"ЧГ=")) <> Неопределено Цикл
			_нс = _нс + 1;
		КонецЦикла;
		СтруктураЭлемента.itemCode = _базоваяЧасть + Формат(_нс,"ЧГ=");
	КонецЕсли;
	
	// Ищем максимальный itemTabOrder
	СтруктураЭлемента.itemTabOrder = ПолучитьМаксимальноеЗначениеКлючаВМассивеСтруктур(структураСхемы.item,"itemTabOrder") + 5; // пока так. Это порядок обхода. Возможно нужно более продвинутое вычисление сделать (считать все подчиненные и соединенные элементы последнего и прибавлять на их количество к максимальному)
	
	// Ищем максимальный zOrder
	СтруктураЭлемента.zOrder = ПолучитьМаксимальноеЗначениеКлючаВМассивеСтруктур(структураСхемы.item,"zOrder",-1) + 1;
	
	// *** Устанавливаем координаты и размер (опциоально)
	Если СтруктураЭлемента.itemType <> 1 Тогда // если не Линия
		Если x = Неопределено И y <> Неопределено Тогда // ищем максимальный X
			x = ПолучитьМаксимальноеЗначениеКлючаВМассивеСтруктур(структураСхемы.item,"rectRight") + структураСхемы.gridHorizontalStep;
		КонецЕсли;
		Если y = Неопределено И x <> Неопределено Тогда // ищем максимальный Y
			y = ПолучитьМаксимальноеЗначениеКлючаВМассивеСтруктур(структураСхемы.item,"rectBottom") + структураСхемы.gridVerticalStep;
		КонецЕсли;
		ЗаполнитьЗначенияСвойств(СтруктураЭлемента,Новый Структура("rectLeft,rectTop,rectRight,rectBottom",x,y,x+dx,y+dy));
		РасставитьТочкиФигуры(СтруктураЭлемента);
	КонецЕсли;
	
	// ДОБАВЛЕНИЕ ПОДГОТОВЛЕННОГО ЭЛЕМЕНТА
	структураСхемы.item.Добавить(СтруктураЭлемента);
	
	Возврат СтруктураЭлемента.itemid;
	
КонецФункции

// Рисуем фигуру элемента по точкам. Вообще говоря, как расставим точки,
// так и будет выглядеть фигура. Тут - типовой вариант, без изысков.
// А можно и фантазию включить... )) (см. скриншоты к статье) Модификатор - как раз для этого
Процедура РасставитьТочкиФигуры(СтруктураЭлемента,Модификатор=Неопределено) Экспорт
	
	Перем rectLeft,rectTop,rectRight,rectBottom,itemType;
	itemType = ?(Модификатор=Неопределено,СтруктураЭлемента.itemType,Модификатор);
	rectLeft = СтруктураЭлемента.rectLeft;
	rectTop = СтруктураЭлемента.rectTop;
	rectRight = СтруктураЭлемента.rectRight;
	rectBottom = СтруктураЭлемента.rectBottom;
	Если itemType = 5 ИЛИ itemType = 9 ИЛИ itemType = 10 Тогда // Действие/Обработка/ВложенныйПроцесс: Прямоугольник
		СтруктураЭлемента.point.Очистить();
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectBottom-1));
	ИначеЕсли itemType = 2 Тогда // Старт: Прямоугольник + треугольник снизу (высота треугольника = 5)
		dy = Цел((rectRight-rectLeft)/2/Sqrt(3));
		dy = ?(rectBottom-dy<=rectTop,Цел((rectBottom-rectTop)/2),dy); // корректировка запредельных значений
		СтруктураЭлемента.point.Очистить();
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectBottom-dy));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",Цел((rectLeft+rectRight)/2),rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectBottom-dy));
	ИначеЕсли itemType = 3 Тогда // Завершение: Прямоугольник + треугольник сверху (высота треугольника = 5)
		dy = Цел((rectRight-rectLeft)/2/Sqrt(3));
		dy = ?(rectTop+dy>=rectBottom,Цел((rectRight-rectLeft)/2),dy); // корректировка запредельных значений
		СтруктураЭлемента.point.Очистить();
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",Цел((rectLeft+rectRight)/2),rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectTop+dy));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop+dy));
	ИначеЕсли itemType = 4 Тогда // Условие: Шестиугольник (расчет середины высоты:dy/2,угол 60 градусов) 
		СтруктураЭлемента.point.Очистить();
		dx = Цел((rectBottom-rectTop)/2/Sqrt(3)); // ДельтаX при 60 градусном уклоне
		dx = ?(2*dx>(rectRight-rectLeft),Цел((rectRight-rectLeft)/4),dx); // корректировка запредельных значений
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,Цел((rectTop+rectBottom)/2)));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dx,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dx,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,Цел((rectTop+rectBottom)/2)));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dx,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dx,rectBottom-1));
	ИначеЕсли itemType = 6 Тогда // ВыборВарианта: Прямоугольник
		СтруктураЭлемента.point.Очистить();
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectBottom-1));
	ИначеЕсли itemType = 7 Тогда // Разделение: Треугольник, острый угол вниз
		dx = Цел((rectRight-rectLeft)/2)-1;
		СтруктураЭлемента.point.Очистить();
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+2*dx,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dx,rectBottom-1));
	ИначеЕсли itemType = 8 Тогда // Слияние: Треугольник, острый угол вверх
		dx = Цел((rectRight-rectLeft)/2)-1;
		СтруктураЭлемента.point.Очистить();
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+2*dx,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dx,rectTop));	
	ИначеЕсли itemType = 11 Тогда // (нетиповые фигуры) Галстук - бабочка
		СтруктураЭлемента.point.Очистить();
		dx = Цел((rectBottom-rectTop)/2/Sqrt(3)); // ДельтаX при 60 градусном уклоне
		dx = ?(2*dx>(rectRight-rectLeft),Цел((rectRight-rectLeft)/4),dx); // корректировка запредельных значений
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,Цел((rectTop+rectBottom)/2)));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dx,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",Цел((rectLeft+rectRight)/2),Цел((rectTop+rectBottom)/2)));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dx,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,Цел((rectTop+rectBottom)/2)));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dx,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",Цел((rectLeft+rectRight)/2),Цел((rectTop+rectBottom)/2)));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dx,rectBottom-1));
	ИначеЕсли itemType = 12 Тогда // (нетиповые фигуры) Звезда шерифа
		СтруктураЭлемента.point.Очистить();
		// сторона маленького треугольника
		dc = Цел((rectRight-rectLeft)/3);
		dchalf = Цел(dc/2);
		dchigh = Цел(dchalf*Sqrt(3));
		//dx = Цел((rectBottom-rectTop)/2/Sqrt(3)); // ДельтаX при 60 градусном уклоне
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop+dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dc,rectTop+dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dc+dchalf,rectTop));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dc,rectTop+dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectTop+dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dchalf,rectTop+2*dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1,rectTop+3*dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectRight-1-dc,rectTop+3*dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dc+dchalf,rectBottom-1));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dc,rectTop+3*dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft,rectTop+3*dchigh));
		СтруктураЭлемента.point.Добавить(Новый Структура("x,y",rectLeft+dchalf,rectTop+2*dchigh));
	ИначеЕсли itemType = 13 Тогда // (нетиповые фигуры) Круг
		СтруктураЭлемента.point.Очистить();
		// сторона маленького треугольника
		radius = МИН(Цел((rectRight-rectLeft)/2),Цел((rectBottom-rectTop)/2));
		xcenter = rectLeft + radius;
		ycenter = rectTop + radius;
		pi = 3.141592635897;
		НачУгол = -20;
		КонУгол = 200;
		ШагГрад = 10;
		у = НачУгол;
		Пока у<=КонУгол Цикл
			Угол = у*pi/180;
			x = Окр(Cos(Угол)*radius);
			y = Окр(Sin(Угол)*radius);
			СтруктураЭлемента.point.Добавить(Новый Структура("x,y",xcenter+x,ycenter+y));
			у = у + ШагГрад;
		КонецЦикла;
		
	КонецЕсли;
		
КонецПроцедуры

Функция ПолучитьМаксимальноеЗначениеКлючаВМассивеСтруктур(массивДляПоиска,ключСтруктуры,СтартовоеЗначениеКлюча=0)
	МаксимальноеЗначениеКлюча = СтартовоеЗначениеКлюча;
	Для каждого элемент из массивДляПоиска Цикл
		МаксимальноеЗначениеКлюча = Макс(МаксимальноеЗначениеКлюча,элемент[ключСтруктуры]);
	КонецЦикла;
	Возврат МаксимальноеЗначениеКлюча;
КонецФункции

Функция НайтиПоЗначениюКлючаВМассивеСтруктур(массивДляПоиска,ключСтруктуры,значениеКлюча)
	Ответ = Неопределено;
	Для каждого элемент из массивДляПоиска Цикл
		Если элемент[ключСтруктуры] = значениеКлюча Тогда
			Ответ = элемент;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Возврат Ответ;
КонецФункции

Функция ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы,itemCode=Неопределено) Экспорт
	
	МассивТиповЭлементовГрафическойСхемы = Новый Массив;
	МассивТиповЭлементовГрафическойСхемы.Добавить("Декорация");			//0		"Декорация"
	МассивТиповЭлементовГрафическойСхемы.Добавить("ДекоративнаяЛиния");	//1		"ДекоративнаяЛиния"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Старт");				//2		"Старт"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Завершение");		//3		"Завершение"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Условие");			//4		"Условие"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Действие");			//5		"Действие"
	МассивТиповЭлементовГрафическойСхемы.Добавить("ВыборВарианта");		//6		"ВыборВарианта"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Разделение");		//7		"Разделение"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Слияние");			//8		"Слияние"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Обработка");			//9		"Обработка"
	МассивТиповЭлементовГрафическойСхемы.Добавить("ВложенныйПроцесс");	//10	"ВложенныйПроцесс"
	Если itemCode = Неопределено Тогда
		itemCode = МассивТиповЭлементовГрафическойСхемы[ТипЭлементаГрафическойСхемы];
	КонецЕсли;
	
	Ответ = Новый Структура;
	
	Ответ.Вставить("itemType",				ТипЭлементаГрафическойСхемы);
	Ответ.Вставить("itemCode",				itemCode); 	// Должно быть задано при добавлении, д.б. уникально
	Ответ.Вставить("itemId",				Неопределено); // Вычислить при добавлении
	Ответ.Вставить("itemTabOrder",			Неопределено); // Вычислить при добавлении
	Ответ.Вставить("zOrder",				Неопределено); // Вычислить при добавлении
	Ответ.Вставить("lineColor",				Новый Соответствие);
	Ответ.lineColor.Вставить("#type",		"jv8ui:Color");
	Ответ.lineColor.Вставить("#value",		"{http://v8.1c.ru/8.1/data/ui/style}BorderColor");
	Ответ.Вставить("alignHor",				"Center");
	Ответ.Вставить("alignVer",				"Center");
	Ответ.Вставить("backColor",				Новый Соответствие);
	Ответ.backColor.Вставить("#type",		"jv8ui:Color");
	Ответ.backColor.Вставить("#value",		"auto");
	Ответ.Вставить("currentLanguage",		"#");
	Ответ.Вставить("picturePlacement",		"Left");
	Ответ.Вставить("textColor",				Новый Соответствие);
	Ответ.textColor.Вставить("#type",		"jv8ui:Color");
	Ответ.textColor.Вставить("#value",		"{http://v8.1c.ru/8.1/data/ui/style}FormTextColor");
	Ответ.Вставить("textFont",				Новый Структура("kind","AutoFont"));
	Ответ.Вставить("tipText",				Новый Соответствие);
	Ответ.Вставить("transparent",			Ложь);
	Ответ.Вставить("hyperlink",				Ложь);
	Ответ.Вставить("itemTitle",				Новый Массив);
	Ответ.Вставить("groupNum",				0);
	Если ТипЭлементаГрафическойСхемы <> 0 Тогда
		Ответ.Вставить("border",				Новый Структура("width,gap,style",Новый Соответствие,Ложь,Новый Соответствие));
		Ответ.border.width.Вставить("#type",	"jxs:decimal");
		Ответ.border.width.Вставить("#value",	1);
		Ответ.border.style.Вставить("#type",	"jsch:ConnectorLineType");
		Ответ.border.style.Вставить("#value",	"Solid");
		Ответ.Вставить("point",					Новый Массив);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы <> 1 Тогда
		Ответ.Вставить("rectBottom",			40);
		Ответ.Вставить("rectLeft",				60);
		Ответ.Вставить("rectRight",				80);
		Ответ.Вставить("rectTop",				20);
		Ответ.Вставить("picture",				Новый Соответствие);
		Ответ.Вставить("pictureStyle",			4);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы >= 2 Тогда
		Ответ.Вставить("pointUUID",				Строка(Новый УникальныйИдентификатор));
		Ответ.Вставить("passageState",			0);
		Ответ.Вставить("tableCode",				0);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 0 Тогда
		Ответ.Вставить("angle",					Новый Соответствие);
		Ответ.angle.Вставить("#type",	"jxs:decimal");
		Ответ.angle.Вставить("#value",	0);
		Ответ.Вставить("flipMode",				0);
		Ответ.Вставить("shape",					"Block");
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 1 Тогда
		Ответ.Вставить("beginArrowStyle",		"None");
		Ответ.Вставить("connectFromItemId",		-1); // Если decorativeLine = Истина, то можно и из ниоткуда
		Ответ.Вставить("connectFromPortIndex",	0);
		Ответ.Вставить("connectToItemId",		-1);
		Ответ.Вставить("decorativeLine",		Истина); // Если Ложь, то будет неубираемая "пристегнутая" линия к объекту
		Ответ.Вставить("endArrowStyle",			"Filled");
		Ответ.Вставить("portIndexFrom",			4);
		Ответ.Вставить("portIndexTo",			0);
		Ответ.Вставить("textPos",				"FirstSegment");
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 4 Тогда
		Ответ.Вставить("falsePortIndex",		1);
		Ответ.Вставить("truePortIndex",			3);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 5 ИЛИ ТипЭлементаГрафическойСхемы = 10 Тогда
		Ответ.Вставить("taskDescription",		itemCode); // Должно быть задано при добавлении; возможно = itemCode
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 5 Тогда
		Ответ.Вставить("addrZoneDivideYPos",	16);
		Ответ.Вставить("groupAddressing",		Ложь);
		Ответ.Вставить("isAddrZoneDivideValid",	Истина);
		Ответ.Вставить("explanation",			"");
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 6 Тогда
		Ответ.Вставить("transition",			Новый Массив);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 10 Тогда
		Ответ.Вставить("subprocessUUID",		"00000000-0000-0000-0000-000000000000");
	КонецЕсли;
	Возврат Ответ;
	
КонецФункции

Функция ПодготовитьСтруктуруЛинии(Схема,connectFrom,connectTo,portIndexFrom=Неопределено,portIndexTo=Неопределено,decorativeLine=Истина,itemCode=Неопределено) Экспорт
	
	Ответ = ПолучитьСтруктуруТипа(1,itemCode);
	Ответ.decorativeLine = decorativeLine; // не декоративная, а прицепленная линия
	Ответ.connectFromItemId = ?(ТипЗнч(connectFrom)=Тип("Структура"),connectFrom.ItemId,connectFrom);
	Ответ.connectToItemId = ?(ТипЗнч(connectTo)=Тип("Структура"),connectTo.ItemId,connectTo);
	Ответ.portIndexFrom = ?(portIndexFrom=Неопределено,1,portIndexFrom); // лево
	Ответ.portIndexTo = ?(portIndexTo=Неопределено,2,portIndexTo); // верх
	
	// Рисуем только начало и окончание. Остальное система дополнит сама при отрисовке.
	Ответ.point.Добавить(ПолучитьКоординатыЭлемента(Схема,Ответ.connectFromItemId,portIndexFrom,Ответ.connectFromPortIndex));
	Ответ.point.Добавить(ПолучитьКоординатыЭлемента(Схема,Ответ.connectToItemId,portIndexTo));
	
	// Багфикс: случай когда линия идет снизу на верхнюю границу
	Если Ответ.point[0].y > Ответ.point[1].y И Ответ.portIndexTo = 2 Тогда
		//Ответ.point.Вставить(1,Новый Структура("x,y",Ответ.point[1].x,Ответ.point[1].y-Схема["#value"].gridVerticalStep));
		xmid = Цел((ПолучитьКоординатыЭлемента(Схема,Ответ.connectFromItemId,3).x + ПолучитьКоординатыЭлемента(Схема,Ответ.connectToItemId,1).x)/2);
		Ответ.point.Вставить(1,Новый Структура("x,y",xmid,Ответ.point[1].y-Схема["#value"].gridVerticalStep));
	КонецЕсли;
	
	Возврат Ответ;
	
КонецФункции

Функция ПолучитьКоординатыЭлемента(Схема,itemId,portIndex,connectFromPortIndex=0)
	Ответ = Новый Структура("x,y",0,0);
	
	структураСхемы = Схема.Получить("#value");
	Если НЕ структураСхемы.Свойство("item") Тогда
		Возврат Ответ;
	КонецЕсли;
	СтруктураЭлемента = НайтиПоЗначениюКлючаВМассивеСтруктур(структураСхемы.item,"itemid",itemId);
	Если СтруктураЭлемента = Неопределено Тогда
		Возврат Ответ;
	КонецЕсли;
	// Порты:
	//1: Лево 
	//2: Верх 
	//3: Право 
	//4: Низ 
	//5: Центр 
	//6: Вариант 1 Лево 
	//7: Вариант 1 Право 
	//8: Вариант 2 Лево 
	//9: Вариант 2 Право
	// Каждый вариант - это 18 точек по шкале Y от rectBottom. Середина = rectBottom - (18/2)
	dy = 0;
	Если portIndex > 5 Тогда
		caseCount = СтруктураЭлемента.transition.Количество();
		connectFromPortIndex = Цел((portIndex-6)/2);
		portIndex = 1 + (portIndex%2)*2;
		dy = (caseCount - connectFromPortIndex - 1)*18 + 18/2;
	КонецЕсли;
	
	Если portIndex = 1 Тогда
		Ответ.x = СтруктураЭлемента.rectLeft;
		Ответ.y = ?(dy>0,СтруктураЭлемента.rectBottom-1-dy,Цел((СтруктураЭлемента.rectTop+СтруктураЭлемента.rectBottom+1)/2));
	ИначеЕсли portIndex = 2 Тогда
		Ответ.x = Цел((СтруктураЭлемента.rectLeft+СтруктураЭлемента.rectRight+1)/2);
		Ответ.y = СтруктураЭлемента.rectTop;
	ИначеЕсли portIndex = 3 Тогда
		Ответ.x = СтруктураЭлемента.rectRight;
		Ответ.y = ?(dy>0,СтруктураЭлемента.rectBottom-1-dy,Цел((СтруктураЭлемента.rectTop+СтруктураЭлемента.rectBottom+1)/2));
	ИначеЕсли portIndex = 4 Тогда
		Ответ.x = Цел((СтруктураЭлемента.rectLeft+СтруктураЭлемента.rectRight+1)/2);
		Ответ.y = СтруктураЭлемента.rectBottom;
	ИначеЕсли portIndex = 5 Тогда
		Ответ.x = Цел((СтруктураЭлемента.rectLeft+СтруктураЭлемента.rectRight+1)/2);
		Ответ.y = Цел((СтруктураЭлемента.rectTop+СтруктураЭлемента.rectBottom+1)/2);
	КонецЕсли;
	
	Возврат Ответ;
КонецФункции

Функция СформироватьГрафическуюСхему(Схема) Экспорт
	// Вывод схемы
	ЗаписьJSON = Новый ЗаписьJSON;
	ЧтениеJSON = Новый ЧтениеJSON;
	
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON,Схема);
	стрJSON = ЗаписьJSON.Закрыть();
	Сообщить(стрJSON);
	ЧтениеJSON.УстановитьСтроку(стрJSON);
	Возврат СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON,Тип("ГрафическаяСхема")); // Вот он результат!
КонецФункции
#КонецОбласти 

Я сам пока не готов сказать, что тут "всё сделано", наверняка что-то не учел. Хотел преподнести, как говорится, с пылу - с жару. Поэтому прошу сообщать о найденных багах. Сразу воспроизведу, поправлю, или приму pullRequest по части кода.

Всем спасибо за внимание, плюсы, лайки, баг-репорты...!

P.S.

Заметили в коде возможности рисования? Второй скрин - это как раз результат. В процедуре вывода добавил следующий код (с модификатором фигур):

Модуль вывода дополнительных фигур
	_разделение = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Разделение,"ТестБП");
	_разделение.itemTitle.Добавить(Новый Структура("lang,content","#","Разделяем"));
	//_разделение.taskDescription = "Пишем свое описание";
	_id_разделение = ДобавитьЭлемент(Схема,_разделение,585,380,50,30);
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_процесс,_id_разделение,4,2,Ложь));

	_действие5 = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Действие);
	_действие5.itemTitle.Добавить(Новый Структура("lang,content","#","Произвольное 
	|задание
	|"));
	_id_условие5 = ДобавитьЭлемент(Схема,_действие5,400,400,100,100);
	_действие5.explanation = "С.Ю.Сидоров";
	//РасставитьТочкиФигуры(_условие5,11); // галстук-бабочка
	РасставитьТочкиФигуры(_действие5,13); // круг
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_разделение,_id_условие5,4,2,Ложь));
	
	_процесс5 = ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы.Завершение);
	_процесс5.alignVer = "Top";
	_процесс5.itemTitle.Добавить(Новый Структура("lang,content","#","Звезда
	|шерифа
	|для победителя"));
	_id_процесс5 = ДобавитьЭлемент(Схема,_процесс5,700,400,100,100);
	РасставитьТочкиФигуры(_процесс5,12); // звезда шерифа
	ДобавитьЭлемент(Схема,ПодготовитьСтруктуруЛинии(Схема,_id_разделение,_id_процесс5,4,2,Ложь));

В планах упрощение API, вынос параметров координат в подготовку структуры элемента, из структуры элемента исключить вычисляемые поля (itemId, zOrder, itemTabOrder) для исключения ошибок, в процедуру ПодготовитьСтруктуруЛинии() добавить возможность обработки в качестве Источника и Приемника готовые структуры Элементов, а не только их itemId (Число) - опять же для удобства и сокращения кода. Результаты представлю по мере готовности...

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Spacer 312 28.09.16 09:47 Сейчас в теме
Интересная статья. А есть ли какие нибудь наработки по динамическому созданию географических схем?
Возможно подобный подход применим и к ним.
2. serg_infostart 355 28.09.16 10:35 Сейчас в теме
(1) Spacer, пока нет. Не было необходимости. Но подозреваю, что этот же подход сработает.
3. rus128 2 28.09.16 11:16 Сейчас в теме
все красиво, кроме:
// Сдесь только для понимания.
Вообще-то правильно писать "Здесь".
4. serg_infostart 355 28.09.16 16:17 Сейчас в теме
(3) rus128, там еще много где косяки по тексту... поправлю в ближайшее время...
5. serg_infostart 355 29.09.16 14:50 Сейчас в теме
Понял, что можно рисовать любые фигуры. Накидал примеров в статью. :)
Конечно, если пользователь будет двигать края фигуры, то карета превратится опять в тыкву наша замечательная фигурка станет тем, чем является по сути.
С типовыми фигурами ничего не произойдет.

А вот и домашнее задание.
Кто нарисует машинку? (добавить кусок кода в процедуру РасставитьТочкиФигуры() с новым Модификатором)
7. Yashazz 4091 09.11.16 12:02 Сейчас в теме
(5) здрасссьте. Я вроде об этом писал, что можно любые фигурки рисовать. Удобнее всего - из фигуры "Условие", она как шестиугольник наиболее гибкая.
В целом - была у меня мысль с json поработать, но в 1С это штука новая, а всё новое в платформе первые года 3 косячит и лучше не связываться) Хотя json лаконичнее, конечно.
9. serg_infostart 355 11.11.16 18:57 Сейчас в теме
(7) Yashazz, приветствую.
В принципе не имеет значения, "сколько"-угольник изначальная фигура, т.к. точек для нее можно добавить очень много (много больше шести).

Про JSON... тут я показал, как оно внутри строится... Но чтобы привести к стандартной 1С-овской модели работы с объектами, конечно, нужно всю эту штуку еще раз упаковать.
Сделать Структуру с переводом реквизитов на русский язык, аккуратно разложить по смысловым объектам, возможно, запихнуть это в обработку, чтобы в одном месте лежало. Вот пока руки никак не дойдут, но надеюсь представить...
ИМХО, должно быть что-то вроде: "СоздатьОбъект() - схема", "ДобавитьЭлемент(Тип)", "Вывести()", "СоединитьЭлементы()",... плюс нетривиальная штука - рисовать соединения, чтобы они сразу штатно отображались (штатно, это так, как если мы покажем как есть, сдвинем элемент туда-сюда руками, линия перерисуется, обходя другие объекты).

Совершенству нет предела...
6. Steelvan 126 09.11.16 11:29 Сейчас в теме
8. ЧерныйКот 09.11.16 14:30 Сейчас в теме
Делал тоже самое через объектную модель ДокументDOM. Ваш вариант выглядит более простым.
10. sviriduk 31.12.16 00:20 Сейчас в теме
Добрый день!
Добавьте, пожалуйста, в Ваш пример хотя бы одну декорацию.
Очень нужно!
Спасибо.
11. serg_infostart 355 09.01.17 10:35 Сейчас в теме
(10) Добрый день.
Увидел ошибку в выводе Декораций (действительно, не было ни одного примера, поэтому не заметил закравшуюся ошибку).
Код для вывода (у меня весь код в модуле/обработке "ГрафическиеСхемы", поэтому с ним привожу):
Декорация = ГрафическиеСхемы.ПолучитьСтруктуруТипа(0);
ГрафическиеСхемы.ДобавитьЭлемент(Схема,Декорация,10,10);
12. sviriduk 10.01.17 22:49 Сейчас в теме
(11) А в чем заключалась ошибка? Можете прислать исправленный код?
Просто вставка данного кода приводит к тому, что при формировании схемы стала возникать ошибка при вызове метода контекста (ПрочитатьJSON):
СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON,Тип("ГрафическаяСхема")); // Вот он результат!
по причине:
Ошибка при вызове метода объекта модели XDTO.
Неверный параметр.
13. serg_infostart 355 11.01.17 12:12 Сейчас в теме
(12) В этом и была ошибка...
Код в статье уже обновленный.
Исправил следующее:
Если itemType = 0 ИЛИ itemType = 5 ИЛИ itemType = 9 ИЛИ itemType = 10 Тогда // Декорация/Действие/Обработка/ВложенныйПроцесс: Прямоугольник

поменял на
Если itemType = 5 ИЛИ itemType = 9 ИЛИ itemType = 10 Тогда // Действие/Обработка/ВложенныйПроцесс: Прямоугольник

Т.е. у Декорации нет свойства Point.
14. sviriduk 11.01.17 23:10 Сейчас в теме
(13) Спасибо. А что нужно сделать, чтобы у декорации задать наименование (заголовок)?
15. serg_infostart 355 17.01.17 09:34 Сейчас в теме
(14)
Декорация.itemTitle.Добавить(Новый Структура("lang,content","#","Вот он заголовок"));


Обратите внимание: поправил модуль в публикации. itemTitle - всегда Массив (раньше было по условию).
16. check2 147 26.04.20 12:01 Сейчас в теме
К сожалению, не взлетело. Падает в ошибку при попытке прочитать json сериализатором.
В этой строке:
	зн = СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON,Тип("ГрафическаяСхема")); // Вот он результат!

См. вложение.
Попробовал убрать добавление всех элементов, оставил только инициализацию
{
"#value": {
"backColor": {
"#value": "{http://v8.1c.ru/8.1/data/ui/style}FieldBackColor",
"#type": "jv8ui:Color"
},
"enableGrid": true,
"drawGridMode": "Lines",
"gridVerticalStep": 20,
"gridHorizontalStep": 20,
"bpUUID": "00000000-0000-0000-0000-000000000000",
"useOutput": "Auto",
"printPropItem": [
{
"key": 6,
"val": 10
},
{
"key": 7,
"val": 10
},
{
"key": 8,
"val": 10
},
{
"key": 9,
"val": 10
},
{
"key": 13,
"val": 0
},
{
"key": 16,
"val": 0
}
]
}
}
Показать


Пробовал на релизе 8.3.14 в режиме совместимости 8.3.12
Есть идеи почему?
UPD:
Сериализовал пустую схему и сравнил с той что получается в инициализации.
После этого взлетело. Видимо, порядок важен. Учитывая, что статья достаточно старая видимо что то поменяли.
См. различия на картинке
Прикрепленные файлы:
17. check2 147 26.04.20 13:06 Сейчас в теме
(16)
В общем взлетело только после того, как ещё поменял дополнительно порядок элементов value & in procedure
Функция ПолучитьСтруктуруТипа(ТипЭлементаГрафическойСхемы,itemCode=Неопределено) Экспорт
	
	МассивТиповЭлементовГрафическойСхемы = Новый Массив;
	МассивТиповЭлементовГрафическойСхемы.Добавить("Декорация");			//0		"Декорация"
	МассивТиповЭлементовГрафическойСхемы.Добавить("ДекоративнаяЛиния");	//1		"ДекоративнаяЛиния"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Старт");				//2		"Старт"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Завершение");		//3		"Завершение"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Условие");			//4		"Условие"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Действие");			//5		"Действие"
	МассивТиповЭлементовГрафическойСхемы.Добавить("ВыборВарианта");		//6		"ВыборВарианта"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Разделение");		//7		"Разделение"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Слияние");			//8		"Слияние"
	МассивТиповЭлементовГрафическойСхемы.Добавить("Обработка");			//9		"Обработка"
	МассивТиповЭлементовГрафическойСхемы.Добавить("ВложенныйПроцесс");	//10	"ВложенныйПроцесс"
	Если itemCode = Неопределено Тогда
		itemCode = МассивТиповЭлементовГрафическойСхемы[ТипЭлементаГрафическойСхемы];
	КонецЕсли;
	
	Ответ = Новый Структура;
	
	Ответ.Вставить("itemType",				ТипЭлементаГрафическойСхемы);
	Ответ.Вставить("itemCode",				itemCode); 	// Должно быть задано при добавлении, д.б. уникально
	Ответ.Вставить("itemId",				Неопределено); // Вычислить при добавлении
	Ответ.Вставить("itemTabOrder",			Неопределено); // Вычислить при добавлении
	Ответ.Вставить("zOrder",				Неопределено); // Вычислить при добавлении
	Ответ.Вставить("lineColor",				Новый Соответствие);
	Ответ.lineColor.Вставить("#value",		"{http://v8.1c.ru/8.1/data/ui/style}BorderColor");
	Ответ.lineColor.Вставить("#type",		"jv8ui:Color");
	Ответ.Вставить("alignHor",				"Center");
	Ответ.Вставить("alignVer",				"Center");
	Ответ.Вставить("backColor",				Новый Соответствие);
	Ответ.backColor.Вставить("#value",		"auto");
	Ответ.backColor.Вставить("#type",		"jv8ui:Color");
	Ответ.Вставить("currentLanguage",		"#");
	Ответ.Вставить("picturePlacement",		"Left");
	Ответ.Вставить("textColor",				Новый Соответствие);
	Ответ.textColor.Вставить("#value",		"{http://v8.1c.ru/8.1/data/ui/style}FormTextColor");
	Ответ.textColor.Вставить("#type",		"jv8ui:Color");
	Ответ.Вставить("textFont",				Новый Структура("kind","AutoFont"));
	Ответ.Вставить("tipText",				Новый Соответствие);
	Ответ.Вставить("transparent",			Ложь);
	Ответ.Вставить("hyperlink",				Ложь);
	Ответ.Вставить("itemTitle",				Новый Массив);
	Ответ.Вставить("groupNum",				0);
	Если ТипЭлементаГрафическойСхемы <> 0 Тогда
		Ответ.Вставить("border",				Новый Структура("width,gap,style",Новый Соответствие,Ложь,Новый Соответствие));
		Ответ.border.width.Вставить("#value",	1);
		Ответ.border.width.Вставить("#type",	"jxs:decimal");
		Ответ.border.style.Вставить("#value",	"Solid");
		Ответ.border.style.Вставить("#type",	"jsch:ConnectorLineType");
		Ответ.Вставить("point",					Новый Массив);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы <> 1 Тогда
		Ответ.Вставить("rectBottom",			40);
		Ответ.Вставить("rectLeft",				60);
		Ответ.Вставить("rectRight",				80);
		Ответ.Вставить("rectTop",				20);
		Ответ.Вставить("picture",				Новый Соответствие);
		Ответ.Вставить("pictureStyle",			4);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы >= 2 Тогда
		Ответ.Вставить("pointUUID",				Строка(Новый УникальныйИдентификатор));
		Ответ.Вставить("passageState",			0);
		Ответ.Вставить("tableCode",				0);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 0 Тогда
		Ответ.Вставить("angle",					Новый Соответствие);
		Ответ.angle.Вставить("#value",	0);
		Ответ.angle.Вставить("#type",	"jxs:decimal");
		Ответ.Вставить("flipMode",				0);
		Ответ.Вставить("shape",					"Block");
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 1 Тогда
		Ответ.Вставить("beginArrowStyle",		"None");
		Ответ.Вставить("connectFromItemId",		-1); // Если decorativeLine = Истина, то можно и из ниоткуда
		Ответ.Вставить("connectFromPortIndex",	0);
		Ответ.Вставить("connectToItemId",		-1);
		Ответ.Вставить("decorativeLine",		Истина); // Если Ложь, то будет неубираемая "пристегнутая" линия к объекту
		Ответ.Вставить("endArrowStyle",			"Filled");
		Ответ.Вставить("portIndexFrom",			4);
		Ответ.Вставить("portIndexTo",			0);
		Ответ.Вставить("textPos",				"FirstSegment");
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 4 Тогда
		Ответ.Вставить("falsePortIndex",		1);
		Ответ.Вставить("truePortIndex",			3);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 5 ИЛИ ТипЭлементаГрафическойСхемы = 10 Тогда
		Ответ.Вставить("taskDescription",		itemCode); // Должно быть задано при добавлении; возможно = itemCode
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 5 Тогда
		Ответ.Вставить("addrZoneDivideYPos",	16);
		Ответ.Вставить("groupAddressing",		Ложь);
		Ответ.Вставить("isAddrZoneDivideValid",	Истина);
		Ответ.Вставить("explanation",			"");
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 6 Тогда
		Ответ.Вставить("transition",			Новый Массив);
	КонецЕсли;
	Если ТипЭлементаГрафическойСхемы = 10 Тогда
		Ответ.Вставить("subprocessUUID",		"00000000-0000-0000-0000-000000000000");
	КонецЕсли;
	Возврат Ответ;
	
КонецФункции
Показать


Исходному автору и автору адаптации на json респект и уважуха. Всем добра!
Прикрепленные файлы:
serg_infostart; +1 Ответить
18. check2 147 26.04.20 15:00 Сейчас в теме
(16)
Указанная проблема очень похожа на проблему кроссплатформенности в платформе 8.3.14.1993... Изначально пробовал под Linux… Под Winodws получил ту же ошибку.
После того как все последовательности упаковал в условия
	СИ = Новый СистемнаяИнформация();
	Если СИ.ТипПлатформы = ТипПлатформы.Linux_x86 ИЛИ
			СИ.ТипПлатформы = ТипПлатформы.Linux_x86_64 Тогда
		Ответ.lineColor.Вставить("#value",		"{http://v8.1c.ru/8.1/data/ui/style}BorderColor");
		Ответ.lineColor.Вставить("#type",		"jv8ui:Color");
	Иначе
		Ответ.lineColor.Вставить("#type",		"jv8ui:Color");
		Ответ.lineColor.Вставить("#value",		"{http://v8.1c.ru/8.1/data/ui/style}BorderColor");
	КонецЕсли;
Показать

Надо будет под другими версиями платформами потестить.
Оставьте свое сообщение

См. также

Аналог PIVOT в запросе 1С (как выполнить транспонирование таблицы в запросе 1С) Промо

Практика программирования v8 Бесплатно (free)

В статье показывается простой метод реализации аналога оператора PIVOT в запросе 1С без использования соединений.

12.12.2020    4181    Eugen-S    23    

Что за ? в коде, или Секретный оператор в 1С

Практика программирования v8 Платформа 1C v8.2 Платформа 1С v8.1 1cv8.cf Бесплатно (free)

Инкремент, модуль и прочая магия, которая скрыта под символом "?"

21.10.2021    6030    SeiOkami    36    

Полезные примеры СКД, ч.2

Практика программирования v8 v8::СКД Бесплатно (free)

Еще несколько примеров решения задач в СКД.

06.04.2021    10321    Neti    8    

Обзор полезных методов БСП 3.1.4

Практика программирования БСП (Библиотека стандартных подсистем) v8 1cv8.cf Бесплатно (free)

Библиотека стандартных подсистем (далее - БСП) является частью любой типовой конфигурации, поэтому умение применять готовые процедуры и функции повышает качество разработки и избавляет от написания лишнего кода. К сожалению, не у всех есть время и упорство овладеть всей документацией, поэтому я собрал воедино наиболее популярный функционал.

25.03.2021    38595    rayastar    51    

Использование классов .Net в 1С для новичков Промо

Практика программирования Разработка внешних компонент Универсальные функции v7.7 v8 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    85354    Serginio    115    

Звуковое управление в 1С 8.3

Практика программирования v8 1cv8.cf Бесплатно (free)

В данной статье описано создание библиотеки для звукового управления (выполнение команд голосом) для платформы 1С 8.3. Задача была поставлена так, чтобы модуль функционировал непосредственно на клиенте 1С, осуществляя управление формами, и взаимодействовал с интерфейсом.

16.03.2021    7009    velemir    33    

Serverless (Faas) в 1С. Создание и вызов Yandex Cloud Functions

Универсальные функции Практика программирования v8 Бесплатно (free)

"Я не могу просто взять и скопировать код с гитхаба", "у нас 1С микросервисами окружена", "возможностей мало" - частые фразы 1С разработчиков. которым не хватает возможностей платформы в современном мире. Faas, конечно, история не новая, но нас сдерживало 152ФЗ и задержки по пингам. Для того, чтобы действительно использовать в 1С код, к примеру, на Python, надо было приложить усилия. Теперь всё намного проще - берём и используем.

28.12.2020    8714    comol    31    

Базовые вещи БСП, которые облегчат жизнь программисту 1С

Практика программирования БСП (Библиотека стандартных подсистем) v8 1cv8.cf Россия Бесплатно (free)

В данной публикации я опишу полезные процедуры и функции модуля общего назначения библиотеки стандартных подсистем, обязательные к использованию любым программистом 1С.

30.08.2020    19743    quazare    34    

Использование программных перечислений, ч.1: строковые константы Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Часто ли у вас возникает необходимость в коде выполнять сравнение на строку?

10.12.2016    40974    unichkin    74    

Форма выбора (подбор) в управляемых формах

Практика программирования v8 v8::УФ 1cv8.cf Россия Бесплатно (free)

Разбор небольших примеров того, как правильно открывать форму выбора (подбора) в управляемых формах, не прибегая к модальным окнам.

08.05.2020    74843    user5300    19    

Программная работа с настройками СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Нюансы программной работы с настройками системы компоновки данных в отчетах и динамических списках. Обзор всех видов настроек компоновки. Что в каких случаях правильно применять. В качестве примера рассмотрена работа с отборами и группировками.

27.01.2020    64064    ids79    26    

Вспомогательные инструкции в коде 1С Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Помогаем редактору кода 1С помогать нам писать и анализировать код.

15.10.2018    35932    tormozit    106    

[СКД] Программное создание схемы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    42891    John_d    22    

СКД. Шаг 3. Используем макеты для оформления отчета

Работа с интерфейсом v8 v8::СКД 1cv8.cf Бесплатно (free)

В данной публикации рассмотрим базовый подход к использованию собственных макетов в СКД на примере формирования небольшого отчета.

13.01.2020    36465    aximo    18    

Последовательности событий при проведении документа 1С. Шпаргалка + про формы + про расширения

Практика программирования v8 Россия Бесплатно (free)

Собрал информацию о событиях/подписках/расширениях в одном месте.

30.12.2019    34513    kuzyara    38    

Оформление и рефакторинг сложных логических выражений Промо

Практика программирования v8 Россия Бесплатно (free)

В сложных логических выражениях нередко самому автору спустя какое-то время тяжело разобраться, не говоря уже о других программистах. Предлагаемая методика позволяет повысить наглядность таких выражений путем оформления в виде И-ИЛИ дерева и одновременно выполнять их рефакторинг.

20.09.2012    82712    tormozit    131    

Сходство Джаро - Винклера. Нечеткое сравнение строк

Универсальные функции v8 Россия Бесплатно (free)

В области информатики и статистики сходство Джаро - Винклера представляет собой меру схожести строк для измерения расстояния между двумя последовательностями символов. В публикации рассмотрены некоторые особенности алгоритма, и представлен вариант его реализации на языке 1С.

25.12.2019    8360    brooho    19    

Как передать IP адрес, который вызвал HTTP запрос в 1C (для веб-сервера Apache)

Практика программирования v8 Бесплатно (free)

Столкнулся с задачей получения IP адреса, который вызывает http сервис 1С. Итак, решение:

22.11.2019    12163    Sibars    19    

Полезные процедуры и функции для программиста

Практика программирования Универсальные функции v8 1cv8.cf Россия Бесплатно (free)

Все мы пишем программный код и часто используем процедуры, облегчающие его написание. Ниже приведена выборка таких полезных процедур и функций.

07.10.2019    39342    HostHost    41    

Запись значения в поле ввода/формы со срабатыванием события ПриИзменении Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Иногда возникает необходимость после записи значения в какое либо поле ввода/формы вызвать для него обработчик события ПриИзменении, а о вызове самого события приходится только мечтать. В этой статье приводится программный способ вызова этого события.

11.07.2007    54189    tormozit    51    

Таблица значений. Нюансы

Практика программирования v8 Бесплатно (free)

Обзор некоторых аспектов использования общеизвестного инструмента 1С.

01.10.2019    52267    Yashazz    56    

[Шпаргалка] Программное создание элементов формы

Практика программирования Работа с интерфейсом v8 1cv8.cf Бесплатно (free)

Программное создание практически всех популярных элементов формы.

06.09.2019    99728    rpgshnik    75    

Агрегатные функции СКД, о которых мало кто знает

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    76479    ids79    56    

Как сделать из &НаКлиентеНаСервереБезКонтекста почти &НаКлиентеНаСервере Промо

Практика программирования v8 1cv8.cf Россия Бесплатно (free)

Как сделать метод формы, доступный на клиенте и на сервере одновременно, и сохранить при этом удобство разработки

10.09.2017    50950    tormozit    74    

Регистры бухгалтерии. Общая информация

Практика программирования Математика и алгоритмы v8 v8::БУ БУ Бесплатно (free)

Общая информация о внутреннем устройстве регистров бухгалтерии.

05.09.2019    45898    YPermitin    25    

Три костыля. Сказ про фокусы в коде

Практика программирования v8 Бесплатно (free)

Три интересных (или странных) костыля в коде, которые могут помочь в повседневных и не очень задачах.

03.09.2019    30069    YPermitin    81    

Отслеживание выполнения фонового задания

Практика программирования Универсальные функции Разработка v8 1cv8.cf Бесплатно (free)

Запуск фонового задания из модуля внешней обработки. Отслеживание выполнения задания в виде прогресса, расположенного на форме.

17.08.2019    44749    ids79    22    

Выгрузка документа по условию Промо

Практика программирования Разработка v8 Бесплатно (free)

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    17942    m-rv    3    

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    149006    ids79    75    

Фоновое выполнение кода в 1С - это просто

Практика программирования v8 1cv8.cf Бесплатно (free)

Как легко запускать выполнение в фоне, не прибегая к долгому описанию фоновых процедур.

02.08.2019    59725    avalakh    26    

Разбираемся с параметрами редактирования СКД

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Связь по типу, Параметры выбора, Связи параметров выбора

31.07.2019    41096    json    17    

Как прикрутить ГУИД к регистру сведений Промо

Практика программирования Перенос данных из 1C8 в 1C8 Разработка v8 Бесплатно (free)

... и немного теории обмена данными. В частности, разберем боль всех, кто пишет небанальные обмены данными: как набору записей регистра сведений назначить гуид и далее использовать его в обмене для идентификации этого набора.

16.04.2019    23239    m-rv    18    

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    103761    ids79    16    

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Инструментарий разработчика Практика программирования v8 v8::СКД Бесплатно (free)

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    47933    ids79    27    

Регистры сведений. За кулисами

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    33615    YPermitin    14    

Как сделать запрос на изменение данных Промо

Практика программирования v8 v8::Запросы 1cv8.cf Бесплатно (free)

В статье приведены особенности внутренней архитектуры и примеры работы с расширением языка запросов 1С.

01.06.2018    36680    m-rv    23    

"Меньше копипаста!", или как Вася универсальную процедуру писал

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    22458    SeiOkami    53    

Работа с настройками системы компоновки данных

Практика программирования v8 v8::СКД 1cv8.cf Бесплатно (free)

Варианты отчетов, работа с настройками вариантов: структура группировок, поля отчета, отборы, сортировка, условное оформление, другие настройки, настройки отображения диаграмм.

02.07.2019    82918    ids79    18    

Создание отчетов с помощью СКД - основные понятия и элементы

Практика программирования Математика и алгоритмы v8 v8::СКД Бесплатно (free)

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    75245    ids79    28    

Метод формирования движений в типовых регистрах нетиповыми регистраторами Промо

Практика программирования v8 1cv8.cf Бесплатно (free)

Вариант решения задач с проведением по типовым регистрам нетиповыми регистраторами. Зачем - чтобы при сравнении конфигурации не обращать внимание на свойства регистров и исключить вероятность допущения горькой оплошности при обновлении информационных баз, заменив типы регистраторов основной конфигурации типами конфигурации поставщика. Для программных продуктов, имеющих в своем составе метаданных документ "Корректировка регистров"("Корректировка записей регистров").

05.12.2017    30712    itriot11    34    

Подсистема "Варианты отчетов". Используете ли Вы ее правильно?

Работа с интерфейсом БСП (Библиотека стандартных подсистем) v8 1cv8.cf Бесплатно (free)

Небольшая история про использование подсистемы "Варианты отчетов" из БСП. Используете ли Вы ее правильно?

04.06.2019    55650    YPermitin    55    

Регистры накопления. Структура хранения в базе данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    62933    YPermitin    31    

О расширениях замолвите слово...

Практика программирования Разработка v8 Бесплатно (free)

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    42345    ellavs    131    

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Практика программирования v8 Бесплатно (free)

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    31842    ellavs    90    

Трюки с внешними источниками данных

Практика программирования Разработка v8 1cv8.cf Бесплатно (free)

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    40928    YPermitin    53    

Разработка и сценарное тестирование с Vanessa-ADD. Отчетность Allure. Автоматизация запуска сценариев

Практика программирования BDD/TDD-тестирование, Vanessa v8 Россия Бесплатно (free)

Формируем отчетность о результатах выполнения сценариев. Автоматизируем запуск.

26.02.2019    28306    Vladimir Litvinenko    28    

Возможности типовых шаблонов ограничения доступа на уровне записей (RLS)

Практика программирования БСП (Библиотека стандартных подсистем) Роли и права v8 v8::Права Бесплатно (free)

Краткий обзор применения типовых шаблонов ограничения доступа на уровне записей в конфигурациях, созданных на базе БСП: #ПоЗначениям, #ПоНаборамЗначений, #ПоЗначениямРасширенный, #ПоЗначениямИНаборамРасширенный

03.02.2019    64471    ids79    11