Программное создание графических схем (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 Платные (руб)

Обработка предназначена для редактирования картинок в режиме «Предприятие», с возможностью РИСОВАТЬ на них. Поддерживается работа как в обычных формах (толстый клиент) так и на управляемых формах (тонкий клиент). Обработка позволяет редактировать как картинки, хранимые в базе, так и графические файлы с диска на файловой системе. Помимо базовых функций (изменение размеров, преобразование формата, обрезание картинки, повороты и т.п.) – редактор имеет богатый набор инструментов для рисования. Доступна функция вставки изображения из буфера обмена. Также обработка может быть использована из встроенного языка как объект для редактирования картинок. Объект может быть использован: на стороне клиента, на стороне сервера, из внешнего соединения. Данная обработка будет особенно полезна тем, кто вносит картинки в базу (изображения номенклатуры, фотографии физических лиц и т.п.). Функционал реализуется с использованием JavaScript и бесплатного ПО ImageMagick (без использования внешних компонент).

6000 руб.

16.01.2015    61939    43    59    

80

[Расширения] Динамическое управление видимостью и доступностью элементов форм (УФ) (8.3.6+)

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

Механизм «Динамическое управление доступом к элементам форм объектов 1С8» предназначен для обеспечения возможности оперативного управления видимостью и доступностью элементов форм документов и справочников продуктов фирмы «1С» «1С:Предприятие 8». Решение универсальное, встраивается в любую конфигурацию с минимальными доработками, что позволяет без проблем обновлять типовые решения.

5000 руб.

14.01.2016    54567    16    21    

42

Управление дашбордами

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

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

2400 руб.

29.06.2020    16823    21    4    

35

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

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

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

2 стартмани

22.08.2023    2197    24    progmaster    7    

3

Модель состояния для MVC

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

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

1 стартмани

05.07.2022    3843    kalyaka    4    

29

Табло очереди заказов на экран телевизора

WEB-интеграция Работа с интерфейсом Платформа 1С v8.3 1С:Розница 2 Платные (руб)

Связка из веб-приложения и расширения для 1С: Розница 2.3.

3600 руб.

29.04.2022    12200    1    5    

10

Условное оформление элементов форм в пользовательском режиме 1С (управление видимостью и доступностью элементов форм)

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

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

6000 руб.

18.01.2022    8885    1    2    

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

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

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

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


Обратите внимание: поправил модуль в публикации. itemTitle - всегда Массив (раньше было по условию).
16. check2 356 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 356 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 356 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)? Сравнивал все элементы до и после передвижения - все свойства линии кажутся одинаковыми.
Прикрепленные файлы:
Оставьте свое сообщение