Поделиться через


Настройка элементов и панели элементов

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

Определение панели элементов

В Обозревателе DSL разверните узел "Редактор" и узлы под ним. Обычно при этом отрывается иерархия следующего вида:

Editor
     Toolbox Tabs
        MyDsl          //a tab
           Tools
               ExampleElement      // an element tool
               ExampleRelationship // a connection tool

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

  • Создавать новые таблицы. Вкладки определяют заголовки разделов в панели элементов.

  • Создавать новые средства.

  • Копировать и вставлять средства.

  • Перемещать средства вверх или вниз по списку.

  • Удалять вкладки и средства.

Важно!

Чтобы добавить или вставить элементы в Обозреватель DSL, щелкните прародителя нового узла правой кнопкой мыши. Например, чтобы добавить средство, щелкните правой кнопкой мыши вкладку, а не узел "Сервис ". Чтобы добавить вкладку, щелкните правой кнопкой мыши узел редактора.

Свойство "Значок панели элементов" каждого средства ссылается на файл растрового изображения 16x16. Эти файлы обычно хранятся в папке Dsl\Resources .

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

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

Добавление средства в панель элементов

  1. Средство элемента обычно создают после создания класса фигуры и его сопоставления с классом домена.

    Средство подключения обычно создают после создания класса соединителя и его сопоставления со ссылочным отношением.

  2. В Обозреватель DSL разверните узел редактора и узел вкладок панели элементов.

    Щелкните правой кнопкой мыши узел вкладки панели элементов и выберите команду "Добавить новый элемент" или "Добавить новое средство Подключение ion".

  3. Задайте свойство "Значок панели элементов", чтобы ссылаться на растровое изображение 16x16.

    Если вы хотите определить новый значок, создайте файл растрового изображения в Обозреватель решений в папке Dsl\Resources. Файл должен иметь следующие значения свойств: Build Action = Content; Копирование в выходной каталог = не копируется.

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

    Для средства соединителя: задайте свойству Подключение ion Builder средства одно из элементов, предлагаемых в раскрывающемся списке. Построители подключений автоматически создаются при сопоставлении соединителя с доменной связью. Сразу после создания соединителя, как правило, выбирается соответствующий построитель подключений.

  5. Чтобы протестировать DSL, нажмите клавишу F5 или CTRL+F5, а в экспериментальном экземпляре Visual Studio откройте пример файла модели. На панели элементов должно появиться новое средство. Перетащите его на схему, чтобы проверить, создает ли оно новый элемент.

    Если средство не отображается, остановите экспериментальную visual Studio. В меню "Пуск Windows" введите visual Studio, а затем выполните команду "Сброс экспериментального экземпляра Microsoft Visual Studio", соответствующую вашей версии Visual Studio. В меню Построить выберите пункт Перестроить решение. Затем проверьте DSL еще раз.

Настройка средств элемента

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

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

    Эти настройки также влияют на процесс вставки и перетаскивания элемента.

    Дополнительные сведения см. в разделе "Настройка создания и перемещения элементов".

  • Написать код, чтобы настроить средство на возможность создания групп элементов. Средство запускается методами из файла ToolboxHelper.cs, которые можно переопределить. Дополнительные сведения см. в разделе "Создание групп элементов" из средства.

Создание групп элементов из инструмента

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

Следующий пример взят из DSL, в котором есть тип "Транзистор". Каждый транзистор имеет три именованных контакта. Средство элемента для транзисторов хранит прототип, содержащий четыре элемента модели и три ссылки отношения. Когда пользователь перетаскивает средство на схему, создается экземпляр прототипа, который связывается с корнем модели.

Этот код переопределяет метод, определенный в dsl\GeneratedCode\ToolboxHelper.cs.

Дополнительные сведения о настройке модели с помощью кода программы см. в статье "Навигация и обновление модели в коде программы".

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

  public partial class CircuitsToolboxHelper
  {
    /// <summary>
    /// Toolbox initialization, called for each element tool on the toolbox.
    /// This version deals with each Component subtype separately.
    /// </summary>
    /// <param name="store"></param>
    /// <param name="domainClassId">Identifies the domain class this tool should instantiate.</param>
    /// <returns>prototype of the object or group of objects to be created by tool</returns>
    protected override ElementGroupPrototype CreateElementToolPrototype(Store store, Guid domainClassId)
    {
        if (domainClassId == Transistor.DomainClassId)
        {
            Transistor transistor = new Transistor(store);

            transistor.Base = new ComponentTerminal(store);
            transistor.Collector = new ComponentTerminal(store);
            transistor.Emitter = new ComponentTerminal(store);

            transistor.Base.Name = "base";
            transistor.Collector.Name = "collector";
            transistor.Emitter.Name = "emitter";

            // Create an ElementGroup for the Toolbox.
            ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
            elementGroup.AddGraph(transistor, true);
            // AddGraph includes the embedded parts

            return elementGroup.CreatePrototype();
        }
        else
        {
            return base.CreateElementToolPrototype(store, domainClassId);
}  }    }

Настройка средств Подключение ion

Как правило, средство элемента создается при создании нового класса соединителя. Кроме того, можно переопределить одно средство, разрешив типам и обеих сторон определять тип отношения. Например, можно определить одно средство подключения, которое может создавать как отношения типа "человек — человек", так и отношения типа "человек — город".

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

