move region calculation to arrangement

This commit is contained in:
Xinhao Yuan 2019-07-11 11:25:20 -04:00
parent bc8bda02e6
commit dfb3e8f365
4 changed files with 99 additions and 69 deletions

View File

@ -12,8 +12,8 @@ TL;DR --- I want the control of my layout.
## Use the layout
Use `layout = layout_machi.layout.create(name)` to instantiate the layout.
It is advised to instantiate layouts of unique names for each tag (and for each screen), since the editor will restore the last regions of the layout based on the names.
Use `layout = layout_machi.layout.create(name, editor)` to instantiate the layout with an editor object (see below on creating the editor).
The editor will restore the last regions of the layouts based on their names.
## Editor
@ -101,8 +101,6 @@ So far, the key binding is not configurable. One has to modify the source code t
`layout_machi.editor.fit_region(c, cycle = false)` will fit a floating client into the closest region.
If `cycle` is true, it then moves the window by cycling all regions.
`layout_machi.editor.refresh_layout(layout, screen)` will recalculate the regions of the layout based on the workarea of the `screen` and the last editing command performed on `layout`.
## Caveats
`beautiful.useless_gap` is handled differently in layout-machi and it doesn't cooperate well with the standard way.

View File

@ -70,7 +70,7 @@ end
-- @return whether any actions have been taken on the client
local function fit_region(c, cycle)
layout = api.layout.get(c.screen)
regions = layout.get_regions and layout.get_regions()
regions = layout.get_regions and layout.get_regions(c.screen.workarea)
if type(regions) ~= "table" or #regions < 1 then
return false
end
@ -102,6 +102,28 @@ local function shrink_area_with_gap(a, gap)
height = a.height - (a.bu and 0 or gap / 2) - (a.bd and 0 or gap / 2) }
end
-- local function parse(cmd)
-- root = {}
-- args = ""
-- open_areas = { root }
-- for c = 1, #cmd do
-- char = cmd:sub(c, c)
-- if char == "w" then
-- local a = open_areas[#open_areas]
-- table.remove(open_areas, #open_areas)
-- root.type = "w"
-- root.
-- else if tonumber(char) ~= nil then
-- args = args .. char
-- end
-- end
-- end
local function restore_data(data)
if data.history_file then
local file, err = io.open(data.history_file, "r")
@ -268,7 +290,7 @@ local function create(data)
depth = a.depth + 1,
group_id = split_count,
bl = i == 1 and a.bl or false,
br = i == #offset and a.br or false,
br = i == #offset - 1 and a.br or false,
bu = a.bu,
bd = a.bd,
}
@ -313,7 +335,7 @@ local function create(data)
bl = a.bl,
br = a.br,
bu = i == 1 and a.bu or false,
bd = i == #offset and a.bd or false,
bd = i == #offset - 1 and a.bd or false,
}
children[#children + 1] = child
end
@ -678,8 +700,8 @@ local function create(data)
)
end
local function set_by_cmd(layout, screen, cmd)
init(screen.workarea)
local function run_cmd(init_area, cmd)
init(init_area)
push_history()
for i = 1, #cmd do
@ -702,26 +724,18 @@ local function create(data)
end
end
)
layout.cmd = cmd
data.last_cmd[layout.name] = cmd
layout.set_regions(areas_with_gap)
api.layout.arrange(screen)
return areas_with_gap
end
local function refresh_layout(layout, screen)
if layout.cmd == nil then return end
set_by_cmd(layout, screen, layout.cmd)
end
local function try_restore_last(layout, screen)
if data.last_cmd[layout.name] == nil then return end
set_by_cmd(layout, screen, data.last_cmd[layout.name])
local function get_last_cmd(name)
return data.last_cmd[name]
end
return {
start_interactive = start_interactive,
refresh_layout = refresh_layout,
try_restore_last = try_restore_last,
run_cmd = run_cmd,
get_last_cmd = get_last_cmd
}
end

View File

@ -36,10 +36,28 @@ local function find_region(c, regions)
return choice
end
function do_arrange(p, priv)
function create(name, editor)
local priv = {
name = name,
editor = editor,
cmd = editor.get_last_cmd(name),
regions_cache = {}
}
local function get_regions(workarea)
if priv.cmd == nil then return {} end
local key = tostring(workarea.width) .. "x" .. tostring(workarea.height) .. "+" .. tostring(workarea.x) .. "+" .. tostring(workarea.y)
if priv.regions_cache[key] == nil then
priv.regions_cache[key] = priv.editor.run_cmd(workarea, priv.cmd)
end
return priv.regions_cache[key]
end
function arrange(p)
local wa = p.workarea
local cls = p.clients
local regions = priv.regions
local regions = get_regions(wa)
if #regions == 0 then return end
@ -69,20 +87,20 @@ function do_arrange(p, priv)
end
end
function create(name)
local priv = { regions = {} }
local function set_regions(regions)
priv.regions = regions
function set_cmd(cmd)
if priv.cmd ~= cmd then
priv.cmd = cmd
priv.regions_cache = {}
end
local function get_regions()
return priv.regions
end
-- move the closest region regardingly to the center distance
local function resize_handler(c, context, h)
if context ~= "mouse.move" then return end
local workarea = c.screen.workarea
local regions = get_regions(workarea)
if #priv.regions == 0 then return end
local center_x = h.x + h.width / 2
@ -90,7 +108,8 @@ function create(name)
local choice = 1
local choice_value = nil
for i, r in ipairs(priv.regions) do
for i, r in ipairs(regions) do
local r_x = r.x + r.width / 2
local r_y = r.y + r.height / 2
local dis = (r_x - center_x) * (r_x - center_x) + (r_y - center_y) * (r_y - center_y)
@ -102,18 +121,17 @@ function create(name)
if c.machi_region ~= choice then
c.machi_region = choice
c.x = priv.regions[choice].x
c.y = priv.regions[choice].y
c.width = priv.regions[choice].width
c.height = priv.regions[choice].height
c.x = regions[choice].x
c.y = regions[choice].y
c.width = regions[choice].width
c.height = regions[choice].height
end
end
return {
name = name,
arrange = function (p) do_arrange(p, priv) end,
get_region_count = function () return #priv.regions end,
set_regions = set_regions,
arrange = arrange,
set_cmd = set_cmd,
get_regions = get_regions,
resize_handler = resize_handler,
}

View File

@ -58,7 +58,7 @@ local function start(c)
local layout = api.layout.get(screen)
if c.floating or layout.get_regions == nil then return end
local regions = layout.get_regions()
local regions = layout.get_regions(c.screen.workarea)
local infobox = api.wibox({
screen = screen,