Создание узлов

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

Схема узла

Любой узел определяет его форма, входы и имя.

Наименование

Имя влияет на правильность обработки в программе, потому назвать узлы нужно правильно:

Форма

Генерация формы происходит автоматически, однако существует возможность изменить размеры узла. Стандартно при небольшом количестве входов и выходов узел имеет форму квадрата 1x1 (блок), однако для циклов и похожих узлов форма расширяется по высоте, доходя до 1x2 (два блока). Расширение по горизонтали возможно. Слева узла находятся входы, справа выходы.

Кроме простых входов существуют разделители и пустые входы. Пустые входы представляют собой маленький вход, но без обозначения (к нему нельзя подключить другой узел). Разделитель, в свою очередь, пытается разделить коннекторы на блоки. Например, если последовательность выходов (сверху вниз) такова - (‘ctrl’, ‘sep’, ‘ctrl’), то результат - форма узла будет 1x2 (два блока), а выходы расположатся по одному на каждый блок.

Генерация узла

У создания узлов есть несколько вариантов:

Создание узла

Такой вид генерации является базовым и используется во всех остальных. Для создания требуется базовое знание структуры Python и в частности словарей. Для создания узла требуется создать словарь со следующей структурой:

node = {
    # кортеж входов с форматом ('single'|'multiple', [<type>, ['small', ['directed']]])
    'inputs': (
        ('single', 'ctrl'),
    ),  

    # кортеж выходов ('single'|'multiple', [<type>, ['small', ['directed']]])
    'outputs': (
        ('single', 'int'),
    ),

    # кортеж цветов выходов (типов) - опционально
    'outputs_color': ('int',), 
    
    # пользовательский символ - опционально
    'user_symbol': '&',

    # время работы узла - опционально  
    'time': '~',  
    
    # наименование узла (уникальное и используемое в обработке узлов)
    'sync_name': 'length',  

    # наименование узла (уникальное и используемое в создании 
    # изображения и обработке узлов если не указано sync_name)
    'label': 'length',

    # описание внутри узла - опционально
    'inner': 'Len',  

    # дополнительное описание - опционально
    'desc': 'in',  
    
    # размер шрифта дополнительного описания - опционально
    'desc_size': 6,  

    # размер шрифта дополнительной информации - опционально
    'adds_size': 6,  

    # размер шрифта внутреннего описания - опционально
    'inner_size': 8,  
    
    # цвет заднего фона (r, g, b) - опционально
    'bg_color': (255, 255, 255), 

    # цвет границ (r, g, b) - опционально 
    'border_color': (0, 0, 0),  

    # толщина границ - опционально
    'border_width': 0.5,  
    
    # ширина узла - опционально
    'width': 1,  
    
    # подсказка при наведении - опционально
    'tooltip': { 
        # название узла
        'label': 'Label',  

        # описание узла - опционально
        'desc': 'Node description', 
 
        # список описаний входов узла - опционально
        'inputs': [  
            # кортеж из краткого обозначения узла и описания
            ('Input 1', 'input 1 desc'),  
            ('Input 2', 'input 2 desc'),
        ],

        # список описаний выходов узла - опционально
        'outputs': [  
            ('Output 1', 'output 1 desc'),
            ('Output 2', 'output 2 desc'),
        ],

        # дополнительная информация - опционально
        'adds': 'Node additional description',  

        # ширина строки - опционально
        'word_wrap': 30  
    }
}

Входы и выходы

Для описания входов или выходов используется кортежа со специальной структурой. Первым элементом является количество входных соединений - single и multiple. После него может идти тип. После могут идти два параметра - small и directed. Обязательным всегда является первый элемент. Остальные могут быть в разных комбинациях, однако тип данных всегда должен быть раньше параметров.

Вместо количества входных соединений можно использовать дополнительные обозначения (разделители):

Если в кортеже лишь одно значение, то нужно написать запятую после него, чтоб программа понимала, что это кортеж.

Примеры:

(
    # одиночный, бестиповой
    ('single',), 
    # одиночный, тип bool
    ('single', 'bool'),
    # множественный, бестиповой
    ('multiple',),
    # множественный, тип char
    ('multiple', 'char'),
    # множественный, тип real, направленный
    ('multiple', 'real', 'directed'),
    # множественный, тип int, уменьшенный
    ('multiple', 'int', 'small'),
    # множественный, тип ctrl, уменьшенный и направленный
    ('multiple', 'ctrl', 'small'),
    # множественный, бестиповой, уменьшенный
    ('multiple', 'small'),
)

Имя узла

Имя узла определятся двумя способами. Используя только параметр label и используя sync_name. В первом случае название будет принадлежать как изображению, как обозначению в обработчике, так и в библиотеке (если она создаваться будет). Во втором случае label будет относиться к обозначению в библиотеке, а sync_name уже к обозначению в обработчике и к изображению.

Разница не большая, однако иногда требуется обозначить узлы с разным функционалом одинаковым именем.

Подсказка

Всплывающая подсказка - информация показываемая при наведении курсора на узел в Draw.io. Позволяет быстро получить информацию об узле. Очень полезно, если постоянно забывается функция узла. Всплывающая подсказка не обязательна. У подсказки есть название, описание, дополнительная информация, а также информация по входам и выходам.

Описание входов - это список из кортежей. Каждый кортеж должен состоять из обозначения и описания. Описание отображается в подсказке.

Запуск генерации узла

Для простого создания узла не требуется использовать модифицированный Python. Однако для создания описания узла в формате PNG все же требуется установить библиотеку PIL. Для установки требуется написать в консоли устройства или Repl.it команду pip install pillow. Последний (Repl.it) чаще всего автоматически устанавливает все требуемые библиотеки автоматически.

Далее требуется перейти в скрипт new_node.py и перейти в раздел if __name__ == "__main__": .... Внутри него есть пример узла и готовые закомментированные инструкции. Для их использования достаточно убрать решетку. Переменные svg_save_folder и lib_save_folder определяют места, куда сохранятся файлы SVG и DRAWIO, library_name - название библиотеки.

svg_save_folder = "<путь к созданным изображениям>"
lib_save_folder = "<путь к созданной библиотеке>"
library_name = "<название создаваемой библиотеки>"

Переменная node хранит в себе информацию по узлу. Если создается один узел, то достаточно прописать в ней описание узла

node = {
    'inner': 'Join',
    'label': 'join',
    ...
}

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

nodes_info = [
    {...},
    {...}
]

Простой узел

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

generate_node(node, svg_save_folder)

Для создания рабочего узла нужно перетащить изображение на рабочую область. Стиль можно добавить через правую кнопку по узлу (выбрав “Edit Style”) и добавив полученный стиль в конец окна.

Узел-Функция

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

generate_function(node, svg_save_folder, lib_save_folder)

Библиотека

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

generate_library(library_name, nodes_info, svg_save_folder, lib_save_folder)

Дополнительные возможности

К обучению