You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
4.9 KiB
144 lines
4.9 KiB
--[[ |
|
|
|
Licensed under GNU General Public License v2 |
|
* (c) 2017, Simon Désaulniers <sim.desaulniers@gmail.com> |
|
* (c) 2017, Uli Schlachter |
|
* (c) 2017, Jeferson Siqueira <jefersonlsiq@gmail.com> |
|
|
|
--]] |
|
|
|
-- Menu iterator with Naughty notifications |
|
-- lain.util.menu_iterator |
|
|
|
local naughty = require("naughty") |
|
local helpers = require("lain.helpers") |
|
local atable = require("awful.util").table |
|
local assert = assert |
|
local pairs = pairs |
|
local tconcat = table.concat |
|
local unpack = unpack or table.unpack -- lua 5.1 retro-compatibility |
|
|
|
local state = { cid = nil } |
|
|
|
local function naughty_destroy_callback(reason) |
|
local closed = naughty.notificationClosedReason |
|
if reason == closed.expired or reason == closed.dismissedByUser then |
|
local actions = state.index and state.menu[state.index - 1][2] |
|
if actions then |
|
for _,action in pairs(actions) do |
|
-- don't try to call nil callbacks |
|
if action then action() end |
|
end |
|
state.index = nil |
|
end |
|
end |
|
end |
|
|
|
-- Iterates over a menu. |
|
-- After the timeout, callbacks associated to the last visited choice are |
|
-- executed. Inputs: |
|
-- * menu: a list of {label, {callbacks}} pairs |
|
-- * timeout: time to wait before confirming the menu selection |
|
-- * icon: icon to display in the notification of the chosen label |
|
local function iterate(menu, timeout, icon) |
|
timeout = timeout or 4 -- default timeout for each menu entry |
|
icon = icon or nil -- icon to display on the menu |
|
|
|
-- Build the list of choices |
|
if not state.index then |
|
state.menu = menu |
|
state.index = 1 |
|
end |
|
|
|
-- Select one and display the appropriate notification |
|
local label |
|
local next = state.menu[state.index] |
|
state.index = state.index + 1 |
|
|
|
if not next then |
|
label = "Cancel" |
|
state.index = nil |
|
else |
|
label, _ = unpack(next) |
|
end |
|
|
|
state.cid = naughty.notify({ |
|
text = label, |
|
icon = icon, |
|
timeout = timeout, |
|
screen = mouse.screen, |
|
replaces_id = state.cid, |
|
destroy = naughty_destroy_callback |
|
}).id |
|
end |
|
|
|
-- Generates a menu compatible with the first argument of `iterate` function and |
|
-- suitable for the following cases: |
|
-- * all possible choices individually (partition of singletons); |
|
-- * all possible subsets of the set of choices (powerset). |
|
-- |
|
-- Inputs: |
|
-- * args: an array containing the following members: |
|
-- * choices: Array of choices (string) on which the menu will be |
|
-- generated. |
|
-- * name: Displayed name of the menu (in the form "name: choices"). |
|
-- * selected_cb: Callback to execute for each selected choice. Takes |
|
-- the choice as a string argument. Can be `nil` (no action |
|
-- to execute). |
|
-- * rejected_cb: Callback to execute for each rejected choice (possible |
|
-- choices which are not selected). Takes the choice as a |
|
-- string argument. Can be `nil` (no action to execute). |
|
-- * extra_choices: An array of extra { choice_str, callback_fun } pairs to be |
|
-- added to the menu. Each callback_fun can be `nil`. |
|
-- * combination: The combination of choices to generate. Possible values: |
|
-- "powerset" and "single" (default). |
|
-- Output: |
|
-- * m: menu to be iterated over. |
|
local function menu(args) |
|
local choices = assert(args.choices or args[1]) |
|
local name = assert(args.name or args[2]) |
|
local selected_cb = args.selected_cb |
|
local rejected_cb = args.rejected_cb |
|
local extra_choices = args.extra_choices or {} |
|
|
|
local ch_combinations = args.combination == "powerset" and helpers.powerset(choices) or helpers.trivial_partition_set(choices) |
|
|
|
for _, c in pairs(extra_choices) do |
|
ch_combinations = atable.join(ch_combinations, {{c[1]}}) |
|
end |
|
|
|
local m = {} -- the menu |
|
|
|
for _,c in pairs(ch_combinations) do |
|
if #c > 0 then |
|
local cbs = {} |
|
|
|
-- selected choices |
|
for _,ch in pairs(c) do |
|
if atable.hasitem(choices, ch) then |
|
cbs[#cbs + 1] = selected_cb and function() selected_cb(ch) end or nil |
|
end |
|
end |
|
|
|
-- rejected choices |
|
for _,ch in pairs(choices) do |
|
if not atable.hasitem(c, ch) and atable.hasitem(choices, ch) then |
|
cbs[#cbs + 1] = rejected_cb and function() rejected_cb(ch) end or nil |
|
end |
|
end |
|
|
|
-- add user extra choices (like the choice "None" for example) |
|
for _,x in pairs(extra_choices) do |
|
if x[1] == c[1] then |
|
cbs[#cbs + 1] = x[2] |
|
end |
|
end |
|
|
|
m[#m + 1] = { name .. ": " .. tconcat(c, " + "), cbs } |
|
end |
|
end |
|
|
|
return m |
|
end |
|
|
|
return { iterate = iterate, menu = menu }
|
|
|