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

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

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

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


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

См. также

Использование языковой модели GPT3 для создания интерфейса 1С на естественном языке

Работа с интерфейсом Платформа 1С v8.3 1С:Управление торговлей 11 Бесплатно (free)

Я взял типовую конфигурацию УТ редакции 11.5 Немного доработал запрос к языковой модели GPT-3 и получил возможность обращаться к учетной системе на естественном языке

15.01.2023    10501    mkalimulin    122    

77

{UI/UX} Свой всплывающий информер у элемента формы

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

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

12.08.2022    4887    rpgshnik    36    

82

Динамическая кнопка VS Комбинация клавиш

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

Часто требуется ко всем формам или к списку форм привязать новые действия. Но как это сделать не меняя каждую форму и в идеале не меняя конфигурацию? Ниже будет описано, как запрограммировать новые действия через расширение (т.е. не меняя конфигурации) и сделать это универсально (не меняя каждую форму).

08.08.2022    5729    sapervodichka    33    

76

Система контроля ведения учета [БСП]

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

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    5452    quazare    8    

101

Хитрости СКД. Часть 3

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

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

28.05.2022    6638    milkers    11    

87

Базовые принципы работы с регламентными заданиями подсистем БСП

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

В очередной публикации рассмотрим некоторые базовые приемы работы с регламентными заданиями в рамках библиотеки стандартных подсистем

22.05.2022    9182    quazare    24    

55

Модули общего назначения - готовые полезные функции и процедуры конфигураций на БСП

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

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

25.04.2022    10071    quazare    11    

130

Полезный код для программистов 1С (часть 3). Подготовка печатных форм + подсистема Управление печатью (БСП)

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

Мы все любим 1С, не так ли? Вот дает 1С прекрасный механизм возможности модификации макетов печатных форм в БСП. А из всех рекомендаций это получение макета и заполнение параметров областей. И вы спросите: "А что не так... ты печатные формы накодить не можешь без указаний сверху?". Да вот в том то и дело, что я могу все. А вот пользователям от такого механизма пользы 0, если из всех доступных изменений остаются только шрифты, да текст произвольный накинуть. А ведь можно больше, надо только соблюдать несколько правил при подготовке печатных форм...

07.03.2022    9768    vandalsvq    0    

56

Конвертируем печатную форму pdf в картинку (jpg, gif, png и прочие) на сервере

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

Была поставлена интересная задача конвертировать печатную форму в файл картинку. По условию задачи клиенту на почту нужно присылать только файл картинку (jpg, gif).

22.12.2021    6308    John_d    25    

46

Программный интерфейс для доработки форм

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

Реализовал простой способ программного создания новых элементов, команд и реквизитов на форме.

25.11.2021    6687    AtamanovYS    19    

121

Несколько простых приемов для удобной работы в конфигураторе

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

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

12.11.2021    13492    acces969    95    

142

Как читать чужой код? Часть 4. Программный интерфейс. Исправление чужих доработок

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

Во всех вакансиях есть требование - умение читать чужой код. Но ни на одних курсах специально этому не учат. Чтобы устранить это противоречие, пишу данную статью. Рассмотрю случаи, в которых нам необходимо разбирать чужой код, поймём, чей код мы пытаемся разобрать, зачем и, главное, как. В статье описан личный опыт длиною в 18 лет начиная с версии платформы 7.7. Статья будет большой, набираемся терпения). Статья содержит в себе описание сценариев разбора кода, т.е. набор шагов. В статье не получится показать это на практике. Для этого планирую сделать онлайн или оффлайн курс, где на примерах будет показан разбор незнакомого кода. Статья разбита на 4 публикации для удобства изучения.

20.09.2021    4931    biimmap    9    

53

Из Word в табличный документ

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

Быстро и просто: текст, списки, таблицы. Готовый код

18.08.2021    4687    Yashazz    6    

63

Префиксация объектов - полезный типовой функционал БСП

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

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

21.06.2021    10820    quazare    4    

61

Динамический список и поиск... неприятностей

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

Страх и ненависть в поиске по динамическому списку, или "Кое-что о неоптимальном отборе".

17.03.2021    11212    Yashazz    37    

51

Программное условное оформление динамического списка, раскраска строк списка по цветам справочника или любым другим условиям (условное оформление)

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

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

30.11.2020    16574    SizovE    6    

46

Сохранение настроек

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

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

22.11.2020    9780    ixijixi    8    

67

[mobile] Переносим HTML интерфейс на 1С

