|
--[[ |
|
.Language=Russian,Russian (Русский) |
|
.PluginContents=RClickEx |
|
.Options CtrlStartPosChar=§¦ |
|
|
|
|
|
@Contents |
|
$ #RClickEx — Right Click Menu Activator# |
|
|
|
Скрипт позволяет использовать правую клавишу мыши в панелях для вызова контекстного меню (посредством EMenu), |
|
не теряя возможности выделения файлов этой же клавишей. |
|
|
|
Возможны несколько вариантов активации меню: |
|
|
|
• §¦#Удержанием# правой клавиши. |
|
• §¦Кликом #двумя клавишами# одновременно |
|
§¦(не имеет значения какая из клавиш нажата первой, но требуется Far 3 build >= 6171). |
|
• §¦При клике правой клавишей с #модификатором# #Ctrl#/#Shift# |
|
§¦(помимо этого модификаторы изменяют вид меню, см. ниже). |
|
|
|
Через #меню конфигурации# плагинов доступны такие настройки: |
|
|
|
• §¦использовать #графическое# / или #текстовое# меню; |
|
• §¦активировать меню: |
|
• §¦при удержании клавиши / или при нажатии обоих клавиш вместе; |
|
• §¦опционально, и при клике с #Ctrl# и/или #Shift#; |
|
• §¦для режима с удержанием: #время задержки (мс)#, после которого вызывается меню. |
|
|
|
Особенности: |
|
|
|
• §¦Обрабатываются нажатия #[Ctrl+][Shift+]MsRClick#: |
|
• §¦Использование #Ctrl# инвертирует настройку графическое / текстовое меню. |
|
• §¦При нажатом #Shift# открывается “~расширенное~@https://lifehacker.com/open-hidden-menu-options-with-the-shift-and-right-click-5804483@” меню. |
|
• §¦Вызов графического меню происходит после отпускания клавиши (в целях обхода ~бага~@https://forum.farmanager.com/viewtopic.php?f=9&t=7540&start=16@). |
|
• §¦Работает в том числе и в плагиновой панели, если файлы на ней реальные. |
|
За пределами панелей (на пустом месте) никаких функций не предусмотрено. |
|
• §¦Подразумевается, что настройка (#far:config#) #Panel.RightClickSelect=true#, |
|
ведь в противном случае скрипт просто не имеет смысла. |
|
|
|
Первоначальная идея отсюда: ~https://forum.farmanager.com/viewtopic.php?t=7200~@https://forum.farmanager.com/viewtopic.php?t=7200@ |
|
@ |
|
--]] |
|
local Info = Info or package.loaded.regscript or function(...) return ... end --luacheck: ignore 113/Info |
|
local nfo = Info { _filename or ..., |
|
name = "RClickEx"; |
|
description = "Right Click Menu Activator"; |
|
version = "0.4"; --https://semver.org/lang/ru/ |
|
author = "jd"; |
|
url = "https://forum.farmanager.com/viewtopic.php?t=13250"; |
|
id = "D841C948-BE8A-4ACB-97F4-53205783A971"; |
|
minfarversion = {3,0,0,6171,0}; |
|
files = "README.md"; |
|
--config = function(nfo,name) end; |
|
--help = function(nfo,name) end; |
|
|
|
--options = {}; |
|
--disabled = true; |
|
} |
|
if not nfo or nfo.disabled then return end |
|
--local O = nfo.options |
|
|
|
if not Far.GetConfig"Panel.RightClickSelect" then |
|
far.Message([[ |
|
|
|
This macro requires Panel.RightClickSelect=true |
|
(see far:config)]],...,nil,"wl") |
|
return |
|
end |
|
|
|
local F = far.Flags |
|
local selfpath = _filename or ... |
|
nfo.help = function() |
|
far.ShowHelp(selfpath, nil, F.FHELP_CUSTOMFILE) |
|
end |
|
|
|
local S = mf.mload(nfo.author, nfo.name) or { |
|
GUImenu = true, |
|
HoldMode = true, |
|
WithMods = true, |
|
HoldDelay = 500, |
|
} |
|
local MinDelay = 20 |
|
|
|
local _TXT,_GUI = 1,2 |
|
local cmds = {"rclk_txt:", "rclk_gui:"} |
|
|
|
local CTRL = bit64.bor(0x4,0x8) -- RCtrl,LCtrl |
|
local color = far.AdvControl(F.ACTL_GETCOLOR, far.Colors.COL_PANELCURSOR) |
|
color.ForegroundColor, color.BackgroundColor = color.BackgroundColor, color.ForegroundColor -- invert |
|
local function eMenu (SelCount) |
|
if SelCount and SelCount~=APanel.SelCount then |
|
Panel.Select(0,2,1) -- invert (restore) |
|
end |
|
local cmd = S.GUImenu and _GUI or _TXT |
|
if bit64.band(Mouse.LastCtrlState, CTRL)~=0 then |
|
cmd = 3-cmd -- invert |
|
end |
|
if cmd==_GUI then |
|
local scr = far.SaveScreen() |
|
far.Text(Mouse.X, Mouse.Y, color, "..release..") |
|
repeat |
|
mf.waitkey(MinDelay) |
|
until bit64.band(Mouse.Button, F.RIGHTMOST_BUTTON_PRESSED)==0 |
|
far.RestoreScreen(scr) |
|
end |
|
mf.postmacro(Plugin.Command, "742910F1-02ED-4542-851F-DEE37C2E13B2", cmds[cmd]) |
|
end |
|
|
|
local function On2Click (timer, ClickPos, SelCount) |
|
if bit64.band(Mouse.Button, F.RIGHTMOST_BUTTON_PRESSED)==0 or ClickPos~=Object.CurPos then |
|
timer:Close() |
|
elseif bit64.band(Mouse.Button, F.FROM_LEFT_1ST_BUTTON_PRESSED)~=0 then |
|
timer:Close() |
|
eMenu(SelCount) |
|
end |
|
end |
|
|
|
local function OnHold (timer, ClickPos, SelCount) |
|
timer:Close() |
|
if Mouse.Button==F.RIGHTMOST_BUTTON_PRESSED and ClickPos==Object.CurPos then |
|
eMenu(SelCount) |
|
end |
|
end |
|
|
|
local function checkPanel (pnl, x, y, deadTop, deadBottom) |
|
local pi = panel.GetPanelInfo(nil,pnl) |
|
if x>pi.PanelRect.left and x<pi.PanelRect.right and |
|
y>=pi.PanelRect.top+deadTop and y<=pi.PanelRect.bottom-deadBottom and |
|
bit64.band(pi.Flags, F.PFLAGS_VISIBLE)==F.PFLAGS_VISIBLE then |
|
|
|
return bit64.band(pi.Flags, F.PFLAGS_PLUGIN)==0 or bit64.band(pi.Flags, F.PFLAGS_REALNAMES)==F.PFLAGS_REALNAMES |
|
end |
|
end |
|
|
|
local descr = nfo.name.." — "..nfo.description |
|
local timer |
|
Macro { description=descr; |
|
area="Shell Tree"; key="MsRClick ShiftMsRClick CtrlMsRClick CtrlShiftMsRClick"; |
|
id="208B186D-4B57-4734-9476-6A390FBE55DD"; |
|
condition=function() -- https://github.com/FarPluginsArchive/farplug-alvls/blob/master/rcl2apps/rcl2apps.cpp |
|
local deadTop = (Far.GetConfig"Panel.Layout.ColumnTitles" and 1 or 0) |
|
+ (Far.GetConfig"Interface.ShowMenuBar" and 1 or 0) |
|
local deadBottom = Far.GetConfig"Panel.Layout.ColumnTitles" and 2 or 0 |
|
local x,y = Mouse.X, Mouse.Y |
|
return checkPanel(1,x,y,deadTop,deadBottom) |
|
or checkPanel(0,x,y,deadTop,deadBottom) |
|
end; |
|
action=function() |
|
if timer and not timer.Closed then timer:Close() end |
|
Keys"MsLClick" -- set cursor to clicked file |
|
if S.WithMods and mf.akey(1,1)~="MsRClick" |
|
or not S.HoldMode and bit64.band(Mouse.Button, F.FROM_LEFT_1ST_BUTTON_PRESSED)~=0 then |
|
eMenu() |
|
return |
|
end |
|
local SelCount = APanel.SelCount |
|
Keys"AKey" |
|
timer = far.Timer(S.HoldMode and S.HoldDelay or MinDelay, |
|
S.HoldMode and OnHold or On2Click, |
|
Object.CurPos, |
|
SelCount) |
|
end; |
|
} |
|
|
|
local bullet = "⦿" --• |
|
local check = "✓" |
|
nfo.config = function() |
|
local Props = { |
|
Title=nfo.name, |
|
Id=win.Uuid"DE560C2A-CEA0-4EEB-A494-AADC772E6EEC", |
|
} |
|
repeat |
|
local Items = { |
|
{text="Use GUI menu", |
|
toggle="GUImenu", checked=S.GUImenu and check}, |
|
{text="Act on:", separator=true}, |
|
{text="Button hold", |
|
mode="Hold", checked=S.HoldMode and bullet}, |
|
{text="Right+Left buttons click", |
|
mode="2Buttons", checked=not S.HoldMode and bullet}, |
|
{text="With Ctrl/Shift", |
|
toggle="WithMods", checked=S.WithMods and check}, |
|
{separator=true}, |
|
{text="Hold delay: "..S.HoldDelay.." ms", |
|
action=function() |
|
local Id = win.Uuid"2E95C789-D37B-49E2-BABB-1032BA327A5F" |
|
local Prompt = "Enter hold delay for right button" |
|
local res = far.InputBox(Id, nfo.name, Prompt, nfo.name.."HoldDelay", S.HoldDelay) |
|
res = res and S.HoldDelay~=res and tonumber(res) |
|
S.HoldDelay = res or S.HoldDelay |
|
return res |
|
end; |
|
grayed=not S.HoldMode}, |
|
} |
|
local item, pos = far.Menu(Props, Items, "F1") |
|
Props.SelectIndex = pos |
|
if not item then |
|
--noop |
|
elseif item.BreakKey then |
|
far.ShowHelp(selfpath, nil, F.FHELP_CUSTOMFILE) |
|
else |
|
local tosave = true |
|
if item.mode then |
|
if not item.checked then |
|
S.HoldMode = not S.HoldMode |
|
else |
|
tosave = false |
|
end |
|
elseif item.toggle then |
|
S[item.toggle] = not S[item.toggle] |
|
elseif item.action then |
|
tosave = item.action() |
|
end |
|
if tosave then |
|
mf.msave(nfo.author, nfo.name, S) |
|
end |
|
end |
|
until not item |
|
end |
|
|
|
MenuItem { |
|
description=descr; |
|
menu="Config"; |
|
guid="AADCDA31-7835-450E-AE4C-35D2620B9CF4"; |
|
text=nfo.name.." - "..nfo.description; |
|
action=nfo.config; |
|
} |