Skip to content

Commit

Permalink
Release Docking Tools v0.1 (Initial Release) (#1466)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenTalagan authored Dec 2, 2024
1 parent c3f3520 commit 0049770
Show file tree
Hide file tree
Showing 8 changed files with 367 additions and 0 deletions.
26 changes: 26 additions & 0 deletions View/talagan_Docking tools.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--[[
@description Docking tools : actions to resize docks
@version 0.1
@author Ben 'Talagan' Babut
@donation https://www.paypal.com/donate/?business=3YEZMY9D6U8NC&no_recurring=1&currency_code=EUR
@license MIT
@metapackage
@provides
[main=main] talagan_Docking tools/actions/talagan_Maximize bottommost dock.lua > talagan_Maximize bottommost dock.lua
[main=main] talagan_Docking tools/actions/talagan_Minimize bottommost dock.lua > talagan_Minimize bottommost dock.lua
[main=main] talagan_Docking tools/actions/talagan_Set bottommost dock height (500).lua > talagan_Set bottommost dock height (500).lua
[main=main,midi_editor] talagan_Docking tools/actions/talagan_Maximize dock containing active MIDI Editor.lua > talagan_Maximize dock containing active MIDI Editor.lua
[main=main,midi_editor] talagan_Docking tools/actions/talagan_Minimize dock containing active MIDI Editor.lua > talagan_Minimize dock containing active MIDI Editor.lua
[main=main,midi_editor] talagan_Docking tools/actions/talagan_Set dock containing active MIDI Editor height (500).lua > talagan_Set dock containing active MIDI Editor height (500).lua
[nomain] talagan_Docking tools/docking_lib.lua
@changelog
- Initial Release
@about
This package provide actions to quickly resize the MIDI dock and the bottommost dock (maximize, minimize, or set to custom height).
These actions are meant to be small bricks of bigger custom actions where you perform a reorganisation of the UI (e.g. use FTC's scrolling scripts for the MIDI editor).
You can copy / paste the "... (500).lua" action files and modify their name to put a custom height instead of 500.
Thanks to @edgemeal for the technical advice / windows support and @X-raym for the code review!
--]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path

local ok, docking_lib = pcall(require, "talagan_Docking tools/docking_lib")
if not ok then
reaper.MB("This script is not well installed. Please install 'Docking tools' with Reapack.","Ouch!",0)
return
end

if not docking_lib.CheckDependencies() then return end

docking_lib.maximizeBottommostDock()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path

local ok, docking_lib = pcall(require, "talagan_Docking tools/docking_lib")
if not ok then
reaper.MB("This script is not well installed. Please install 'Docking tools' with Reapack.","Ouch!",0)
return
end

if not docking_lib.CheckDependencies() then return end

docking_lib.maximizeMidiDock()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path

local ok, docking_lib = pcall(require, "talagan_Docking tools/docking_lib")
if not ok then
reaper.MB("This script is not well installed. Please install 'Docking tools' with Reapack.","Ouch!",0)
return
end

if not docking_lib.CheckDependencies() then return end

docking_lib.minimizeBottommostDock()
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path

local ok, docking_lib = pcall(require, "talagan_Docking tools/docking_lib")
if not ok then
reaper.MB("This script is not well installed. Please install 'Docking tools' with Reapack.","Ouch!",0)
return
end

if not docking_lib.CheckDependencies() then return end

docking_lib.minimizeMidiDock()
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path

local ok, docking_lib = pcall(require, "talagan_Docking tools/docking_lib")
if not ok then
reaper.MB("This script is not well installed. Please install 'Docking tools' with Reapack.","Ouch!",0)
return
end

if not docking_lib.CheckDependencies() then return end

local _, sfname = reaper.get_action_context()
local param = tonumber(sfname.match(sfname,"%((.*)%).lua"))

docking_lib.resizeBottommostDock(param)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path

local ok, docking_lib = pcall(require, "talagan_Docking tools/docking_lib")
if not ok then
reaper.MB("This script is not well installed. Please install 'Docking tools' with Reapack.","Ouch!",0)
return
end

if not docking_lib.CheckDependencies() then return end

local _, sfname = reaper.get_action_context()
local param = tonumber(sfname.match(sfname,"%((.*)%).lua"))

docking_lib.resizeMidiDock(param)
239 changes: 239 additions & 0 deletions View/talagan_Docking tools/docking_lib.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
-- @noindex
-- @author Ben 'Talagan' Babut
-- @license MIT
-- @description This is part of Talagan Docking Tools

local function CheckReapack(func_name, api_name, search_string)
if not reaper.APIExists(func_name) then
local answer = reaper.MB( api_name .. " is required and you need to install it.\z
Right-click the entry in the next window and choose to install.",
api_name .. " not installed", 0 )
reaper.ReaPack_BrowsePackages( search_string )
return false
end
return true
end

local function CheckDependencies()
if not CheckReapack("JS_ReaScriptAPI_Version", "JS_ReaScriptAPI", "js_ReaScriptAPI") then return false end

return true
end


------------------------

DOCK_BOTTOM = 0
DOCK_FLOATING = 4

local function setTimeout(callback, timeout)
local wur = timeout
local wut = reaper.time_precise()

function _wait_ready()

if reaper.time_precise() - wut < wur then
reaper.defer(_wait_ready)
return
end

callback()
end

reaper.defer(_wait_ready)
end

-- Thanks to @edgemeal for this technique !
local function JS_LDrag(hwnd, x_start,x_end, y_start,y_end)
reaper.JS_WindowMessage_Send(hwnd, "WM_LBUTTONDOWN", 1, 0, x_start, y_start)
reaper.JS_WindowMessage_Send(hwnd, "WM_LBUTTONUP", 0, 0, x_end, y_end)
end

local function JS_Window_GetTopParent(hwnd)
local p = hwnd; local p2 = hwnd;
while p2 do
p = p2;
p2 = reaper.JS_Window_GetParent(p)
end
return p
end

local function JS_Window_GetBounds(hwnd)
local _, left, top, right, bottom = reaper.JS_Window_GetClientRect( hwnd )

local os = reaper.GetOS()
h = top - bottom

-- Under windows, vertical coordinates are flipped !
if os == "Win32" or os == "Win64" then
h = bottom - top
end

return {hwnd = hwnd, l = left, t = top, r = right, b = bottom, w = (right-left), h = h }
end

local function JS_Window_Debug(hwnd)
local bounds = JS_Window_GetBounds(hwnd);
reaper.ShowConsoleMsg("Title : " .. reaper.JS_Window_GetTitle(hwnd) .. "\n");
reaper.ShowConsoleMsg("Width : " .. bounds.w .. "\n");
reaper.ShowConsoleMsg("Height : " .. bounds.h .. "\n");
reaper.ShowConsoleMsg("T,R,B,L : " .. bounds.t .. ", " .. bounds.r .. ", " .. bounds.b .. ", " .. bounds.l .. "\n");
end

local function findDockerThatContainsWindow(hwnd_to_find)
local c, l = reaper.JS_Window_ListFind("REAPER_dock",true);
for token in string.gmatch(l, "[^,]+") do
local hwnd = reaper.JS_Window_HandleFromAddress(token);
if reaper.JS_Window_IsChild(hwnd, hwnd_to_find) then
return JS_Window_GetBounds(hwnd);
end
end
return nil;
end

local function findBottommostDock()
local lowest = nil
local blowest = nil
local c, l = reaper.JS_Window_ListFind("REAPER_dock",true);
for token in string.gmatch(l, "[^,]+") do
local hwnd = reaper.JS_Window_HandleFromAddress(token);
local idx,_ = reaper.DockIsChildOfDock(hwnd)
local pos = reaper.DockGetPosition(idx)

-- Don't try to do something on docks that are not docked at the bottom
if pos == DOCK_BOTTOM then
local bounds = JS_Window_GetBounds(hwnd)

local bot = bounds.b
if os == "Win32" or os == "Win64" then
-- Under windows we reverse the bottom bound to have the same ordering logic as on MacOS/Linux
-- (This will be negative but we don't care, we just want to know what's the bottommost dock)
bot = - bot
end

if not lowest or bot < blowest then
lowest = bounds
blowest = bot
end
end

end

if lowest then
return lowest
end

return nil
end

local function findTopWindowThatContainsWindow(hwnd_to_find)
local c, l = reaper.JS_Window_ListAllTop();
for token in string.gmatch(l, "[^,]+") do
local hwnd = reaper.JS_Window_HandleFromAddress(token);
if reaper.JS_Window_IsChild(hwnd, hwnd_to_find) then
return JS_Window_GetBounds(hwnd);
end
end
return nil;
end

local function deferredDebugPostCheck()
setTimeout(function()
local redock = JS_Window_GetBounds(dock.hwnd);
if redock.h ~= height then
reaper.ShowConsoleMsg("Requested height : " .. height .. " , but got height " .. redock.h .. "\n")
end
end, 1.0);
end

local function safeHeight(dock, height)
-- We need to clamp the requested height so that what we ask
-- will match what's REAPER will be able to do
-- else, at the end of our action subsequent actions will not work on a valid height
-- (they will run on what we have set, but a few cycles later, REAPER
-- will repack the UI, making those adjusments wrong)

local sheight = height

local topw = JS_Window_GetTopParent(dock.hwnd);
local topwbounds = JS_Window_GetBounds(topw);

-- JS_Window_Debug(topw);

local maxheight = topwbounds.h - 191;
local minheight = math.min(320, topwbounds.h - 174);

-- reaper.ShowConsoleMsg(height .. "\n");
-- reaper.ShowConsoleMsg(maxheight .. "\n");
-- reaper.ShowConsoleMsg(minheight .. "\n");

if sheight > maxheight then
sheight = maxheight;
end

if sheight < minheight then
sheight = minheight;
end

-- reaper.ShowConsoleMsg("Safe height : " .. sheight)

return sheight
end

local function resizeDock(dock, height)

-- height = safeHeight(dock, height)
-- reaper.ShowConsoleMsg(height .. "\n");

-- Remember current focus
local focused = reaper.JS_Window_GetFocus();

-- Drag the resize grip... thanks @edgemeal for the technique !
JS_LDrag(dock.hwnd, 0, 0, 0, dock.h - height)

-- Restore focus
reaper.JS_Window_SetFocus(focused);

-- The next call helps to check if what we requested is what we got
-- use it in debug mode only
-- deferredDebugPostCheck();
end

-- Exports

local function resizeMidiDock(height)
local me = reaper.MIDIEditor_GetActive(); -- Exists because we found the parent docket
if not me then return end

local dock = findDockerThatContainsWindow(me);
if not dock then return end

resizeDock(dock, height);
end

local function resizeBottommostDock(height)
local dock = findBottommostDock()
if not dock then return end
resizeDock(dock, height)
end

local function maximizeMidiDock() resizeMidiDock(10000) end
local function minimizeMidiDock() resizeMidiDock(0) end

local function maximizeBottommostDock() resizeBottommostDock(10000) end
local function minimizeBottommostDock() resizeBottommostDock(0) end


return {
CheckDependencies=CheckDependencies,
setTimeout=setTimeout,

resizeMidiDock=resizeMidiDock,
maximizeMidiDock=maximizeMidiDock,
minimizeMidiDock=minimizeMidiDock,

resizeBottommostDock=resizeBottommostDock,
maximizeBottommostDock=maximizeBottommostDock,
minimizeBottommostDock=minimizeBottommostDock,
}

0 comments on commit 0049770

Please sign in to comment.