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

ADN Club => AutoCAD .NET API => Тема начата: avc от 26-03-2021, 13:28:41

Название: Подключить ленту из cuix
Отправлено: avc от 26-03-2021, 13:28:41
Наверно все сталкивались с ситуацией, когда Автокад упорно не показывает ленты (Ribbon) из CUIX плагина. Устал помогать пользователям решать эту проблему. Вот поставил себе 2022 - и опять эта проблема.
Обычно это происходит при установке нового Автокад или нового плагина или новой версии старого плагина. В списке файлов частичной кастомизации мой cuix присутствует, панели инструментов нарисовались (хотя включен ленточный интерфейс, зачем панели-то?). А лента Add-ins пуста и других самодельных лент тоже нет. Причем их нет даже в списке выключенных. Можно почистить папку support и перезагрузить Автокад несколько раз, покликать workspace-ами, чтоб ленты все-таки нарисовались. Но может есть какой-то программный способ включить риббонки? Я уже сделал код, который грузит CUIX, если он еще не загружен. Но тут другой случай, мой cuix уже есть в CustomizationSection.PartialCuiFiles
Название: Re: Подключить ленту из cuix
Отправлено: Привалов Дмитрий от 26-03-2021, 14:02:43
хотя включен ленточный интерфейс, зачем панели-то?
Ленточный интерфейс не отключает панели, меню и т.д. Он как-бы дополнение к уже имеющимся.

А лента Add-ins пуста и других самодельных лент тоже нет.
Частенько связано с рабочими пространствами. Т.е. вроде должно появиться, но нет. Обычно приходится заходить в адаптацию рабочего пространства и настраивать руками.
И, если не путаю, то меню и панели появляются автоматом. А с лентой и панелью быстрого доступа приходится дополнительно настраивать.
Если частичный CUIX уже был подгружен в основной CUIX то иногда приходиться выгружать/загружать частичный CUIX или даже заменять основной.

Но может есть какой-то программный способ включить риббонки?
Не знаю как программно, не требовалось.
Можно сделать настройки в основном файле адаптации и частичном. И после подгрузки лента должна добавиться в текущее рабочее пространство.

В настройках вкладки ленты нужно выставить настройки
Добавить к рабочим пространствам
Объединять или добавлять вкладку

И что не очевидно, нужно задать Псевдонимы

Из справки:
Отображение вкладок ленты из частичного файла CUIx
При загрузке вкладок ленты из частичного файла CUIx свойство "Поведение рабочего пространства" можно использовать для управления способом обработки вкладок ленты, которые, возможно, используют один и тот же псевдоним в главном и в частичном файлах CUIx. Опция "Только добавлять вкладку" приводит к отображению каждой вкладки ленты, загружаемой с рабочим пространством, как вкладки этого рабочего пространства. А опция "Только объединять вкладку" приводит к отображению вкладок ленты из частичного файла CUIx только при наличии для них соответствующих псевдонимов в главном файле CUIx. Опция "Объединять или добавлять вкладку" приводит к объединению вкладки прежде, чем на ленте будет создана новая вкладка.

Название: Re: Подключить ленту из cuix
Отправлено: avc от 26-03-2021, 14:32:16
иногда приходиться выгружать/загружать частичный CUIX или даже заменять основной.
Да, приходится выгружать/загружать. И учить этому всех пользователей. Могу выгрузить программно, но как узнать что это надо сделать, что лента не отображена?
В свойствах всех Tabs задано "Merge or add tab"
А вот алиасы у табов и панелей как попало - где-то не задал, где-то одинаковые. Не знал где они вообще используются. Попробовал подправить. Задал всем уникальные псевдонимы. Ничего не изменилось.
Название: Re: Подключить ленту из cuix
Отправлено: Привалов Дмитрий от 26-03-2021, 14:49:37
Попробую подправить, но сильно сомневаюсь что проблема из-за этого.
Проблема не из-за этого, это если хочешь чтобы вкладки подгрузились в рабочее пространство, при подгрузке CUIX, то придется задать одинаковые алиасы в  основном и частичном файле.
Иначе механизм не сработает.