Работа с интерфейсом Мобильная разработка Платформа 1С v8.3 Мобильная платформа Конфигурации 1cv8 Бесплатно (free)

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

02.11.2020    13634    leobrn    82    

106

Произвольные колонтитулы и повтор шапки таблицы в табличном документе (функция)

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

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

07.10.2020    13455    ellavs    7    

39

Лайфхаки для разработчиков 1С. Часть 1

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

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

30.09.2020    9637    Neti    47    

68

Рендеринг элементов управляемого интерфейса

Работа с интерфейсом Платформа 1С v8.3 Управляемые формы Россия Бесплатно (free)

Реализация отображения всего состояния формы проще, чем работа по изменениям. Однако использование идеи разделения алгоритмов на программные слои MVC и построения реактивных систем позволяет получить не только простые и масштабируемые решения, но и производительные интерфейсы. Рассмотрим примеры таких реализаций на основе использования фреймворка «Управление состоянием»: Информационная надпись, Заголовок формы, Свертываемая группа, Отключаемые панели.

22.09.2020    5047    kalyaka    5    

39

[Общий модуль] Динамическое формирование интерфейса

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

Библиотека готовых функций для разработки интерфейса формы и размещения на нём элементов формы с помощью программного кода.

28.08.2020    30633    rpgshnik    88    

284

Самый простой парсинг и обработка веб-страниц в 1С

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

Рассмотрим самый простой парсинг веб-страниц средствами платформы 1С и еще некоторые полезные приемы работы с веб-страницами.

07.08.2020    24849    Infostart    30    

145

Полезные встроенные функции для работы с печатными формами и не только на УТ 11.4 и БП 3.0 (сравнение)

Универсальные функции Платформа 1С v8.3 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 Россия Бесплатно (free)

В данном обзоре приведу примеры встроенных используемых функций для работы с печатными формами на примерах конфигураций Управление торговлей 11.4 и Бухгалтерия 3.0.

10.07.2020    15009    quazare    7    

86

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

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

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

08.05.2020    177889    user5300    40    

288

Получаем уровень группировки ячейки табличного документа

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

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

23.03.2020    8729    maxx    16    

57

Treemapping — способ визуализации данных древовидной структуры. Карта-схема дерева

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

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

18.02.2020    8531    randomus    20    

75

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

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

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

13.01.2020    71417    aximo    23    

199

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

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

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

25.12.2019    11268    brooho    21    

170

Автоматическое создание связанного объекта в базе 1С: Документооборот через бесшовную интеграцию

Универсальные функции Механизмы типовых конфигураций Платформа 1С v8.3 1С:Документооборот 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Бесплатно (free)

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

23.12.2019    6132    pavelpribytkin96    3    

39

[СКД] Вывод картинки в результат любого отчета на СКД

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

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

09.12.2019    16085    John_d    18    

122

Управляемые формы. Изменение формы списка или формы объекта без внесения изменений в типовые формы (без использования расширений)

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

Вносим изменения в типовые формы объектов (документы, справочники, журналы, обработки, общие формы). Не снимая с поддержки эти формы. Создаем программно элементы из общего модуля. Для примера рассмотрю добавление колонки "Скрепка" в форму списка документа. Если к документу привязан файл, то в списке в новой колонке должна отображаться "скрепка".

12.11.2019    21371    John_d    29    

125

Быстрое создание наполненных коллекций

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

Разберем самые частые способы создания коллекции, значения которой известны заранее. И сравним скорость их выполнения.

28.10.2019    9130    SeiOkami    69    

68

Преобразование XML в таблицу значений или иной объект 1С методом XSL преобразования

Универсальные функции Файловый обмен (TXT, XML, DBF), FTP Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

24.10.2019    21289    kraspila    33    

58

Обертка функций Excel на русском. Ускорение процесса разработки.

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

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

24.10.2019    8927    DmitryKotov    6    

56

Методика независимой системы "Подписки на события"

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

В этой небольшой статье я хочу вам предложить пошаговое описание разработки системы управления "Подписками на события" для документов. Цель разработки - возможность управления подписками в вашей конфигурации, не прибегая к программированию через конфигуратор. Думаю, будет полезно и интересно!

17.10.2019    18735    aximo    35    

71

Создание асинхронных виджетов

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

Описание нескольких способов создания асинхронных виджетов для 1С:Предприятия. Рассматриваются способы с использованием HTTP-сервисов и фоновых заданий.

16.10.2019    16361    Infostart    19    

156