diff options
Diffstat (limited to '.config/awesome/ui/fresnel/init.lua')
| -rw-r--r-- | .config/awesome/ui/fresnel/init.lua | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/.config/awesome/ui/fresnel/init.lua b/.config/awesome/ui/fresnel/init.lua new file mode 100644 index 0000000..cf1357a --- /dev/null +++ b/.config/awesome/ui/fresnel/init.lua @@ -0,0 +1,276 @@ +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 |
