dazscript-framework 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +365 -93
- package/babel.config.js +33 -33
- package/dist/babel/trace-babel-plugin.js +243 -243
- package/dist/babel/trace-log-babel-plugin.js +164 -164
- package/dist/scripts/install-generator.js +185 -185
- package/package.json +72 -70
- package/src/common/dz-dump.ts +120 -120
- package/src/common/log.ts +56 -56
- package/src/common/trace.ts +26 -26
- package/src/core/action-decorator.ts +15 -15
- package/src/core/base-script.ts +30 -30
- package/src/core/custom-action.ts +11 -11
- package/src/core/global.ts +4 -4
- package/src/dialog/basic-dialog.ts +40 -32
- package/src/dialog/builders/button-builder.ts +52 -52
- package/src/dialog/builders/checkbox-builder.ts +29 -29
- package/src/dialog/builders/color-picker-builder.ts +35 -35
- package/src/dialog/builders/combo-box-builder.ts +38 -35
- package/src/dialog/builders/combo-edit-builder.ts +35 -35
- package/src/dialog/builders/dialog-builder.ts +49 -49
- package/src/dialog/builders/groupbox-builder.ts +121 -82
- package/src/dialog/builders/label-builder.ts +33 -28
- package/src/dialog/builders/layout-builder.ts +59 -59
- package/src/dialog/builders/line-edit-builder.ts +124 -119
- package/src/dialog/builders/list-box-builder.ts +103 -0
- package/src/dialog/builders/list-view-builder.ts +396 -328
- package/src/dialog/builders/node-selection-builder.ts +55 -55
- package/src/dialog/builders/path-combo-box-builder.ts +24 -24
- package/src/dialog/builders/popup-menu-builder.ts +46 -46
- package/src/dialog/builders/radio-builder.ts +42 -42
- package/src/dialog/builders/slider-builder.ts +39 -22
- package/src/dialog/builders/splitter-builder.ts +88 -88
- package/src/dialog/builders/tab-builder.ts +120 -106
- package/src/dialog/builders/widget-builder.ts +136 -124
- package/src/dialog/builders/widgets-builder.ts +140 -135
- package/src/dialog/input-dialog.ts +30 -27
- package/src/dialog/input-validator.ts +8 -8
- package/src/dialog/selection-dialog.ts +47 -0
- package/src/dialog/shared.ts +8 -8
- package/src/helpers/action-helper.ts +214 -81
- package/src/helpers/array-helper.ts +170 -145
- package/src/helpers/camera-helper.ts +12 -12
- package/src/helpers/custom-action-helper.ts +176 -176
- package/src/helpers/directory-helper.ts +14 -0
- package/src/helpers/file-helper.ts +90 -90
- package/src/helpers/http-helper.ts +190 -0
- package/src/helpers/input-helper.ts +18 -18
- package/src/helpers/list-view-helper.ts +105 -89
- package/src/helpers/menu-helper.ts +28 -28
- package/src/helpers/message-box-helper.ts +25 -15
- package/src/helpers/node-helper.ts +461 -236
- package/src/helpers/number-helper.ts +10 -10
- package/src/helpers/numeric-property-helper.ts +91 -91
- package/src/helpers/object-helper.ts +2 -2
- package/src/helpers/pane-helper.ts +28 -20
- package/src/helpers/progress-helper.ts +51 -33
- package/src/helpers/property-helper.ts +61 -52
- package/src/helpers/record-helper.ts +16 -16
- package/src/helpers/scene-helper.ts +144 -94
- package/src/helpers/script-helper.ts +15 -15
- package/src/helpers/skeleton-helper.ts +26 -26
- package/src/helpers/splitter-helper.ts +8 -8
- package/src/helpers/string-helper.ts +39 -31
- package/src/helpers/surface-helper.ts +5 -5
- package/src/helpers/undo-helper.ts +8 -8
- package/src/helpers/viewport-helper.ts +21 -8
- package/src/lib/delayed.ts +38 -38
- package/src/lib/dictionary.ts +3 -0
- package/src/lib/frame-keys.ts +67 -67
- package/src/lib/guid.ts +2 -2
- package/src/lib/menu-item.ts +10 -9
- package/src/lib/observable.ts +147 -94
- package/src/lib/set.ts +50 -25
- package/src/lib/settings.ts +112 -104
- package/src/lib/tree-node.ts +149 -145
- package/src/samples/config.ts +2 -2
- package/src/samples/hello-world.dsa.ts +12 -12
- package/src/samples/sample-dialog.dsa.ts +51 -51
- package/src/samples/sample-dialog.ts +48 -48
- package/src/shared/set-keyboard-shortcut.ts +146 -102
- package/tsconfig.json +116 -116
- package/webpack.config.js +70 -70
|
@@ -1,328 +1,396 @@
|
|
|
1
|
-
import { warn } from '@dsf/common/log';
|
|
2
|
-
import { clearColumns, filter, getDataItem, setDataItem } from '@dsf/helpers/list-view-helper';
|
|
3
|
-
import { Delayed } from '@dsf/lib/delayed';
|
|
4
|
-
import { Observable } from '@dsf/lib/observable';
|
|
5
|
-
import { TreeNode } from '@dsf/lib/tree-node';
|
|
6
|
-
import { IWidgetBuilder, createWidget } from './widget-builder';
|
|
7
|
-
import { WidgetBuilderContext } from './widgets-builder';
|
|
8
|
-
|
|
9
|
-
type ListViewFilterOptions = {
|
|
10
|
-
keywords: Observable<string>,
|
|
11
|
-
field: (listItem: DzListViewItem) => string,
|
|
12
|
-
selectOnFilter?: boolean,
|
|
13
|
-
filters?: (viewItem: DzListViewItem) => boolean,
|
|
14
|
-
delay?: { min: number, max: number }
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export enum ListViewRefreshOptions {
|
|
18
|
-
All,
|
|
19
|
-
Filters
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class ListViewBuilder<TItem, TData> implements IWidgetBuilder<DzListView> {
|
|
23
|
-
|
|
24
|
-
private readonly context: ListViewBuilderContext<TItem, TData>
|
|
25
|
-
|
|
26
|
-
constructor(dialogContext: WidgetBuilderContext) {
|
|
27
|
-
this.context = new ListViewBuilderContext(dialogContext)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
visible(value: boolean | Observable<boolean>): this {
|
|
31
|
-
this.context.visible = typeof value === 'boolean'
|
|
32
|
-
? new Observable(value)
|
|
33
|
-
: value
|
|
34
|
-
return this
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.context.
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
49
|
-
* @param
|
|
50
|
-
* @returns
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
this.context.
|
|
54
|
-
return this
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
this.context.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return this
|
|
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
|
-
this
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
*
|
|
163
|
-
* @
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
context.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
}
|
|
1
|
+
import { warn } from '@dsf/common/log';
|
|
2
|
+
import { clearColumns, filter, getDataItem, setDataItem } from '@dsf/helpers/list-view-helper';
|
|
3
|
+
import { Delayed } from '@dsf/lib/delayed';
|
|
4
|
+
import { Observable } from '@dsf/lib/observable';
|
|
5
|
+
import { TreeNode } from '@dsf/lib/tree-node';
|
|
6
|
+
import { IWidgetBuilder, createWidget } from './widget-builder';
|
|
7
|
+
import { WidgetBuilderContext } from './widgets-builder';
|
|
8
|
+
|
|
9
|
+
type ListViewFilterOptions = {
|
|
10
|
+
keywords: Observable<string>,
|
|
11
|
+
field: (listItem: DzListViewItem) => string,
|
|
12
|
+
selectOnFilter?: boolean,
|
|
13
|
+
filters?: (viewItem: DzListViewItem) => boolean,
|
|
14
|
+
delay?: { min: number, max: number }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export enum ListViewRefreshOptions {
|
|
18
|
+
All,
|
|
19
|
+
Filters
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class ListViewBuilder<TItem, TData> implements IWidgetBuilder<DzListView> {
|
|
23
|
+
|
|
24
|
+
private readonly context: ListViewBuilderContext<TItem, TData>
|
|
25
|
+
|
|
26
|
+
constructor(dialogContext: WidgetBuilderContext) {
|
|
27
|
+
this.context = new ListViewBuilderContext(dialogContext)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
visible(value: boolean | Observable<boolean>): this {
|
|
31
|
+
this.context.visible = typeof value === 'boolean'
|
|
32
|
+
? new Observable(value)
|
|
33
|
+
: value
|
|
34
|
+
return this
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
height(value: number): this {
|
|
38
|
+
this.context.height = value
|
|
39
|
+
return this
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
minHeight(value: number): this {
|
|
43
|
+
this.context.minHeight = value
|
|
44
|
+
return this
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Binds the list rows to a collection of items
|
|
49
|
+
* @param items
|
|
50
|
+
* @returns
|
|
51
|
+
*/
|
|
52
|
+
items(items: Observable<TreeNode<TItem>[]>): ListViewBindBuilder<TItem, TData> {
|
|
53
|
+
this.context.items = items
|
|
54
|
+
return new ListViewBindBuilder(this.context)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Build an item row with the provided function
|
|
59
|
+
* @param build the function to use for building a row
|
|
60
|
+
* @returns returns a ListViewItem or DzCheckListItem
|
|
61
|
+
*/
|
|
62
|
+
row(build: (item: TreeNode<TItem>, parent: DzListView | DzListViewItem, id?: number) => DzListViewItem): this {
|
|
63
|
+
this.context.rowBuilder = build
|
|
64
|
+
return this
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
sorting(sort: boolean | number, order: 'asc' | 'desc' = 'asc'): this {
|
|
68
|
+
if (typeof sort === 'boolean')
|
|
69
|
+
this.context.sorting = sort ? 0 : -1
|
|
70
|
+
else
|
|
71
|
+
this.context.sorting = sort
|
|
72
|
+
this.context.sortAscending = order === 'asc'
|
|
73
|
+
return this
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
sortOnBuild(onOff: boolean = true): this {
|
|
77
|
+
this.context.sortOnBuild = onOff
|
|
78
|
+
return this
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
expanded(onOff: boolean | Observable<boolean>): this {
|
|
82
|
+
if (typeof onOff === 'boolean')
|
|
83
|
+
this.context.expanded = new Observable(onOff)
|
|
84
|
+
else
|
|
85
|
+
this.context.expanded = onOff
|
|
86
|
+
return this
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
flat(onOff: boolean | Observable<boolean>): this {
|
|
90
|
+
this.context.flat = typeof onOff === 'boolean'
|
|
91
|
+
? new Observable(onOff)
|
|
92
|
+
: onOff
|
|
93
|
+
return this
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
doubleClicked(bind: Observable<TData>): this {
|
|
97
|
+
this.context.doubleClicked = bind
|
|
98
|
+
return this
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
refresh(when: Observable<any>, what: ListViewRefreshOptions = ListViewRefreshOptions.All): this {
|
|
102
|
+
this.context.refreshWhen = when
|
|
103
|
+
this.context.refreshWhat = what
|
|
104
|
+
return this
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
contextMenu(fn: (listView: DzListView, item: DzListViewItem, pos: Point) => DzPopupMenu): this {
|
|
108
|
+
this.context.contextMenu = fn
|
|
109
|
+
return this
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
build(then?: (listView: DzListView) => void): DzListView {
|
|
113
|
+
let listView = build(this.context)
|
|
114
|
+
then?.(listView)
|
|
115
|
+
return listView
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
class ListViewBuilderContext<TItem, TData> {
|
|
120
|
+
columns: Observable<string[]> = new Observable([])
|
|
121
|
+
columnsWidth?: (index: number, width: number, listView: any) => number
|
|
122
|
+
items: Observable<TreeNode<TItem>[]> = new Observable([])
|
|
123
|
+
text: (item: TreeNode<TItem>) => string[]
|
|
124
|
+
data: (item: TreeNode<TItem>) => TData
|
|
125
|
+
sorting: number = 0
|
|
126
|
+
sortAscending: boolean = true
|
|
127
|
+
sortOnBuild: boolean = true
|
|
128
|
+
selected: Observable<TData>
|
|
129
|
+
filter: ListViewFilterOptions
|
|
130
|
+
doubleClicked: Observable<TData>
|
|
131
|
+
rowBuilder: (item: TreeNode<TItem>, parent: DzListView | DzListViewItem, id?: number) => DzListViewItem
|
|
132
|
+
contextMenu: (listView: DzListView, item: DzListViewItem, pos: Point) => DzPopupMenu
|
|
133
|
+
refreshWhen: Observable<void>
|
|
134
|
+
expanded: Observable<boolean>
|
|
135
|
+
visible: Observable<boolean> = new Observable(true)
|
|
136
|
+
height: number | null = null
|
|
137
|
+
minHeight: number | null = null
|
|
138
|
+
decorated: boolean
|
|
139
|
+
flat: Observable<boolean>
|
|
140
|
+
refreshWhat: ListViewRefreshOptions = ListViewRefreshOptions.All
|
|
141
|
+
constructor(public readonly dialogContext: WidgetBuilderContext) { }
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
class ListViewBindBuilder<TItem, TData> {
|
|
145
|
+
constructor(private context: ListViewBuilderContext<TItem, TData>) { }
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Sepecify the text to display on each column
|
|
149
|
+
* @param columns
|
|
150
|
+
* @returns
|
|
151
|
+
*/
|
|
152
|
+
columns(columns: string[] | Observable<string[]>, width?: (index: number, width: number, listView: any) => number): this {
|
|
153
|
+
this.context.columns = columns instanceof Observable
|
|
154
|
+
? columns
|
|
155
|
+
: new Observable(columns)
|
|
156
|
+
this.context.columnsWidth = width
|
|
157
|
+
return this
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Callback for extracting the text to display on each column from every item in the list
|
|
162
|
+
* @param from the callback function to extract the text for each item
|
|
163
|
+
* @returns a string array for every column text to be display for a given item
|
|
164
|
+
*/
|
|
165
|
+
text(from: (item: TreeNode<TItem>) => string[]): this {
|
|
166
|
+
this.context.text = from
|
|
167
|
+
return this
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Callback to specify which part of the item will be stored in each row as data. It can be
|
|
172
|
+
* the whole item or a property of the item
|
|
173
|
+
* @param from the callback function to specify what to store as data
|
|
174
|
+
* @returns the data to be stored in each row for a given item
|
|
175
|
+
*/
|
|
176
|
+
data(from: (item: TreeNode<TItem>) => TData): this {
|
|
177
|
+
this.context.data = from
|
|
178
|
+
return this
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Bind the data of a selected row in the list to an object
|
|
183
|
+
* @param bind
|
|
184
|
+
* @returns
|
|
185
|
+
*/
|
|
186
|
+
selected(bind: Observable<TData>): this {
|
|
187
|
+
this.context.selected = bind
|
|
188
|
+
return this
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
filter(options: ListViewFilterOptions): this {
|
|
192
|
+
this.context.filter = options
|
|
193
|
+
return this
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
build(then?: (listView: DzListView) => void): DzListView {
|
|
197
|
+
let listView = build(this.context)
|
|
198
|
+
then?.(listView)
|
|
199
|
+
return listView
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const build = <TItem, TData>(context: ListViewBuilderContext<TItem, TData>): DzListView => {
|
|
204
|
+
const listView = createWidget(context.dialogContext).build(DzListView)
|
|
205
|
+
let rowId = -1
|
|
206
|
+
|
|
207
|
+
if (context.visible) {
|
|
208
|
+
if (context.visible.value === false)
|
|
209
|
+
listView.hide()
|
|
210
|
+
context.visible.connect((visible) => {
|
|
211
|
+
if (visible)
|
|
212
|
+
listView.show()
|
|
213
|
+
else
|
|
214
|
+
listView.hide()
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (context.height !== null) {
|
|
219
|
+
listView.height = context.height
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (context.minHeight !== null) {
|
|
223
|
+
listView.minHeight = context.minHeight
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const buildColumns = (columns: string[]) => {
|
|
227
|
+
clearColumns(listView)
|
|
228
|
+
columns.forEach(column => {
|
|
229
|
+
listView.addColumn(column)
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const buildItem = (item: TreeNode<TItem>, parent: DzListView | DzListViewItem) => {
|
|
234
|
+
rowId++
|
|
235
|
+
parent = context.flat?.value === true ? listView : parent
|
|
236
|
+
|
|
237
|
+
let listItem = context.rowBuilder ? context.rowBuilder(item, parent, rowId) : new DzListViewItem(parent, rowId)
|
|
238
|
+
if (!listItem) return
|
|
239
|
+
|
|
240
|
+
listItem.open = context.expanded?.value === true
|
|
241
|
+
let data = context.data ? context.data(item) : item.value
|
|
242
|
+
if (data != null) {
|
|
243
|
+
setDataItem(listItem, data)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
context.text(item).forEach((text, idx) => {
|
|
247
|
+
if (!text || idx >= context.columns.value.length)
|
|
248
|
+
return;
|
|
249
|
+
listItem.setText(idx, text)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
item.children.forEach((child) => {
|
|
253
|
+
context.decorated = true
|
|
254
|
+
buildItem(child, listItem)
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const filterList = (keywords?: string) => {
|
|
259
|
+
filter(listView, context.filter.field, keywords ?? context.filter?.keywords?.value, { selectOnFilter: context.filter.selectOnFilter ?? true, filters: context.filter.filters })
|
|
260
|
+
}
|
|
261
|
+
let delayedFilter: Delayed | null = null
|
|
262
|
+
|
|
263
|
+
const buildList = (items: TreeNode<TItem>[], selectedId?: number) => {
|
|
264
|
+
rowId = -1
|
|
265
|
+
context.decorated = false
|
|
266
|
+
if (!context.text)
|
|
267
|
+
return warn('No text function provided for list builder')
|
|
268
|
+
|
|
269
|
+
listView.clear()
|
|
270
|
+
context.columns?.value.forEach((_, index) => {
|
|
271
|
+
listView.setColumnWidth(index, 0)
|
|
272
|
+
})
|
|
273
|
+
listView.allColumnsShowFocus = true
|
|
274
|
+
|
|
275
|
+
if (context.visible.value === false)
|
|
276
|
+
return
|
|
277
|
+
|
|
278
|
+
if (!items) return
|
|
279
|
+
|
|
280
|
+
items.forEach((item) => {
|
|
281
|
+
buildItem(item, listView)
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
if (context.columnsWidth) {
|
|
285
|
+
context.columns?.value.forEach((_, index) => {
|
|
286
|
+
listView.setColumnWidth(index, context.columnsWidth!(index, listView.columnWidth(index), listView))
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
listView.rootIsDecorated = context.decorated
|
|
291
|
+
if (context.sorting >= 0 && context.sortOnBuild) listView.sort()
|
|
292
|
+
|
|
293
|
+
if (context.filter?.keywords.value || context.filter?.filters)
|
|
294
|
+
filterList()
|
|
295
|
+
|
|
296
|
+
if (selectedId) {
|
|
297
|
+
listView.getItems(DzListView.All).forEach(item => {
|
|
298
|
+
if (item.id === selectedId) {
|
|
299
|
+
listView.setSelected(item, true)
|
|
300
|
+
listView.setCurrentItem(item)
|
|
301
|
+
listView.ensureItemVisible(item)
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const updateList = (items: TreeNode<TItem>[]) => {
|
|
308
|
+
if (!context.text) return
|
|
309
|
+
if (!items) return
|
|
310
|
+
|
|
311
|
+
const existingByPath: Record<string, DzListViewItem> = {}
|
|
312
|
+
listView.getItems(DzListView.All).forEach((li) => {
|
|
313
|
+
const data = getDataItem<any>(li)
|
|
314
|
+
const path = data?.id ?? String(li.id)
|
|
315
|
+
existingByPath[path] = li
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
const incomingPaths: Record<string, boolean> = {}
|
|
319
|
+
items.forEach((item) => {
|
|
320
|
+
incomingPaths[item.path] = true
|
|
321
|
+
const existing = existingByPath[item.path]
|
|
322
|
+
if (existing) {
|
|
323
|
+
context.text(item).forEach((text, idx) => {
|
|
324
|
+
existing.setText(idx, text ?? '')
|
|
325
|
+
})
|
|
326
|
+
const data = context.data?.(item)
|
|
327
|
+
if (data) setDataItem(existing, data)
|
|
328
|
+
} else {
|
|
329
|
+
buildItem(item, listView)
|
|
330
|
+
}
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
listView.getItems(DzListView.All).forEach((li) => {
|
|
334
|
+
const data = getDataItem<any>(li)
|
|
335
|
+
const path = data?.id ?? String(li.id)
|
|
336
|
+
if (!incomingPaths[path]) listView.deleteItem(li)
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
listView.sort()
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const onSelectionChanged = (callback: (item: DzListViewItem, data: TData) => void) => {
|
|
343
|
+
(listView as any)["selectionChanged()"].scriptConnect(() => {
|
|
344
|
+
callback(listView.selectedItem(), getDataItem(listView.selectedItem()))
|
|
345
|
+
})
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
buildColumns(context.columns.value)
|
|
349
|
+
context.columns.connect((columns) => {
|
|
350
|
+
buildColumns(columns)
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
listView.setSorting(context.sorting, context.sortAscending)
|
|
354
|
+
buildList(context.items?.value)
|
|
355
|
+
context.items.connect((items) => {
|
|
356
|
+
updateList(items)
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
context.refreshWhen?.connect(() => {
|
|
360
|
+
if (context.refreshWhat === ListViewRefreshOptions.All)
|
|
361
|
+
buildList(context.items?.value, listView.selectedItem()?.id)
|
|
362
|
+
else {
|
|
363
|
+
filterList()
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
if (context.selected) {
|
|
369
|
+
onSelectionChanged((_, data) => {
|
|
370
|
+
context.selected.value = data
|
|
371
|
+
})
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (context.filter) {
|
|
375
|
+
context.filter.keywords.connect((keywords) => {
|
|
376
|
+
if (!delayedFilter) {
|
|
377
|
+
delayedFilter = new Delayed(() => {
|
|
378
|
+
filterList(context.filter?.keywords?.value)
|
|
379
|
+
}, context.filter.delay?.min ?? 100, context.filter.delay?.max ?? 400)
|
|
380
|
+
}
|
|
381
|
+
delayedFilter.trigger()
|
|
382
|
+
})
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (context.doubleClicked) {
|
|
386
|
+
listView.doubleClicked.scriptConnect((listItem) => {
|
|
387
|
+
context.doubleClicked.value = listItem?.getDataItem('data')
|
|
388
|
+
})
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
listView.contextMenuRequested.scriptConnect((item: DzListViewItem, pos: Point) => {
|
|
392
|
+
context.contextMenu?.(listView, item, pos).exec(pos.cursorPos(), 0)
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
return listView
|
|
396
|
+
}
|