Расчёт ширины не доотлаживал; может лажать на 1 позицию
"подгонку" ширины сделал зависящей от ВСЕХ позиций (независимо от того, есть ли редакторы, у которых Title не равен FileName). Не большие потери, но если хотите - оптимизируйте.
Last edited by buniak_a_h on Sat 23 Apr, 2022 09:17, edited 2 times in total.
local F = far.Flags
local ScreensSwitchId = win.Uuid(far.Guids.ScreensSwitchId)
local function switchTitles(hDlg)
local cType
local aTitles = {}
local n = far.AdvControl(F.ACTL_GETWINDOWCOUNT)
for i=1,n do
local wi = far.AdvControl(F.ACTL_GETWINDOWINFO, i)
if wi.Type == F.WTYPE_EDITOR then
cType = cType or wi.TypeName -- так не будет зависеть от языка интерфейса
local edid = wi.Id
local f1,f2 = editor.GetFileName(edid), editor.GetTitle(edid)
if f1 ~= f2 then
aTitles[f1] = f2
aTitles[f2] = f1
end
end
end
local r = hDlg:send(F.DM_GETDLGRECT)
local w0, h0 = r.Right-r.Left+1, r.Bottom-r.Top+1
local w = 0
local lr = hDlg:send(F.DM_GETITEMPOSITION, 1)
n = hDlg:send(F.DM_LISTINFO, 1).ItemsNumber
for i=1, n do
local it = hDlg:send(F.DM_LISTGETITEM, 1, i)
--local tp, pos, fn = it.Text:match"^[%d&]+%s+(%a+)[%s*]+()(.*)$" -- как выяснилось, при количестве окон более 9 нумерация становится буквенной A-Z. Шаблон исправлен
local tp, pos, fn = it.Text:match"^&?[%d%u ]%s+(%a+)[%s*]+()(.*)$"
if tp == cType and aTitles[fn] then
it.Text = it.Text:sub(1,pos-1) .. aTitles[fn]
it.Index = i
hDlg:send(F.DM_LISTUPDATE, 1, it)
end
w = math.max(w, it.Text:len())
end -- for i
w = math.min( w+7, Far.Width)
hDlg:send(F.DM_RESIZEDIALOG, 0, {X=w; Y=h0})
hDlg:send(F.DM_SETITEMPOSITION, 1, {Left=lr.Left,Top=lr.Top,Bottom=lr.Bottom,Right=w-2})
end; -- function switchTitles
Event {
description = "Замена (изначально) временного имени редактируемого файла на исходное из NetBox'а";
id = "86784CDC-465B-47A5-961E-D0CA75372172";
group = "DialogEvent";
condition = function(Event, Param)
if Event == F.DE_DLGPROCEND and Param.Msg == F.DN_INITDIALOG then
local Id = (Param.hDlg:send(F.DM_GETDIALOGINFO) or {}).Id
return Id == ScreensSwitchId
end
end;
action = function(Event, Param) switchTitles(Param.hDlg) end;
}
----------------------------------------------------
Macro{
description = "Замена (по F2) временного имени редактируемого файла на исходное из NetBox'а";
id="B5254B15-C58F-49A6-87FF-BD1EAE79A0BE";
area="Menu";
key="F2";
flags="";
condition=function(key, data)
local hDlg = far.AdvControl(F.ACTL_GETWINDOWINFO).Id
local Id = (hDlg:send(F.DM_GETDIALOGINFO) or {}).Id
if Id == ScreensSwitchId then
data.hDlg = hDlg
return true
end
end;
action=function(data) switchTitles(data.hDlg) end;
}
Last edited by buniak_a_h on Sat 23 Apr, 2022 11:40, edited 1 time in total.
buniak_a_h wrote: Sat 23 Apr, 2022 11:42
Смотрите последний вариант. А то тот, что я присылал, работает при количестве окон не более 9-ти
Спасибо! Правда, у меня меню только меняет ширину, но при этом не меняет местоположение. В результате край нередко вылезает за правую границу экрана и отсекается.
Чтобы это полечить без прыгания туда-сюда, было бы здорово, если бы при переключении ширина могла только увеличиваться (т.е. не уменьшалась бы), а само меню сдвигалось влево ровно настолько, насколько необходимо, чтобы правая рамка была видна.
HaRT wrote: Sun 24 Apr, 2022 00:47
не меняет местоположение
Имел в виду, но забыл написать!
После строчки с DM_RESIZEDIALOG вставьте строчку hDlg:send(F.DM_MOVEDIALOG, 1, {X=-1; Y=r.Top})
HaRT wrote: Sun 24 Apr, 2022 00:47
было бы здорово, если бы при переключении ширина могла только увеличиваться
Сделал "прыганье" туда-сюда для удобства отладки. Замените строку w = math.min( w+7, Far.Width)
на w = math.max( w0, math.min( w+7, Far.Width) )
и будет Вам Щястие Великое
Я добавил в меню подсказку F2, когда она уместна (т.е. будет иметь видимый эффект).
Также допилил логику позиционирования, чтобы при длинных заголовках видимая ширина использовалась максимально, пусть даже и ценой выезжания рамок за края.
Заодно выкладываю макро, чтобы быстро переключаться в панели, дважды нажав F12.
Также исправлены некоторые предупреждения и внесены косметические правки.
-- See https://forum.farmanager.com/viewtopic.php?p=170841#p170841
local F = far.Flags
Macro {
description = "Press F12 twice to go to panels (if any)";
area = 'Menu'; key = 'F12';
condition = function()
return Menu.Id == far.Guids.ScreensSwitchId;
end;
code = [[Keys'Alt1']]
}
local viewerTitles = {}
Event { -- Need this crutch as FAR API does not expose Viewer Title via Viewer API
description = "Keep track of open viewers' titles";
group = 'ViewerEvent';
action = function( id, event, param )
local _ = param
if event == F.VE_READ then -- TODO special-case QView, Info
viewerTitles[ id ] = Object.Title
end
if event == F.VE_CLOSE then
viewerTitles[ id ] = nil
end
end
}
local function switchTitles( dlg )
local aTitles = {}
local winTypeEdit, winTypeView
for i = 1, actl.GetWindowCount() do
local wi = actl.GetWindowInfo(i)
local f1, f2
if wi.Type == F.WTYPE_EDITOR then
winTypeEdit = winTypeEdit or wi.TypeName -- чтобы не зависеть от языка интерфейса
f1, f2 = editor.GetFileName( wi.Id ), editor.GetTitle( wi.Id )
end
if wi.Type == F.WTYPE_VIEWER then
winTypeView = winTypeView or wi.TypeName -- чтобы не зависеть от языка интерфейса
f1, f2 = viewer.GetFileName( wi.Id ), viewerTitles[ wi.Id ]
end
if f1 and f2 and f1 ~= f2 then
aTitles[f1], aTitles[f2] = f2, f1
end
end
local ret, r = false, dlg:GetDlgRect()
local wF, w, w0, h0 = Far.Width, 0, r.Right-r.Left+1, r.Bottom-r.Top+1
local lr = dlg:GetItemPosition(1)
for i = 1, dlg:ListInfo(1).ItemsNumber do
local it = dlg:ListGetItem(1,i)
-- как выяснилось, при количестве окон более 9 нумерация становится буквенной A-Z
local tp, pos, fn = it.Text:match'^&?[%d%u ]%s+(%a+)[%s*]+()(.*)$'
if ( tp == winTypeEdit or tp == winTypeView ) and aTitles[fn] then
it.Text = it.Text:sub(1,pos-1) .. aTitles[fn]
it.Index = i
dlg:ListUpdate(1, it)
ret = true -- заменили хотя бы один элемент
end
w = math.max(w, it.Text:len())
end -- for i
local w1 = math.max(w0, math.min(w, wF)+8)
dlg:ResizeDialog(0, {X=w1; Y=h0})
local center, dx = -1, w+2 > wF and -1 or 0
dlg:MoveDialog(1, {X=center; Y=r.Top})
dlg:MoveDialog(0, {X=dx; Y=0})
dlg:SetItemPosition(1, {Left=lr.Left,Top=lr.Top,Bottom=lr.Bottom,Right=w1-3})
return ret
end; -- function switchTitles
Event {
description = "Замена (изначально) временного имени редактируемого файла на исходное из NetBox'а, FarCmds'а и т.п.";
id = '86784CDC-465B-47A5-961E-D0CA75372172';
group = 'DialogEvent';
condition = function(Event, Param)
if Event == F.DE_DLGPROCEND and Param.Msg == F.DN_INITDIALOG then
local Id = (Param.hDlg:GetDialogInfo() or {}).Id
return Id == win.Uuid( far.Guids.ScreensSwitchId )
end
end;
action = function(Event, Param)
local _ = Event;
if switchTitles(Param.hDlg) then
-- See https://forum.farmanager.com/viewtopic.php?p=166727#p166727
local Titles = Param.hDlg:ListGetTitles(1)
Titles.Bottom = 'F2'
Param.hDlg:ListSetTitles(1, Titles)
end
end;
}
Macro {
description = "Замена (по F2) временного имени редактируемого файла на исходное из NetBox'а, FarCmds'а и т.п.";
id = 'B5254B15-C58F-49A6-87FF-BD1EAE79A0BE';
area = 'Menu'; key = 'F2';
condition = function() --key, data)
return Menu.Id == far.Guids.ScreensSwitchId
end;
action = function() --data)
switchTitles( actl.GetWindowInfo().Id )
end;
}
P.S.
Замечу, что этот скрипт полезен не только совместно с NetBox'ом, но и в сочетании с FarCmds при использовании синтаксиса edit: < PROG ARG.... К сожалению, с вариантом view: < PROG ARG... номер не проходит, поскольку FAR API не предоставляет возможности получить заголовок просмотрщика. (Или она есть, но я не там искал?) 2025-03-19: с помощью костыля удалось.
Last edited by HaRT on Thu 20 Mar, 2025 00:51, edited 4 times in total.
Reason:Добавлена поддержка просмотрщиков, несколько упрощён код.
В мой форк внесены исправления, касающиеся ширины:
1. Правое поле диалога теперь такое же, как левое, — 2 знакоместа.
2. Если заголовки «экранов» достаточно длинные, то теперь видимая ширина используется по максимуму, вплоть до того, что цифра с номером экрана будет в самом левом знакоместе, а признак отсечения (») — в самом правом. Разумеется, поля, рамки и отступы при этом оказываются за экраном. Также при переключении по F2 элементы могут смещаться влево-вправо на 1-2 знакоместа. (Если заголовки не длинные, то всё как раньше, кроме п.1.)
Кстати, это работает с любыми длинными заголовками независимо от их происхождения.
HaRT wrote: Thu 09 Jun, 2022 21:50 с вариантом view: < PROG ARG... номер не проходит, поскольку FAR API не предоставляет возможности получить заголовок просмотрщика. (Или она есть, но я не там искал?)
В моём форке удалось подставить костыль и добавить поддержку просмотрщиков. Заодно запрошено соответствующее усовершенствование NetBox.