summaryrefslogtreecommitdiff
path: root/lang/lua/astal/binding.lua
blob: 610f3a681bbe9c315401d9eb6e403fa34d776a16 (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
local lgi = require("lgi")
local GObject = lgi.require("GObject", "2.0")

---@class Binding
---@field emitter table|Variable
---@field property? string
---@field transform_fn function
local Binding = {}

---@param emitter table | userdata
---@param property? string
---@return Binding
function Binding.new(emitter, property)
    return setmetatable({
        emitter = emitter,
        property = property,
        transform_fn = function(v)
            return v
        end,
    }, Binding)
end

function Binding:__tostring()
    local str = "Binding<" .. tostring(self.emitter)
    if self.property ~= nil then
        str = str .. ", " .. self.property
    end
    return str .. ">"
end

---@return any
function Binding:get()
    if self.property ~= nil and GObject.Object:is_type_of(self.emitter) then
        return self.transform_fn(self.emitter[self.property])
    elseif type(self.emitter.get) == "function" then
        return self.transform_fn(self.emitter:get())
    end
    error("can not get: Not a GObject or a Variable " + self)
end

---@param transform fun(value: any): any
---@return Binding
function Binding:as(transform)
    local b = Binding.new(self.emitter, self.property)
    b.transform_fn = function(v)
        return transform(self.transform_fn(v))
    end
    return b
end

---@param callback fun(value: any)
---@return function
function Binding:subscribe(callback)
    if self.property ~= nil and GObject.Object:is_type_of(self.emitter) then
        local id = self.emitter.on_notify:connect(function()
            callback(self:get())
        end, self.property, false)
        return function()
            GObject.signal_handler_disconnect(self.emitter, id)
        end
    elseif type(self.emitter.subscribe) == "function" then
        return self.emitter:subscribe(function()
            callback(self:get())
        end)
    end
    error("can not subscribe: Not a GObject or a Variable " + self)
end

Binding.__index = Binding
return Binding