277 lines
8.5 KiB
Lua
277 lines
8.5 KiB
Lua
|
local awful = require "awful"
|
||
|
local gtable = require "gears.table"
|
||
|
local gdebug = require "gears.debug"
|
||
|
local gfs = require "gears.filesystem"
|
||
|
local h = require "misc.helpers"
|
||
|
local cfg = require "misc.cfg"
|
||
|
local vars = require "misc.vars"
|
||
|
local wibox = require "wibox"
|
||
|
local beautiful = require "beautiful"
|
||
|
local rubato = require "lib.rubato"
|
||
|
local al_prompt = require "lib.bling.widget.app_launcher.prompt"
|
||
|
local btn = awful.button.names
|
||
|
|
||
|
package.cpath = package.cpath .. ";" .. gfs.get_configuration_dir() .. "ui/fresnel/lenses/target/debug/lib?.so"
|
||
|
|
||
|
local lenses = require "lenses"
|
||
|
local max_entries = 10
|
||
|
|
||
|
local fresnel = {}
|
||
|
|
||
|
fresnel._toggled = false
|
||
|
fresnel._entries_exec = {}
|
||
|
fresnel._entries_offset = 0
|
||
|
fresnel._entries_count = 0
|
||
|
fresnel._visible_entries = 0
|
||
|
fresnel._selected_index = 1
|
||
|
|
||
|
function fresnel:_exec_entry(entry_index)
|
||
|
local exec = self._entries_exec[entry_index]
|
||
|
if type(exec) ~= "userdata" then
|
||
|
awful.spawn((exec[2] and cfg.terminal .. " -e " or "") .. exec[1])
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function fresnel:_update(query, scrolled)
|
||
|
query = query or ""
|
||
|
scrolled = scrolled or false
|
||
|
|
||
|
if not scrolled then
|
||
|
self._selected_index = 1
|
||
|
self._entries_offset = 0
|
||
|
end
|
||
|
|
||
|
local layout = self._widget.widget:get_children_by_id("entry_layout")[1]
|
||
|
local status = self._widget.widget:get_children_by_id("status")[1]
|
||
|
local all_providers = {}
|
||
|
local entries_count = 0
|
||
|
|
||
|
self._entries_exec = {}
|
||
|
layout:reset()
|
||
|
|
||
|
for _, provider in h.opairs(lenses) do
|
||
|
local entries = provider(query)
|
||
|
|
||
|
table.sort(entries, function(a, b)
|
||
|
return a.message < b.message
|
||
|
end)
|
||
|
|
||
|
all_providers = gtable.join(all_providers, entries)
|
||
|
end
|
||
|
|
||
|
self._entries_count = #all_providers
|
||
|
|
||
|
for i, entry in ipairs(all_providers) do
|
||
|
if i <= self._entries_offset then
|
||
|
goto continue
|
||
|
end
|
||
|
if entries_count == max_entries then break end
|
||
|
table.insert(self._entries_exec, entry.exec)
|
||
|
|
||
|
local entry_widget = wibox.widget {
|
||
|
widget = wibox.container.background,
|
||
|
shape = vars.shape,
|
||
|
{
|
||
|
widget = wibox.container.margin,
|
||
|
margins = vars.padding,
|
||
|
{
|
||
|
widget = wibox.container.constraint,
|
||
|
strategy = "max",
|
||
|
height = vars.char_height,
|
||
|
{
|
||
|
{
|
||
|
widget = wibox.container.background,
|
||
|
fg = vars.colors.dim.fg,
|
||
|
{
|
||
|
widget = wibox.widget.textbox,
|
||
|
text = entry.provider .. " | "
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
widget = wibox.widget.textbox,
|
||
|
text = entry.message
|
||
|
},
|
||
|
spacing = vars.padding,
|
||
|
layout = wibox.layout.fixed.horizontal
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
buttons = {
|
||
|
awful.button {
|
||
|
modifiers = {},
|
||
|
button = btn.LEFT,
|
||
|
on_press = function()
|
||
|
self:_exec_entry(i)
|
||
|
end
|
||
|
}
|
||
|
},
|
||
|
_selected = false
|
||
|
}
|
||
|
|
||
|
if self._selected_index + self._entries_offset == i then
|
||
|
entry_widget._selected = true
|
||
|
entry_widget.bg = vars.colors.black
|
||
|
end
|
||
|
|
||
|
entry_widget:connect_signal("mouse::enter", function()
|
||
|
if entry_widget._selected == true then return end
|
||
|
entry_widget.bg = vars.colors.black
|
||
|
end)
|
||
|
|
||
|
entry_widget:connect_signal("mouse::leave", function()
|
||
|
if entry_widget._selected == true then return end
|
||
|
entry_widget.bg = vars.colors.bg
|
||
|
end)
|
||
|
|
||
|
layout:add(entry_widget)
|
||
|
|
||
|
entries_count = entries_count + 1
|
||
|
self._visible_entries = entries_count
|
||
|
::continue::
|
||
|
end
|
||
|
|
||
|
status.text = self._entries_offset + self._selected_index .. "/" .. self._entries_count
|
||
|
end
|
||
|
|
||
|
fresnel._text = ""
|
||
|
fresnel._prompt = al_prompt {
|
||
|
prompt = "",
|
||
|
reset_on_stop = true,
|
||
|
ul_cursor = "low",
|
||
|
bg_cursor = vars.colors.black,
|
||
|
changed_callback = function(text)
|
||
|
if fresnel._text == text then return end
|
||
|
if fresnel._toggled == false then return end
|
||
|
fresnel:_update(text)
|
||
|
fresnel._text = text
|
||
|
end,
|
||
|
keypressed_callback = function(mod, key)
|
||
|
if key == "Escape" or key == " " and mod.Mod4 then
|
||
|
fresnel:hide()
|
||
|
elseif key == "Return" then
|
||
|
fresnel:_exec_entry(fresnel._selected_index)
|
||
|
fresnel:hide()
|
||
|
elseif key == "Up" then
|
||
|
local next_index = fresnel._selected_index - 1
|
||
|
if next_index < 1 and fresnel._entries_offset == 0 then
|
||
|
return
|
||
|
elseif next_index < 1 and fresnel._entries_offset > 0 then
|
||
|
fresnel._entries_offset = fresnel._entries_offset - 1
|
||
|
else
|
||
|
fresnel._selected_index = next_index
|
||
|
end
|
||
|
|
||
|
fresnel:_update(fresnel._text, true)
|
||
|
elseif key == "Down" then
|
||
|
local next_index = fresnel._selected_index + 1
|
||
|
if next_index > fresnel._visible_entries and fresnel._entries_offset + fresnel._visible_entries == fresnel._entries_count then
|
||
|
return
|
||
|
elseif next_index > fresnel._visible_entries and fresnel._entries_offset + fresnel._visible_entries < fresnel._entries_count then
|
||
|
fresnel._entries_offset = fresnel._entries_offset + 1
|
||
|
else
|
||
|
fresnel._selected_index = next_index
|
||
|
end
|
||
|
|
||
|
fresnel:_update(fresnel._text, true)
|
||
|
end
|
||
|
end
|
||
|
}
|
||
|
|
||
|
fresnel._widget = h.popup {
|
||
|
visible = false,
|
||
|
ontop = true,
|
||
|
placement = function(d)
|
||
|
awful.placement.top(d, {
|
||
|
margins = {
|
||
|
top = beautiful.useless_gap * 2
|
||
|
}
|
||
|
})
|
||
|
end,
|
||
|
minimum_width = screen[1].geometry.width / 2,
|
||
|
maximum_width = screen[1].geometry.width / 2,
|
||
|
widget = {
|
||
|
{
|
||
|
widget = wibox.container.background,
|
||
|
bg = vars.colors.black,
|
||
|
fg = vars.colors.dim.fg,
|
||
|
shape = vars.shape,
|
||
|
{
|
||
|
widget = wibox.container.margin,
|
||
|
margins = vars.padding,
|
||
|
{
|
||
|
{
|
||
|
widget = wibox.widget.textbox,
|
||
|
text = ">"
|
||
|
},
|
||
|
{
|
||
|
widget = wibox.container.margin,
|
||
|
margins = {
|
||
|
left = vars.padding,
|
||
|
right = vars.padding
|
||
|
},
|
||
|
{
|
||
|
widget = wibox.container.constraint,
|
||
|
strategy = "max",
|
||
|
height = vars.char_height,
|
||
|
{
|
||
|
widget = wibox.container.background,
|
||
|
fg = vars.colors.fg,
|
||
|
fresnel._prompt.textbox
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
widget = wibox.widget.textbox,
|
||
|
text = "0/0",
|
||
|
id = "status"
|
||
|
},
|
||
|
layout = wibox.layout.align.horizontal
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
widget = wibox.container.margin,
|
||
|
margins = {
|
||
|
top = vars.padding
|
||
|
},
|
||
|
{
|
||
|
spacing = vars.padding,
|
||
|
layout = wibox.layout.fixed.vertical,
|
||
|
id = "entry_layout"
|
||
|
}
|
||
|
},
|
||
|
layout = wibox.layout.align.vertical
|
||
|
}
|
||
|
}
|
||
|
fresnel._widget.maximum_height = vars.big_padding * 2 + (vars.padding * 2 + vars.char_height) * (1 + 10) + vars.padding + vars.padding * 9
|
||
|
|
||
|
function fresnel:show()
|
||
|
self._toggled = true
|
||
|
self._timed.target = 1
|
||
|
self:_update()
|
||
|
self._prompt:start()
|
||
|
end
|
||
|
|
||
|
function fresnel:hide()
|
||
|
self._toggled = false
|
||
|
self._timed.target = 0
|
||
|
self._prompt:stop()
|
||
|
end
|
||
|
|
||
|
fresnel._timed = rubato.timed {
|
||
|
duration = vars.anim_duration,
|
||
|
intro = vars.anim_intro,
|
||
|
pos = 0,
|
||
|
subscribed = function(pos)
|
||
|
fresnel._widget.opacity = pos
|
||
|
|
||
|
if pos == 0 then
|
||
|
fresnel._widget.visible = false
|
||
|
else
|
||
|
fresnel._widget.visible = true
|
||
|
end
|
||
|
end
|
||
|
}
|
||
|
|
||
|
return fresnel
|