При создании ссылочного отношения между доменными классами автоматически создается построитель подключения, который можно использовать при сопоставлении средства подключения. Дополнительные сведения о создании средств подключения см. в разделе "Настройка панели элементов".

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

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

Структура построителей подключения

Построители подключений содержат одну или несколько директив подключения связей, которые определяют доменные связи, а также исходные и целевые элементы. Например, в шаблоне решения потока задач можно увидеть КомментарийReferencesSubjectsBuilder в Обозреватель DSL. Этот построитель подключений содержит одну директиву connect link connect с именем CommentReferencesSubjects, которая сопоставляется с связью домена CommentReferencesSubjects. Эта директива подключения связи содержит директиву исходной роли, указывающую на класс домена Comment, и директиву целевой роли, указывающую на класс домена FlowElement.

Использование построителей подключений для ограничения ограниченным исходных и целевых ролей

Построители подключений можно использовать для ограничения вхождения некоторых классов в исходную или в целевую роль определенной доменной связи. Например, у вас есть базовый класс домена, имеющий доменную связь с другим классом домена, но вы не хотите, чтобы все производные этого базового класса получали в этой связи те же самые роли. В решении потока задач есть четыре конкретных класса домена (StartPoint, EndPoint, MergeBranch и Синхронизация), которые наследуются непосредственно от абстрактного класса FlowElement и двух конкретных классов доменов (Task и ObjectInState), которые наследуются косвенно от него. Существует также ссылочная связь Flow, которая принимает классы домена FlowElement как в исходной роли, так и в целевой роли. Однако экземпляр класса домена EndPoint не должен быть источником связи Flow , а экземпляр класса StartPoint — целевым объектом связи Flow . Построитель подключений FlowBuilder имеет директиву подключения по ссылке с именем Flow, которая указывает, какие классы домена могут играть исходную роль (Task, MergeBranch, StartPoint и Синхронизация) и которая может играть целевую роль (MergeBranch, Endpoint и Synchronization).

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

В решении потока задач средство подключения потока используется для рисования экземпляров связей потока и домена ObjectFlow . Построитель подключений FlowBuilder содержит директиву подключения потока,описанную ранее, две директивы подключения канала с именем ObjectFlow. Эти директивы указывают, что экземпляр связи ObjectFlow может быть нарисован между экземплярами класса домена ObjectInState или из экземпляра ObjectInState в экземпляр задачи, но не между двумя экземплярами задачи или от экземпляра задачи к экземпляру ObjectInState. Однако экземпляр связи потока может быть нарисован между двумя экземплярами задачи. При компиляции и запуске решения потока задач можно увидеть, что рисование потока из экземпляра ObjectInState в экземпляр задачи создает экземпляр ObjectFlow, но рисование потока между двумя экземплярами задачи создает экземпляр потока.

Пользовательский код для построителей подключения

В пользовательском интерфейсе имеются четыре флажка, определяющие различные типы настройки построителей подключений:

  • Поле "Пользовательское принятие проверка" в директиве исходной или целевой роли

  • Поле "Настраиваемый проверка подключения" в директиве исходной или целевой роли

  • Поле "Использование настраиваемого подключения проверка в директиве connect"

  • Свойство Is Custom построителя подключений

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

Примечание.

Чтобы добавить пользовательский код, создайте определение разделяемого класса в файле кода отдельно от файлов кода, находящихся в папках GeneratedCode. Чтобы не потерять свою работу, не изменяйте созданные файлы кода. Дополнительные сведения см. в разделе "Переопределение и расширение созданных классов".

Создание пользовательского кода подключения

В каждой директиве подключения ссылки вкладка "Директивы исходной роли" определяет из типов, которые можно перетаскивать. Аналогичным образом, вкладка "Директивы целевой роли" определяет, какие типы можно перетаскивать. Для каждого типа можно дополнительно указать, разрешать ли подключение (для этой директивы подключения ссылки), задав флаг custom Accept , а затем укажите дополнительный код.

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

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

Подключение входить в outPort из вложенного компонента

Connection Builder

В связи с этим необходимо указать, что подключение может идти от вложенного компонента к типу OutPort. Чтобы указать такое подключение, задайте для типа InPort custom Accept в качестве исходной роли и типа OutPort в качестве целевой роли в окне сведений DSL, как показано на следующих рисунках:

Директива Подключение связи в DSL Обозреватель

Connection builder image

Директива Подключение ссылки в окне сведений DSL

Link connect directive in DSL Details window

После этого в класс ConnectionBuilder необходимо предоставить методы:

  public partial class ConnectionBuilder
  {
    /// <summary>
    /// OK if this component has children
    /// </summary>
    private static bool CanAcceptInPortAsSource(InPort candidate)
    {
       return candidate.Component.Children.Count > 0;
    }

    /// <summary>
    /// Only if source is on parent of target.
    /// </summary>
    private static bool CanAcceptInPortAndInPortAsSourceAndTarget                (InPort sourceInPort, InPort targetInPort)
    {
      return sourceInPort.Component == targetInPort.Component.Parent;
    }
// And similar for OutPorts...

Дополнительные сведения о настройке модели с помощью кода программы см. в статье "Навигация и обновление модели в коде программы".

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

Рекомендации по определению построителей подключений

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

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

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