Проблемы из-за настроек отображения в самих рабочих пространствах.
Под каждым рабочим пространством ты указываешь какие вкладки ленты отображать, какие скрыть и в какой последовательности.
Название: Re: Подключить ленту из cuix
Отправлено: avc от 31-03-2021, 13:37:36
Итого. Чтоб просто проверить, загружены ли мои ленты в текущий workspace пришлось изобрести вот такого крокозябра:
Код - C# [Выбрать]
  1.     /// <summary>
  2.     /// загрузка CUIX если его еще нет в загруженных. проверяет обновление файла. проверяет, что загрузились ленты
  3.     /// </summary>
  4.     internal static void LoadMenu(string pluginPath, string pluginName)
  5.     {
  6.         string myCuiName = pluginName + ".cuix";
  7.         string myCuiFile = Path.Combine(pluginPath, myCuiName);
  8.         if (!File.Exists(myCuiFile))
  9.           return;
  10.  
  11.         string mainCuiFile = Application.GetSystemVariable("MENUNAME") + ".cuix";
  12.         if (!File.Exists(mainCuiFile)) //  бывает и так
  13.           return;
  14.  
  15.         CustomizationSection mainCui = new(mainCuiFile);
  16.         if (mainCui is null) return;
  17.         PartialCuiFileCollection partialFiles = mainCui.PartialCuiFiles;
  18.         if (partialFiles.Contains(myCuiName)) //мой Cuix уже загружен
  19.         {
  20.           // проверим, что мой новейший cuix скопирован из папки плагина в папку support
  21.           FileInfo myInf = new(myCuiFile);
  22.           FileInfo mainInf = new(mainCuiFile);
  23.           if (myInf.LastWriteTime > mainInf.LastWriteTime) // не 100% гарантия, но на практике можно и так проверить
  24.           {
  25.             mainCui.RemovePartialMenu(myCuiName, pluginName); // выгрузка, чтоб потом сразу опять загрузить
  26.             if (mainCui.IsModified) mainCui.Save();
  27.           }
  28.           else // с версией все хорошо, но проверим еще, что видны ленты или ленточные панели из моего cuix
  29.           {
  30.             //if ((Int16)Application.GetSystemVariable("RIBBONSTATE") == 0) return; всегда 0 если вызывать из InitializationPlugin
  31.             string wsname = (string)Application.GetSystemVariable("WSCURRENT");
  32.             if (IsNullOrEmpty(wsname)) return;
  33.             Workspace ws = mainCui.getWorkspace(wsname);
  34.             HashSet<string> paneles = AllRibbonPanels(ws.WorkspaceRibbonRoot); // все панели всех лент главного CUI
  35.             CustomizationSection myCui = new(myCuiFile);
  36.             RibbonRoot root = myCui.MenuGroup?.RibbonRoot;
  37.             if (root is null) return;
  38.             bool loaded = false;
  39.             foreach (RibbonTabSource myTab in root.RibbonTabSources)
  40.             {
  41.               //if (cs.LookupElement(myTab.ElementID) is not null) // так не работает - ElementID меняется при подключении к главному cui
  42.               //{ loaded = true; break; }
  43.               if (ws.WorkspaceRibbonRoot.FindTabReference(myCui.MenuGroup.Name, myTab.ElementID) is not null)
  44.               { loaded = true; break; } // нашли одну из лент из моего cuix
  45.               foreach (RibbonPanelSourceReference panel in myTab.Items)
  46.                 if (paneles.Contains(myCui.MenuGroup.Name + '.' + panel.PanelId)) // панели из частичного cui имеют составные Id
  47.                 { loaded = true; break; }
  48.               if (loaded) break; // нашли одну из панелей из моего cuix на ленте Add-ins
  49.             }
  50.             if (!loaded) // cuix загрузился, но панели в текущем пространстве не подключились
  51.             {
  52.               mainCui.RemovePartialMenu(myCuiName, pluginName);
  53.               if (mainCui.IsModified) mainCui.Save();
  54.             }
  55.             else
  56.               return;
  57.           }
  58.         }
  59.  
  60.         // мой cuix не загружен или пришлось выгрузить
  61.         if (mainCui.AddPartialMenu(myCuiFile))
  62.         {
  63.           if (mainCui.IsModified)
  64.           {
  65.             mainCui.Save();
  66.             Application.ReloadAllMenus();
  67.           }
  68.         }
  69.     }
  70.  
  71.     /// <summary>
  72.     /// Идентификаторы всех панелей всех лент
  73.     /// </summary>
  74.     static HashSet<string> AllRibbonPanels(WSRibbonRoot root)
  75.     {
  76.       HashSet<string> ret = new();
  77.       if (root is not null)
  78.         foreach (WSRibbonTabSourceReference tab in root.WorkspaceTabs)
  79.           foreach (WSRibbonPanelSourceReference panel in tab.Panels)
  80.             if (!ret.Contains(panel.PanelId))
  81.               ret.Add(panel.PanelId);
  82.       return ret;
  83.     }
Есть большие сомнения, что способ оптимальный. Но работает.
Точно такая же проблема есть и с загрузкой менюшки в классическом интерфейсе - надо бы отдельно запрограммировать проверку.
Не удалось понять включена ли лента. У workspace есть свойство MenuBar, но потерялось Ribbon.
Странно, что все элементы API не имеют ни имени, ни описания. Искать приходится только по Id. В результате я не могу найти ленту Add-ins. У нее странный цифровой Id в отличии от остальных стандартных лент. Скорее всего будет разным в разных версиях. Приходится перебирать вообще все все ленты.
Можно было вообще не парится, а просто перезагружать мой cuix при каждой инициализации плагина - задержка не особо заметная.
p.s.
написано для 2013 для совместимости. Возможно в более новых Автокадах это API стало более человечным.
Название: Re: Подключить ленту из cuix
Отправлено: Александр Ривилис от 31-03-2021, 13:54:31
Не удалось понять включена ли лента. У workspace есть свойство MenuBar, но потерялось Ribbon.
Код - C# [Выбрать]
  1.             RibbonControl ribbon = ComponentManager.Ribbon;
  2.             if (ribbon != null)
  3.             {
  4.               //  лента включена
  5.             }
