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

17.01.17

Разработка - Работа с интерфейсом

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

Создано по мотивам статьи: Программное создание графических схем от 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 (Число) - опять же для удобства и сокращения кода. Результаты представлю по мере готовности...

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

См. также

Работа с интерфейсом Программист Платформа 1С v8.3 Конфигурации 1cv8 1С:ERP Управление предприятием 2 Платные (руб)

Обработка предназначена для создания и управления дашбордами.

2400 руб.

29.06.2020    17678    24    6    

38

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    11808    YA_418728146    7    

158

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2894    43    progmaster    8    

4

Работа с интерфейсом Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    4630    kalyaka    6    

32

Работа с интерфейсом Платформа 1С v8.3 Платные (руб)

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

6000 руб.

18.01.2022    9387    1    2    

6

Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Бесплатно (free)

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

12.11.2021    19053    acces969    95    

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

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

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

Совершенству нет предела...
6. Steelvan 305 09.11.16 11:29 Сейчас в теме
8. ЧерныйКот 09.11.16 14:30 Сейчас в теме
Делал тоже самое через объектную модель ДокументDOM. Ваш вариант выглядит более простым.
10. sviriduk 31.12.16 00:20 Сейчас в теме
Добрый день!
Добавьте, пожалуйста, в Ваш пример хотя бы одну декорацию.
Очень нужно!
Спасибо.
11. serg_infostart 388 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 388 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 388 17.01.17 09:34 Сейчас в теме
(14)
Декорация.itemTitle.Добавить(Новый Структура("lang,content","#","Вот он заголовок"));


Обратите внимание: поправил модуль в публикации. itemTitle - всегда Массив (раньше было по условию).
16. check2 369 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 369 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 369 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");
	КонецЕсли;
Показать

Надо будет под другими версиями платформами потестить.
19. Maxis 03.10.22 10:30 Сейчас в теме
Подскажите, как настроить такое положение соединительных линий, чтобы линия не прижималась к родительскому блоку (как на картинке 01), а шла чуть ниже него (как на картинке 02)? Сравнивал все элементы до и после передвижения - все свойства линии кажутся одинаковыми.
Прикрепленные файлы:
Оставьте свое сообщение