summaryrefslogtreecommitdiff
path: root/pkgs/astal/src/widget/launcher.lua
blob: cbac6c309b6ac7a716a144a80d42e441d1c0733f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
local astal = require("astal")
local Widget = require("astal.gtk3.widget")
local App = require("astal.gtk3.app")
local Gdk = require("astal.gtk3").Gdk
local Gtk = require("astal.gtk3").Gtk
local astalify = require("astal.gtk3").astalify
local Apps = astal.require("AstalApps")
local Variable = astal.Variable
local lib = require("lib")

local MAX_ENTRIES = 20

local FlowBox = astalify(Gtk.FlowBox)
local FlowBoxChild = astalify(Gtk.FlowBoxChild)

local apps = Apps.Apps()
local text = Variable("")
local list = text(function(text)
	return lib.slice(apps:exact_query(text), 0, MAX_ENTRIES)
end)

function on_show()
	text:set("")
end

function close()
	App:quit()
end

function on_key_press(self, event)
	if event.keyval == Gdk.KEY_Escape then
		close()
	end
end

function on_enter()
	local found = apps:exact_query(text:get())[1]
	if found then
		found:launch()
		close()
	end
end

function Application(app)
	return FlowBoxChild({
		Widget.Button({
			class_name = "app",
			on_clicked = function()
				app:launch()
				close()
			end,
			Widget.Box({
				halign = "CENTER",
				valign = "CENTER",
				vertical = true,
				Widget.Icon({
					icon = app.icon_name,
				}),
				Widget.Label({
					class_name = "name",
					label = app.name,
					valign = "CENTER",
					ellipsize = "END",
					max_width_chars = 20,
				}),
			}),
		}),
	})
end

function Applications(apps)
	return FlowBox({
		hexpand = true,
		homogeneous = true,
		class_name = "apps",
		lib.map(apps, Application)
	})
end

function Launcher()
	return Widget.Box({
		vertical = true,
		Widget.Entry({
			class_name = "search",
			placeholder_text = "Search",
			halign = "CENTER",
			text = text(),
			on_changed = function(self)
				text:set(self.text)
			end,
			on_activate = on_enter,
		}),
		Widget.Box({
			class_name = "apps",
			list:as(Applications),
		}),
	})
end

return function()
	local Anchor = astal.require('Astal').WindowAnchor

	return Widget.Window({
		class_name = "launcher",
		anchor = Anchor.TOP + Anchor.BOTTOM + Anchor.LEFT + Anchor.RIGHT,
		exclusivity = "EXCLUSIVE",
		keymode = "ON_DEMAND",
		application = App,
		on_show = on_show,
		on_key_press_event = on_key_press,
		Launcher(),
	})
end