-
-
Notifications
You must be signed in to change notification settings - Fork 436
/
Copy pathlist-widget.tsx
97 lines (84 loc) · 3.34 KB
/
list-widget.tsx
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
import * as React from 'react';
import { injectable, postConstruct } from 'inversify';
import { Message } from '@phosphor/messaging';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { Emitter } from '@theia/core/lib/common/event';
import { MaybePromise } from '@theia/core/lib/common/types';
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
import { Installable } from '../../../common/protocol/installable';
import { Searchable } from '../../../common/protocol/searchable';
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
import { FilterableListContainer } from './filterable-list-container';
import { ListItemRenderer } from './list-item-renderer';
@injectable()
export abstract class ListWidget<T extends ArduinoComponent> extends ReactWidget {
/**
* Do not touch or use it. It is for setting the focus on the `input` after the widget activation.
*/
protected focusNode: HTMLElement | undefined;
protected readonly deferredContainer = new Deferred<HTMLElement>();
protected readonly filterTextChangeEmitter = new Emitter<string>();
constructor(protected options: ListWidget.Options<T>) {
super();
const { id, label, iconClass } = options;
this.id = id;
this.title.label = label;
this.title.caption = label;
this.title.iconClass = iconClass
this.title.closable = true;
this.addClass('arduino-list-widget');
this.node.tabIndex = 0; // To be able to set the focus on the widget.
this.scrollOptions = {
suppressScrollX: true
}
this.toDispose.push(this.filterTextChangeEmitter);
}
@postConstruct()
protected init(): void {
this.update();
}
protected getScrollContainer(): MaybePromise<HTMLElement> {
return this.deferredContainer.promise;
}
protected onActivateRequest(msg: Message): void {
super.onActivateRequest(msg);
(this.focusNode || this.node).focus();
}
protected onUpdateRequest(msg: Message): void {
super.onUpdateRequest(msg);
this.render();
}
protected onFocusResolved = (element: HTMLElement | undefined) => {
this.focusNode = element;
}
render(): React.ReactNode {
return <FilterableListContainer<T>
container={this}
resolveContainer={this.deferredContainer.resolve}
resolveFocus={this.onFocusResolved}
searchable={this.options.searchable}
installable={this.options.installable}
itemLabel={this.options.itemLabel}
itemRenderer={this.options.itemRenderer}
filterTextChangeEvent={this.filterTextChangeEmitter.event}/>;
}
refresh(filterText: string): void {
this.deferredContainer.promise.then(() => this.filterTextChangeEmitter.fire(filterText));
}
updateScrollBar(): void {
if (this.scrollBar) {
this.scrollBar.update();
}
}
}
export namespace ListWidget {
export interface Options<T extends ArduinoComponent> {
readonly id: string;
readonly label: string;
readonly iconClass: string;
readonly installable: Installable<T>;
readonly searchable: Searchable<T>;
readonly itemLabel: (item: T) => string;
readonly itemRenderer: ListItemRenderer<T>;
}
}