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
|
export class SettingsWatch {
#settings;
#key_data = new Map();
constructor(settings, ...opts) {
this.#settings = settings;
for (const opt of opts) {
if (typeof opt == 'string') {
this.#addSetting(opt, {});
} else {
for (const [prop_name, opts] of Object.entries(opt)) {
this.#addSetting(prop_name, opts)
}
}
}
}
#addSetting(prop_name, opts) {
let key;
if (typeof opts == 'string') {
key = opts;
opts = {};
} else {
key = opts.key ?? prop_name.replace('_', '-');
}
const settings = this.#settings;
const raw_getter = opts.get_raw ?? this.#defaultRawGetter(settings, key);
const getter = opts.get ?? (x => x);
const update_cb = () => {
let value = getter(raw_getter(settings.get_value(key)));
this.#key_data.get(prop_name).value = value;
return value;
};
this.#key_data.set(prop_name, {});
Object.defineProperty(this, prop_name, {
enumerable: true,
configurable: true,
get() {
let data = this.#key_data.get(prop_name);
if (data.value === undefined) {
data.handler_id = settings.connect('changed::' + key, update_cb);
data.value = update_cb();
}
return data.value;
}
});
}
#defaultRawGetter(settings, key) {
const schema = settings.settings_schema.get_key(key);
const [range_ty, _range] = schema.get_range().recursiveUnpack();
if (range_ty == "enum") {
return value => {
return {
nick: value.unpack(),
// FIXME: remove unnecessary lookup if/when g_settings_schema_key_to_enum()
// becomes available. But for now, an extra lookup will have to do.
value: settings.get_enum(key),
};
};
}
return value => value.recursiveUnpack();
}
clear() {
for (const [key, data] of this.#key_data.entries()) {
if (data.handler_id !== undefined)
this.#settings.disconnect(data.handler_id);
delete this[key];
}
this.#key_data.clear();
}
}
// Allow calling clear as a static function.
SettingsWatch.clear = obj => SettingsWatch.prototype.clear.apply(obj);
|