Название: Re: Подключить ленту из cuix
Отправлено: avc от 31-03-2021, 14:04:02
ComponentManager - это из какого namespace? похоже нет его в API 2013
Название: Re: Подключить ленту из cuix
Отправлено: Александр Ривилис от 31-03-2021, 14:35:41
ComponentManager - это из какого namespace? похоже нет его в API 2013
Autodesk.Windows.ComponentManager (из AdWindows.dll) - есть в 2013
Название: Re: Подключить ленту из cuix
Отправлено: avc от 31-03-2021, 15:16:46
Не. Так тоже не получится. ComponentManager.Ribbon == null пока идет инициализация плагина. Команда Ribbon вызывается позже. Задача в том , чтоб у Workspace узнать - будет в нем открываться лента или нет.
Название: Re: Подключить ленту из cuix
Отправлено: Александр Ривилис от 31-03-2021, 15:30:01
RIBBONSTATE (https://knowledge.autodesk.com/ru/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2021/RUS/AutoCAD-Core/files/GUID-61E4267F-6957-4A0D-A2B6-69FB0674331C-htm.html)
Название: Re: Подключить ленту из cuix
Отправлено: avc от 31-03-2021, 15:43:14
Ribbonstate само собой всегда 0. Лента ж не открыта еще. Я об это в коде написал - закомментированная строка.
Но в общем-то это не главная проблема. Ну будет перезагружаться cuix, даже у тех кто до сих пор в классическом интерфейсе. Это не беда.
Просто вызвало удивление недоделанное API. Вдруг где-то запрятано что-то вроде Workspace.ShowRibbon, а я его в упор не вижу.
Так же как и WSRibbonTabSourceReference.Name или DisplayName - должен же быть, но его нет.
Название: Re: Подключить ленту из cuix
Отправлено: Александр Ривилис от 31-03-2021, 15:56:28
Ribbonstate само собой всегда 0. Лента ж не открыта еще.
Так чего же его проверять в Initialize(), если можно проверить когда ComponentManager.Ribbon != null
Название: Re: Подключить ленту из cuix
Отправлено: Привалов Дмитрий от 31-03-2021, 15:59:38
Можно было вообще не парится, а просто перезагружать мой cuix при каждой инициализации плагина - задержка не особо заметная.
Перезагружать зачем, для обновления?  Это не лучшее решение, т.к. изменения происходят не так часто а вот глюк загрузки/выгрузки можно словить. Плюс если расплодится CUIX, то время загрузки/выгрузки возрастет.

Алексея Кулик выкладывал код на лиспе, там идея лучше
Каждый раз при загрузке плагина проверяешь дату создания CUIX, если изменилась, то выгружаешь CUIX, потом загружаешь.

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

Для меня не очень подошло(т.к. у ноутов сети нет), и я стал сохранять дату загруженного CUIX в реестре. Как вариант можешь разместить в файле. и сверять с ней.
Название: Re: Подключить ленту из cuix
Отправлено: avc от 31-03-2021, 16:06:03
Это не лучшее решение
Однозначно. Потому и запилил такой вот велосипед.
Алексея Кулик выкладывал код на лиспе, там идея лучше
Каждый раз при загрузке плагина проверяешь дату создания CUIX, если изменилась, то выгружаешь CUIX, потом загружаешь.
Ужо. См. код
Сверять собственно несчем
Есть с чем. Автокад делает копию cuix из папки плагина в папку support. При обновлении плагина будет очевидное несоответствие. В коде выше уже реализовано (с оговоркой, что проверяется дата изменения главного cuix)
Название: Re: Подключить ленту из cuix
Отправлено: avc от 31-03-2021, 16:10:07
Так чего же его проверять в Initialize(), если можно проверить когда ComponentManager.Ribbon != null
Серьезное усложнение. И пользователю точно не понравится перезагрузка всего интерфейса, когда он уже работать начал. В Initialize - самый подходящий момент.
Название: Re: Подключить ленту из cuix
Отправлено: Александр Ривилис от 31-03-2021, 16:22:19
Так чего же его проверять в Initialize(), если можно проверить когда ComponentManager.Ribbon != null
Серьезное усложнение. И пользователю точно не понравится перезагрузка всего интерфейса, когда он уже работать начал. В Initialize - самый подходящий момент.
Он еще не начал работать. Я имел в виду вот такой фортель: https://adn-cis.org/forum/index.php?topic=10085.msg45642#msg45642
Или такой: https://adn-cis.org/forum/index.php?topic=7912.msg45571#msg45571