Repository navigation
Expand file tree
/
Copy pathmain.ts
More file actions
188 lines (154 loc) · 5.64 KB
/
Copy pathmain.ts
File metadata and controls
188 lines (154 loc) · 5.64 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
* SPDX-FileCopyrightText: 2020 Andy Holmes <andrew.g.r.holmes@gmail.com>
* @source https://gitlab.gnome.org/GNOME/gjs/-/blob/master/examples/glistmodel.js
*/
import Gio from "gi://Gio?version=2.0";
import GObject from "gi://GObject?version=2.0";
// Include signals provided by the registered GObject interface.
interface GjsListStoreSignals extends GObject.Object.SignalSignatures, Gio.ListModel.SignalSignatures {}
/**
* An example of implementing the GListModel interface using the new virtual interface pattern.
*
* With the new virtual interface generation, you only need to implement the virtual methods
* (vfunc_*) instead of all interface methods. The regular methods are automatically provided
* by the GObject runtime.
*/
export class GjsListStore extends GObject.Object implements Gio.ListModel.Interface<GObject.Object> {
// ===============================================================
// REGULAR METHODS - These are automatically provided by GObject runtime
// but included for TypeScript compatibility during development
// ===============================================================
declare get_item: Gio.ListModel["get_item"];
declare get_item_type: Gio.ListModel["get_item_type"];
declare get_n_items: Gio.ListModel["get_n_items"];
declare connect: GObject.SignalMethods<this, GjsListStoreSignals>["connect"];
declare connect_after: GObject.SignalMethods<this, GjsListStoreSignals>["connect_after"];
declare emit: GObject.SignalMethods<this, GjsListStoreSignals>["emit"];
static {
GObject.registerClass(
{
GTypeName: "GjsListStore",
Implements: [Gio.ListModel],
},
GjsListStore,
);
}
_items: GObject.Object[] = [];
constructor() {
super();
/* We'll use a native Array as internal storage for the list model */
this._items = [];
}
// ===============================================================
// VIRTUAL METHODS - These must be implemented for the interface
// ===============================================================
/* Implementing this function amounts to returning a GType. This could be a
* more specific GType, but must be a subclass of GObject.
*/
vfunc_get_item_type() {
const res = GObject.Object.$gtype;
print("vfunc_get_item_type", res);
return res;
}
/* Implementing this function just requires returning the GObject at
* @position or %null if out-of-range. This must explicitly return %null,
* not `undefined`.
*/
vfunc_get_item(position: number) {
const res = this._items[position] || null;
print("vfunc_get_item", res);
return res;
}
/* Implementing this function is as simple as return the length of the
* storage object, in this case an Array.
*/
vfunc_get_n_items() {
const res = this._items.length;
print("vfunc_get_n_items", res);
return res;
}
// items_changed is provided by GObject.Object, signal emission
items_changed(position: number, removed: number, added: number) {
print(`items_changed position: ${position}, removed: ${removed}, added: ${added}`);
this.emit("items-changed", position, removed, added);
}
// ===============================================================
// HELPER METHODS - Custom functionality for this list store
// ===============================================================
/**
* Insert an item in the list. If @position is greater than the number of
* items in the list or less than `0` it will be appended to the end of the
* list.
*
* @param item - the item to add
* @param position - the position to add the item
*/
insertItem(item: GObject.Object, position: number) {
if (!(item instanceof GObject.Object)) throw new TypeError("not a GObject");
if (position < 0 || position > this._items.length) position = this._items.length;
this._items.splice(position, 0, item);
this.items_changed(position, 0, 1);
}
/**
* Append an item to the list.
*
* @param item - the item to add
*/
appendItem(item: GObject.Object) {
if (!(item instanceof GObject.Object)) throw new TypeError("not a GObject");
const position = this._items.length;
this._items.push(item);
this.items_changed(position, 0, 1);
}
/**
* Prepend an item to the list.
*
* @param item - the item to add
*/
prependItem(item: GObject.Object) {
if (!(item instanceof GObject.Object)) throw new TypeError("not a GObject");
this._items.unshift(item);
this.items_changed(0, 0, 1);
}
/**
* Remove @item from the list. If @item is not in the list, this function
* does nothing.
*
* @param item - the item to remove
*/
removeItem(item: GObject.Object) {
if (!(item instanceof GObject.Object)) throw new TypeError("not a GObject");
const position = this._items.indexOf(item);
if (position === -1) return;
this._items.splice(position, 1);
this.items_changed(position, 1, 0);
}
/**
* Remove the item at @position. If @position is outside the length of the
* list, this function does nothing.
*
* @param position - the position of the item to remove
*/
removePosition(position: number) {
if (position < 0 || position >= this._items.length) return;
this._items.splice(position, 1);
this.items_changed(position, 1, 0);
}
/**
* Clear the list of all items.
*/
clear() {
const length = this._items.length;
if (length === 0) return;
this._items = [];
this.items_changed(0, length, 0);
}
}
// Create an example instance demonstrating the new virtual interface pattern
const listStore = new GjsListStore();
listStore.insertItem(new GObject.Object(), 0);
listStore.appendItem(new GObject.Object());
print("GjsListStore example:");
print(`Items in store: ${listStore.get_n_items()}`);
print(`Item type: ${listStore.get_item_type()}`);