AwesomeFiles/config/awesome/modules/awedock/init.lua
2022-07-11 20:06:55 -05:00

366 lines
9.7 KiB
Lua
Executable file

local wibox = require("wibox")
local beautiful = require("beautiful")
local dpi = beautiful.xresources.apply_dpi
local awful = require("awful")
local gears = require("gears")
local rubato = require(tostring(...):match(".*awedock") .. ".rubato")
local function helpers()
local function overloaded()
local fns = {}
local mt = {}
local function oerror()
return error("Invalid argument types to overloaded function")
end
function mt:__call(...)
local arg = { ... }
local default = self.default
local signature = {}
for i, arg in ipairs({ ... }) do
signature[i] = type(arg)
end
signature = table.concat(signature, ",")
return (fns[signature] or self.default)(...)
end
function mt:__index(key)
local signature = {}
local function __newindex(self, key, value)
print(key, type(key), value, type(value))
signature[#signature + 1] = key
fns[table.concat(signature, ",")] = value
print("bind", table.concat(signature, ", "))
end
local function __index(self, key)
print("I", key, type(key))
signature[#signature + 1] = key
return setmetatable({}, { __index = __index, __newindex = __newindex })
end
return __index(self, key)
end
function mt:__newindex(key, value)
fns[key] = value
end
return setmetatable({ default = oerror }, mt)
end
--}}}
local function dec_hex(IN)
local B, K, OUT, I, D = 16, "0123456789ABCDEF", "", 0
while IN > 0 do
I = I + 1
IN, D = math.floor(IN / B), (IN % B) + 1
OUT = string.sub(K, D, D) .. OUT
end
return #OUT == 2 and OUT or "0" .. OUT
end
-- color helpers {{{
local color = {}
color.col_shift = overloaded()
color.col_shift.string.number = function(c, s)
local r, g, b, o = gears.color.parse_color(c)
return "#" .. dec_hex(r * 255 + s) .. dec_hex(g * 255 + s) .. dec_hex(b * 255 + s) .. dec_hex(o * 255)
end
color.col_shift.string.number.number.number = function(c, sr, sg, sb)
local r, g, b, o = gears.color.parse_color(c)
return "#" .. dec_hex(r * 255 + sr) .. dec_hex(g * 255 + sg) .. dec_hex(b * 255 + sb) .. dec_hex(o * 255)
end
color.col_shift.string.number.number.number.number = function(c, sr, sg, sb, so)
local r, g, b, o = gears.color.parse_color(c)
return "#" .. dec_hex(r * 255 + sr) .. dec_hex(g * 255 + sg) .. dec_hex(b * 255 + sb) .. dec_hex(o * 255 + so)
end
color.col_diff = function(f, s)
local fr, fg, fb, fo = gears.color.parse_color(f)
local sr, sg, sb, so = gears.color.parse_color(s)
return sr - fr, sg - fg, sb - fb, so - fo
end
--}}}
return {
color = color,
}
end
local chel = helpers().color
--local function init(s, h, o, shape, pinneds)
local function init(args)
local s = args.screen
local h = args.height or dpi(50)
local o = args.offset or 5
local inner_shape = args.inner_shape or gears.shape.rectangle
local outer_shape = args.outer_shape or gears.shape.rectangle
local pinneds = args.pinneds
-- tasklist creation {{{
local tasklist = awful.widget.tasklist({
screen = s,
source = function()
local ret = {}
for _, t in ipairs(s.tags) do
gears.table.merge(ret, t:clients())
end
return ret
end, --sorts clients in order of their tags
filter = awful.widget.tasklist.filter.alltags,
forced_height = h,
layout = {
layout = wibox.layout.fixed.horizontal,
},
widget_template = {
{
{
nil,
{
{
awful.widget.clienticon,
widget = wibox.container.place,
halign = "center",
valign = "center",
},
widget = wibox.container.margin,
margins = h / 10,
},
{
{
wibox.widget.base.make_widget(),
forced_height = h / 10,
forced_width = h / 10,
id = "status",
bg = beautiful.dock_unfocused_indicator_bg or "#484E5B",
shape = inner_shape,
widget = wibox.container.background,
},
widget = wibox.container.place, --so the bg widget doesnt get stretched
},
layout = wibox.layout.align.vertical,
},
id = "bg",
widget = wibox.container.background,
bg = beautiful.dock_bg or "#061115",
shape = inner_shape,
},
widget = wibox.container.margin,
margins = h / 10,
forced_height = h,
forced_width = h,
create_callback = function(self, c, _, _)
local function hover(p, t) --so gc can collect all the timed objects that are flying around
local on_hover = rubato.timed({
intro = 0.02,
outro = 0.02,
duration = 0.2,
rate = 30,
pos = p,
subscribed = function(pos)
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg or "#061115", pos)
end,
})
on_hover.target = t
end
self:connect_signal("mouse::enter", function()
hover(0, 20)
end)
self:connect_signal("mouse::leave", function()
hover(20, 0)
end)
self:add_button(awful.button({
modifiers = {},
button = 1,
on_press = function()
if not c.active then
c:activate({
context = "through_dock",
switch_to_tag = true,
})
else
c.minimized = true
end
end,
}))
end,
update_callback = function(self, c, _, _) --praying to the gc that this is getting cleared properly, didnt show problems in testing
collectgarbage("collect")
local status_w = rubato.timed({
intro = 0.02,
outro = 0.02,
duration = 0.1,
rate = 30,
pos = self:get_children_by_id("status")[1].forced_width,
subscribed = function(pos)
self:get_children_by_id("status")[1].forced_width = pos
end,
})
local bg_col = beautiful.dock_unfocused_indicator_bg or "#484E5B"
local bg_focus_col = beautiful.dock_indicator_bg or "#6791C9"
local sh_r, sh_g, sh_b, _ = chel.col_diff(bg_col, bg_focus_col)
local status_c = rubato.timed({
intro = 0.04,
outro = 0.04,
duration = 0.2,
rate = 30,
pos = 0,
subscribed = function(pos)
self:get_children_by_id("status")[1].bg = chel.col_shift(
bg_col,
math.floor(pos * (255 * sh_r)),
math.floor((sh_g * 255) * pos),
math.floor((sh_b * 255) * pos)
)
end,
})
--this here sets width and colors depending on the status of the client a widget in the tasklist represents
if c.active then
status_w.target = h / 2
status_c.target = 1
elseif c.minimized then
status_w.target = h / 10
status_c.target = 0
else
status_w.target = h / 3
status_c.target = 0
end
end,
},
})
-- }}}
-- the funny desktop starters {{{
local pinned_apps = pinneds and { layout = wibox.layout.fixed.horizontal } or nil
if pinneds then
for _, p in ipairs(pinneds) do
pinned_apps[#pinned_apps + 1] = wibox.widget({
{
{
nil,
{
{
{
widget = wibox.widget.imagebox,
image = p.icon,
resize = true,
},
margins = dpi(5),
widget = wibox.container.margin,
},
widget = wibox.container.place,
halign = "center",
valign = "center",
},
{
{
wibox.widget.base.make_widget(),
forced_height = h / 10,
forced_width = h / 10,
id = "status",
shape = inner_shape,
widget = wibox.container.background,
},
widget = wibox.container.place, --so the bg widget doesnt get stretched
halign = "center",
},
layout = wibox.layout.align.vertical,
},
widget = wibox.container.background,
shape = inner_shape,
id = "bg",
buttons = awful.button({}, 1, function()
awful.spawn.easy_async(p.start_cmd)
end),
},
widget = wibox.container.margin,
margins = h / 10,
forced_width = h,
forced_height = h,
})
local self = pinned_apps[#pinned_apps]
local function hover(po, t) --so gc can collect all the timed objects that are flying around
local on_hover = rubato.timed({
intro = 0.02,
outro = 0.02,
duration = 0.2,
rate = 30,
pos = po,
subscribed = function(pos)
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg or "#061115", pos)
end,
})
on_hover.target = t
end
self:connect_signal("mouse::enter", function()
hover(0, 20)
end)
self:connect_signal("mouse::leave", function()
hover(20, 0)
end)
self:add_button(
awful.button({ --this is very hacky. Please do NOT COPY if you are looking for suggestions on how to implement this
modifiers = {},
button = 1,
on_press = function() end,
})
)
end
end
-- }}}
local dock_box = awful.popup({
ontop = true,
screen = s,
x = s.geometry.x + s.geometry.width / 2,
y = s.geometry.y + s.geometry.height - (h + o),
shape = outer_shape,
widget = {
{
{
pinned_apps,
tasklist,
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin,
margin = dpi(5),
},
widget = wibox.container.background,
bg = beautiful.dock_bg or "#061115",
shape = inner_shape,
},
})
dock_box:connect_signal("property::width", function() --for centered placement, wanted to keep the offset
dock_box.x = s.geometry.x + s.geometry.width / 2 - dock_box.width / 2
end)
local autohideanim = rubato.timed({
intro = 0.3,
outro = 0.1,
duration = 0.4,
pos = 0,
rate = 60,
easing = rubato.quadratic,
subscribed = function(pos)
dock_box.y = s.geometry.y + s.geometry.height - ((pos * h) + o)
dock_box.opacity = pos
end,
})
local autohidetimer = gears.timer({
timeout = 2,
single_shot = true,
callback = function()
autohideanim.target = 0
end,
})
dock_box:connect_signal("mouse::leave", function()
autohidetimer:again()
end)
dock_box:connect_signal("mouse::enter", function()
autohideanim.target = 1
autohidetimer:stop()
end)
return dock_box
end
return {
init = init,
}