ADN Open CIS
Сообщество программистов Autodesk в СНГ

30/01/2014

Легкое создание кнопок на ленте для вызова внешних команд

Создавая собственную внешнюю команду в интерфейсе Revit ее можно вызвать двумя способами:

Описать внешнюю команду в файле манифеста addin

Код - XML: [Выделить]
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RevitAddIns>
  3.   <AddIn Type="Command">
  4.     <Text>Command PipeCreation</Text>
  5.     <Description>Some description for PipeCreation</Description>
  6.     <Assembly>PipeCreation.dll</Assembly>
  7.     <FullClassName>PipeCreation.Command</FullClassName>
  8.     <ClientId>da5307a6-0182-4f28-8387-dd0de47446ec</ClientId>
  9.     <VendorId>ADNCIS</VendorId>
  10.     <VendorDescription>http://adn-cis.org </VendorDescription>
  11.   </AddIn>
  12. </RevitAddIns>

В этом случае Revit автоматически добавит команду в раскрывающийся список Внешние инструменты на вкладке Надстройки

 

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

В Revit есть несколько типов кнопок. Самый простой и часто используемый – PushButton.

 

PushButton может быть высотой с размер панели на ленте, а также можно разместить кнопки в вертикальный ряд по три кнопки, соответственно размер кнопки будет 1/3 от высоты панели.

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

Создавать свои вкладки, панели и кнопки необходимо в методе OnStartup класса, реализуемого интерфейс IExternalApplication. Данный класс необходимо зарегистрировать в файле манифеста

Код - XML: [Выделить]
  1.   <AddIn Type="Application">
  2.     <Name>Application RibbonUtilSample</Name>
  3.     <Assembly>RibbonUtilSample.dll</Assembly>
  4.     <FullClassName>RibbonUtilSample.App</FullClassName>
  5.     <ClientId>1ff8229e-eb6d-4d70-a947-0f888cdb031d</ClientId>
  6.     <VendorId>ADNCIS</VendorId>
  7.     <VendorDescription>http://adn-cis.org</VendorDescription>
  8.   </AddIn>

При загрузке Revit будет выполнен метод OnStartup объявленного класса.

Для создания кнопки, необходимо:

1)      Создать объект класса PushButtonData в котором необходимо указать:

  • Идентификатор кнопки. Задается строкой. Должен быть уникальным среди всех кнопок в Revit. Задается строкой
  • Название кнопки, которое будет видеть пользователь
  • Путь к файлу сборки, в котором находится команда, которую нужно вызвать при нажатии на кнопку
  • Полное название класса команды, т.е. класса, реализующего интерфейс IExternalCommand, находящегося в сборке, указанной в предыдущем параметре.
  • Дополнительно можно задать изображение для кнопки.
  • Также можно задать дополнительное описание команды, которое пользователь будет видеть при наведении курсора мыши на кнопку

2)      Добавить на панель новую кнопку, передав объект класса PushButtonData. Саму панель предварительно нужно получить.

Полный код, создающий новую вкладку и затем панель, выглядит примерно так:

Код - C#: [Выделить]
  1.        public Result OnStartup(UIControlledApplication a)
  2.         {
  3.             var assembly = Assembly.GetExecutingAssembly();
  4.  
  5.             PushButtonData pushButtonData
  6.                 = new PushButtonData("adncisButton",
  7.                     "ADN-CIS",
  8.                     assembly.Location,
  9.                     "RibbonUtilSample.Command");
  10.  
  11.             pushButtonData.LongDescription = "Пример описания для команды";
  12.  
  13.             // ищем путь к файлу изображения
  14.             var assemblyDir = new FileInfo(assembly.Location).DirectoryName;
  15.             var imagePath = Path.Combine(assemblyDir, "adn-cis-logo.png");
  16.             pushButtonData.LargeImage = new BitmapImage(new Uri(imagePath));
  17.  
  18.             // Создадим новую вкладку
  19.             // При этом нельзя проверить есть ли уже такая вкладка или нет
  20.             a.CreateRibbonTab("ADN-CIS");
  21.  
  22.  
  23.             // Создаем новую панель на вкладке ADN-CIS
  24.             var panel = a.CreateRibbonPanel("ADN-CIS", "Панель ADN-CIS");
  25.  
  26.             // Добавляем кнопку на панель
  27.             panel.AddItem(pushButtonData);
  28.  
  29.             return Result.Succeeded;
  30.         }

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

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

