Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/browser/ui/list/list.ts
5243 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { IDragAndDropData } from '../../dnd.js';
7
import { IKeyboardEvent } from '../../keyboardEvent.js';
8
import { IMouseEvent } from '../../mouseEvent.js';
9
import { GestureEvent } from '../../touch.js';
10
import { ListViewTargetSector } from './listView.js';
11
import { IDisposable } from '../../../common/lifecycle.js';
12
13
export interface IListVirtualDelegate<T> {
14
getHeight(element: T): number;
15
getTemplateId(element: T): string;
16
hasDynamicHeight?(element: T): boolean;
17
getDynamicHeight?(element: T): number | null;
18
setDynamicHeight?(element: T, height: number): void;
19
}
20
21
export interface IListElementRenderDetails {
22
readonly height?: number;
23
readonly onScroll?: boolean;
24
}
25
26
export interface IListRenderer<T, TTemplateData> {
27
readonly templateId: string;
28
renderTemplate(container: HTMLElement): TTemplateData;
29
renderElement(element: T, index: number, templateData: TTemplateData, details?: IListElementRenderDetails): void;
30
disposeElement?(element: T, index: number, templateData: TTemplateData, details?: IListElementRenderDetails): void;
31
disposeTemplate(templateData: TTemplateData): void;
32
}
33
34
export interface IListEvent<T> {
35
readonly elements: readonly T[];
36
readonly indexes: readonly number[];
37
readonly browserEvent?: UIEvent;
38
}
39
40
export interface IListBrowserMouseEvent extends MouseEvent {
41
isHandledByList?: boolean;
42
}
43
44
export interface IListMouseEvent<T> {
45
readonly browserEvent: IListBrowserMouseEvent;
46
readonly element: T | undefined;
47
readonly index: number | undefined;
48
}
49
50
export interface IListTouchEvent<T> {
51
readonly browserEvent: TouchEvent;
52
readonly element: T | undefined;
53
readonly index: number | undefined;
54
}
55
56
export interface IListGestureEvent<T> {
57
readonly browserEvent: GestureEvent;
58
readonly element: T | undefined;
59
readonly index: number | undefined;
60
}
61
62
export interface IListDragEvent<T> {
63
readonly browserEvent: DragEvent;
64
readonly element: T | undefined;
65
readonly index: number | undefined;
66
readonly sector: ListViewTargetSector | undefined;
67
}
68
69
export interface IListContextMenuEvent<T> {
70
readonly browserEvent: UIEvent;
71
readonly element: T | undefined;
72
readonly index: number | undefined;
73
readonly anchor: HTMLElement | IMouseEvent;
74
}
75
76
export const NotSelectableGroupId = 'notSelectable';
77
export type NotSelectableGroupIdType = typeof NotSelectableGroupId;
78
79
export interface IIdentityProvider<T> {
80
getId(element: T): { toString(): string };
81
getGroupId?(element: T): number | NotSelectableGroupIdType;
82
}
83
84
export interface IKeyboardNavigationLabelProvider<T> {
85
86
/**
87
* Return a keyboard navigation label(s) which will be used by
88
* the list for filtering/navigating. Return `undefined` to make
89
* an element always match.
90
*/
91
getKeyboardNavigationLabel(element: T): { toString(): string | undefined } | { toString(): string | undefined }[] | undefined;
92
}
93
94
export interface IKeyboardNavigationDelegate {
95
mightProducePrintableCharacter(event: IKeyboardEvent): boolean;
96
}
97
98
export const enum ListDragOverEffectType {
99
Copy,
100
Move
101
}
102
103
export const enum ListDragOverEffectPosition {
104
Over = 'drop-target',
105
Before = 'drop-target-before',
106
After = 'drop-target-after'
107
}
108
109
export interface ListDragOverEffect {
110
type: ListDragOverEffectType;
111
position?: ListDragOverEffectPosition;
112
}
113
114
export interface IListDragOverReaction {
115
accept: boolean;
116
effect?: ListDragOverEffect;
117
feedback?: number[]; // use -1 for entire list
118
}
119
120
export const ListDragOverReactions = {
121
reject(): IListDragOverReaction { return { accept: false }; },
122
accept(): IListDragOverReaction { return { accept: true }; },
123
};
124
125
/**
126
* Warning: Once passed to a list, that list takes up
127
* the responsibility of disposing it.
128
*/
129
export interface IListDragAndDrop<T> extends IDisposable {
130
getDragURI(element: T): string | null;
131
getDragLabel?(elements: T[], originalEvent: DragEvent): string | undefined;
132
onDragStart?(data: IDragAndDropData, originalEvent: DragEvent): void;
133
onDragOver(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, targetSector: ListViewTargetSector | undefined, originalEvent: DragEvent): boolean | IListDragOverReaction;
134
onDragLeave?(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void;
135
drop(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, targetSector: ListViewTargetSector | undefined, originalEvent: DragEvent): void;
136
onDragEnd?(originalEvent: DragEvent): void;
137
}
138
139
export class ListError extends Error {
140
141
constructor(user: string, message: string) {
142
super(`ListError [${user}] ${message}`);
143
}
144
}
145
146
export abstract class CachedListVirtualDelegate<T extends object> implements IListVirtualDelegate<T> {
147
148
private cache = new WeakMap<T, number>();
149
150
getHeight(element: T): number {
151
return this.cache.get(element) ?? this.estimateHeight(element);
152
}
153
154
protected abstract estimateHeight(element: T): number;
155
abstract getTemplateId(element: T): string;
156
157
setDynamicHeight(element: T, height: number): void {
158
if (height > 0) {
159
this.cache.set(element, height);
160
}
161
}
162
}
163
164