Вложенные МЕНЮ, описанные в отдельном файле

Здесь обсуждается всё, что касается макросов.
Post Reply
buniak_a_h
Posts: 2318
Joined: Sat 20 Apr, 2013 00:17
Location: Питер
Has thanked: 139 times
Been thanked: 248 times
Contact:

Вложенные МЕНЮ, описанные в отдельном файле

Post by buniak_a_h »

Навеяно этим:
SuperStainless wrote: Wed 22 Apr, 2020 16:19 I also meant menus in separate files: would be useful because you can compile the menu only one time and use it in different places.
Некоторые отвечали, что подменю, описанные в других файлах, ФАРом не поддерживаются. Как оказалось, поддерживается (функция mf.usermenu). Ниже привожу пункт "стандартного" меню, вызывающий "вложенное" пользовательское меню, описанное в другом файле, а также скрипт (ивент), "затеняющий" пункт стандартного меню в случае отсутствия такого файла.

Три замечания.
1. Хотя порядок не имеет значения, но лично мне удобно, чтоб этот пункт был первым. Ну, логично: локальное меню вызывается чаще…
2. Название этого пункта меню должно быть как-то формализовано, чтоб скрипт его "узнавал". Для себя я выбрал следующий стандарт: в заголовке пункта меню должно присутствовать имя файла в кавычках. Естественно, не должно быть пунктов, содержащих строку «File_name.ext».
3. Приведённый скрипт только дизейблит пункт меню; если заменить в нём LIF_DISABLE на LIF_HIDDEN, то такие пункты меню будут совсем скрыты. Но тогда надо бы пересчитать размеры рамки и всего диалога; я не стал париться.

Итак, скрипт:
  1. local F = far.Flags
  2. Event {
  3.   id = "5BC25193-48EE-42E7-8446-6125E4FBFAB0";
  4.   group       = "DialogEvent"; -- export.ProcessDialogEvent
  5.   description = "Сокрытие пункта вызова UserMenu из другого файла";
  6. --  filemask    = "*.txt,*.cpp";                          -- string (опциональное поле)
  7. --  priority    = 50;                                     -- number (опциональное поле)
  8.   condition   = function(Event, Param)
  9.    if Area.UserMenu and Event == F.DE_DEFDLGPROCINIT and Param.Msg == F.DN_INPUT then
  10.     local Item = Param.hDlg:send(F.DM_GETDLGITEM, 1)
  11.     if Item and type(Item) == 'table' and (Item[1]==F.DI_LISTBOX or Item[1]=='DI_LISTBOX') and
  12.        (Item[12] or 0) == 0 then
  13.      Item[12] = 1
  14.      Param.hDlg:send(F.DM_SETDLGITEM,1, Item)
  15.      return true
  16.     end
  17.    end
  18.   end; -- condition
  19.   action      = function(Event, Param)
  20.    local hDlg = Param.hDlg
  21.    local n = hDlg:send(F.DM_LISTINFO, 1).ItemsNumber
  22.    for i=1,n do
  23.     local Item = hDlg:send(F.DM_LISTGETITEM, 1, i)
  24.     local FName = Item.Text:match"%b«»"
  25.     if FName then
  26.      FName = win.SearchPath( ( (APanel.Plugin and 'win.GetCurrentDir()' or APanel.Path) .. ';') ..
  27.                              (win.GetEnv("FARHOME") .. ';') ..
  28.                              (win.GetEnv("FARPROFILE") .. ';') ..
  29.                              (win.GetEnv("FARLOCALPROFILE") .. ';') ..
  30.                              (win.GetEnv("PATH") .. ';'), -- Path
  31.                              FName:sub(2,-2)
  32.                            )
  33.      if not FName then
  34.       Item.Flags = bor(Item.Flags, F.LIF_DISABLE)
  35.       Item.Index = i
  36.       hDlg:send(F.DM_LISTUPDATE, 1, Item)
  37.      end
  38.      break
  39.     end
  40.    end
  41.   end; -- action
  42. }
Post Reply

Return to “Обсуждение макросов”