2)      Необходимость указывать название класса команды в виде строки. А значит нет подсказки при вводе наименования. Необходимо беспокоиться о названии при переименовании класса команды

3)      Изображение необходимо задавать в виде объекта класса ImageSource. Это конечно решаемо, но создает некие трудности, например, нельзя просто так вставить изображение из ресурсов.

4)      Невозможно проверить есть ли вкладка с таким именем или нет. Это необходимо, например, если вы создаете несколько своих приложений в разных проектах и их необходимо поместить на одну вкладку.

5)      То же самое, но с панелью

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

Создание кнопки с помощью утилиты становится гораздо проще. Ту же самую кнопку, можно создать гораздо проще и понятнее с помощью всего лишь одного выражения:

Код - C#: [Выделить]
  1.             Ribbon.GetApplicationRibbon(a)
  2.                 .Tab("ADN-CIS")
  3.                 .Panel("Панель RibbonUtil")
  4.                 .CreateButton<Command>("adncis2",
  5.                     "ADN-CIS2", b =>
  6.                     {
  7.                         b.SetLargeImage(Resources.adn_cis_logo);
  8.                         b.SetLongDescription("Описание кнопки, созданной с помощью утилиты");
  9.                     });

Результат создания двух кнопок стандартным методом и с помощью утилиты выглядит так:

 

Утилита устранят все недостатки создания кнопок стандартным методом и обладает интуитивно понятным, так называемым, fluent интерфейсом.

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

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

 

Для создания 8 кнопок также было использовано всего одно выражение:

Код - C#: [Выделить]
  1.             Ribbon.GetApplicationRibbon(a)
  2.                 .Tab("MyTab")
  3.                 .Panel("Panel1")
  4.  
  5.                 .CreateButton("btn1",
  6.                               "Button1",
  7.                               typeof (Command1),
  8.                               btn => btn
  9.                                 .SetLargeImage(Resources
  10.                                     ._1348119708_face_monkey_32)
  11.                                 .SetSmallImage(Resources
  12.                                     ._1348119708_face_monkey_16))
  13.  
  14.                 .CreateSeparator()
  15.  
  16.                 .CreateButton<Command2>("btn2",
  17.                         "Button2",
  18.                         btn => btn
  19.                             .SetLongDescription("This is a description of the button2")
  20.                             .SetLargeImage(Resources
  21.                                 ._1348119643_face_glasses_32))
  22.                 
  23.                 .CreateStackedItems(si=>
  24.                     si
  25.                         .CreateButton<Command3>("btn3", "Button3",
  26.                                 btn=>btn
  27.                                     .SetSmallImage(Resources.
  28.                                     _1348119594_preferences_system_16))
  29.                         .CreateButton<Command4>("btn4", "Button4",
  30.                                 btn=>btn
  31.                                     .SetSmallImage(Resources.
  32.                                         _1348119621_internet_web_browser_16)))
  33.                 .CreateSeparator()
  34.  
  35.                 .CreateStackedItems(si =>
  36.                     si
  37.                         .CreateButton<Command3>("btn3_1", "Button3",
  38.                                 btn => btn
  39.                                     .SetSmallImage(Resources
  40.                                         ._1348119594_preferences_system_16))
  41.                         .CreateButton<Command4>("btn4_1", "Button4",
  42.                                 btn => btn
  43.                                     .SetSmallImage(Resources
  44.                                         ._1348119621_internet_web_browser_16))
  45.                         .CreateButton<Command1>("btn1_1", "Button1",
  46.                                 btn=>btn
  47.                                     .SetSmallImage(Resources
  48.                                         ._1348119553_face_smile_big_16)))
  49.                 ;

Для использования утилиты вам необходимо добавить сборку VCRevitRibbonUtil.dll в ваш проект и добавить

Код - C#: [Выделить]
  1. using VCRevitRibbonUtil;

 

Скачать исходный код утилиты вы можете на GitHub или в виде архива.

 

Автор: Виктор Чекалин
Автор перевода: Виктор Чекалин

Обсуждение: http://adn-cis.org/forum/index.php?topic=494

Опубликовано 30.01.2014