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
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
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
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
|
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { Codicon } from 'vs/base/common/codicons';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { basename } from 'vs/base/common/resources';
import Severity from 'vs/base/common/severity';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
export interface FileFilter {
readonly extensions: string[];
readonly name: string;
}
export type DialogType = 'none' | 'info' | 'error' | 'question' | 'warning';
export interface ICheckbox {
readonly label: string;
readonly checked?: boolean;
}
export interface IConfirmDialogArgs {
readonly confirmation: IConfirmation;
}
export interface IShowDialogArgs {
readonly severity: Severity;
readonly message: string;
readonly buttons?: string[];
readonly options?: IDialogOptions;
}
export interface IInputDialogArgs extends IShowDialogArgs {
readonly buttons: string[];
readonly inputs: IInput[];
}
export interface IDialog {
readonly confirmArgs?: IConfirmDialogArgs;
readonly showArgs?: IShowDialogArgs;
readonly inputArgs?: IInputDialogArgs;
}
export type IDialogResult = IConfirmationResult | IInputResult | IShowResult;
export interface IConfirmation {
readonly title?: string;
readonly type?: DialogType;
readonly message: string;
readonly detail?: string;
readonly primaryButton?: string;
readonly secondaryButton?: string;
readonly checkbox?: ICheckbox;
}
export interface IConfirmationResult {
/**
* Will be true if the dialog was confirmed with the primary button
* pressed.
*/
readonly confirmed: boolean;
/**
* This will only be defined if the confirmation was created
* with the checkbox option defined.
*/
readonly checkboxChecked?: boolean;
}
export interface IShowResult {
/**
* Selected choice index. If the user refused to choose,
* then a promise with index of `cancelId` option is returned. If there is no such
* option then promise with index `0` is returned.
*/
readonly choice: number;
/**
* This will only be defined if the confirmation was created
* with the checkbox option defined.
*/
readonly checkboxChecked?: boolean;
}
export interface IInputResult extends IShowResult {
/**
* Values for the input fields as provided by the user
* or `undefined` if none.
*/
readonly values?: string[];
}
export interface IPickAndOpenOptions {
forceNewWindow?: boolean;
defaultUri?: URI;
telemetryExtraData?: ITelemetryData;
availableFileSystems?: string[];
remoteAuthority?: string | null;
}
export interface ISaveDialogOptions {
/**
* A human-readable string for the dialog title
*/
title?: string;
/**
* The resource the dialog shows when opened.
*/
defaultUri?: URI;
/**
* A set of file filters that are used by the dialog. Each entry is a human readable label,
* like "TypeScript", and an array of extensions.
*/
filters?: FileFilter[];
/**
* A human-readable string for the ok button
*/
saveLabel?: string;
/**
* Specifies a list of schemas for the file systems the user can save to. If not specified, uses the schema of the defaultURI or, if also not specified,
* the schema of the current window.
*/
availableFileSystems?: readonly string[];
}
export interface IOpenDialogOptions {
/**
* A human-readable string for the dialog title
*/
title?: string;
/**
* The resource the dialog shows when opened.
*/
defaultUri?: URI;
/**
* A human-readable string for the open button.
*/
openLabel?: string;
/**
* Allow to select files, defaults to `true`.
*/
canSelectFiles?: boolean;
/**
* Allow to select folders, defaults to `false`.
*/
canSelectFolders?: boolean;
/**
* Allow to select many files or folders.
*/
canSelectMany?: boolean;
/**
* A set of file filters that are used by the dialog. Each entry is a human readable label,
* like "TypeScript", and an array of extensions.
*/
filters?: FileFilter[];
/**
* Specifies a list of schemas for the file systems the user can load from. If not specified, uses the schema of the defaultURI or, if also not available,
* the schema of the current window.
*/
availableFileSystems?: readonly string[];
}
export const IDialogService = createDecorator<IDialogService>('dialogService');
export interface ICustomDialogOptions {
readonly buttonDetails?: string[];
readonly markdownDetails?: ICustomDialogMarkdown[];
readonly classes?: string[];
readonly icon?: Codicon;
readonly disableCloseAction?: boolean;
}
export interface ICustomDialogMarkdown {
readonly markdown: IMarkdownString;
readonly classes?: string[];
}
export interface IDialogOptions {
readonly cancelId?: number;
readonly detail?: string;
readonly checkbox?: ICheckbox;
readonly custom?: boolean | ICustomDialogOptions;
}
export interface IInput {
readonly placeholder?: string;
readonly type?: 'text' | 'password';
readonly value?: string;
}
/**
* A handler to bring up modal dialogs.
*/
export interface IDialogHandler {
/**
* Ask the user for confirmation with a modal dialog.
*/
confirm(confirmation: IConfirmation): Promise<IConfirmationResult>;
/**
* Present a modal dialog to the user.
*
* @returns A promise with the selected choice index. If the user refused to choose,
* then a promise with index of `cancelId` option is returned. If there is no such
* option then promise with index `0` is returned.
*/
show(severity: Severity, message: string, buttons?: string[], options?: IDialogOptions): Promise<IShowResult>;
/**
* Present a modal dialog to the user asking for input.
*
* @returns A promise with the selected choice index. If the user refused to choose,
* then a promise with index of `cancelId` option is returned. If there is no such
* option then promise with index `0` is returned. In addition, the values for the
* inputs are returned as well.
*/
input(severity: Severity, message: string, buttons: string[], inputs: IInput[], options?: IDialogOptions): Promise<IInputResult>;
/**
* Present the about dialog to the user.
*/
about(): Promise<void>;
}
/**
* A service to bring up modal dialogs.
*
* Note: use the `INotificationService.prompt()` method for a non-modal way to ask
* the user for input.
*/
export interface IDialogService {
readonly _serviceBrand: undefined;
/**
* An event that fires when a dialog is about to show.
*/
onWillShowDialog: Event<void>;
/**
* An event that fires when a dialog did show (closed).
*/
onDidShowDialog: Event<void>;
/**
* Ask the user for confirmation with a modal dialog.
*/
confirm(confirmation: IConfirmation): Promise<IConfirmationResult>;
/**
* Present a modal dialog to the user.
*
* @param severity the severity of the message
* @param message the message to show
* @param buttons the buttons to show. By convention, the first button should be the
* primary action and the last button the "Cancel" action.
*
* @returns A promise with the selected choice index. If the user refused to choose,
* then a promise with index of `cancelId` option is returned. If there is no such
* option then promise with index `0` is returned.
*/
show(severity: Severity, message: string, buttons?: string[], options?: IDialogOptions): Promise<IShowResult>;
/**
* Present a modal dialog to the user asking for input.
*
* @returns A promise with the selected choice index. If the user refused to choose,
* then a promise with index of `cancelId` option is returned. If there is no such
* option then promise with index `0` is returned. In addition, the values for the
* inputs are returned as well.
*/
input(severity: Severity, message: string, buttons: string[], inputs: IInput[], options?: IDialogOptions): Promise<IInputResult>;
/**
* Present the about dialog to the user.
*/
about(): Promise<void>;
}
export const IFileDialogService = createDecorator<IFileDialogService>('fileDialogService');
/**
* A service to bring up file dialogs.
*/
export interface IFileDialogService {
readonly _serviceBrand: undefined;
/**
* The default path for a new file based on previously used files.
* @param schemeFilter The scheme of the file path. If no filter given, the scheme of the current window is used.
* Falls back to user home in the absence of enough information to find a better URI.
*/
defaultFilePath(schemeFilter?: string): Promise<URI>;
/**
* The default path for a new folder based on previously used folders.
* @param schemeFilter The scheme of the folder path. If no filter given, the scheme of the current window is used.
* Falls back to user home in the absence of enough information to find a better URI.
*/
defaultFolderPath(schemeFilter?: string): Promise<URI>;
/**
* The default path for a new workspace based on previously used workspaces.
* @param schemeFilter The scheme of the workspace path. If no filter given, the scheme of the current window is used.
* Falls back to user home in the absence of enough information to find a better URI.
*/
defaultWorkspacePath(schemeFilter?: string): Promise<URI>;
/**
* Shows a file-folder selection dialog and opens the selected entry.
*/
pickFileFolderAndOpen(options: IPickAndOpenOptions): Promise<void>;
/**
* Shows a file selection dialog and opens the selected entry.
*/
pickFileAndOpen(options: IPickAndOpenOptions): Promise<void>;
/**
* Shows a folder selection dialog and opens the selected entry.
*/
pickFolderAndOpen(options: IPickAndOpenOptions): Promise<void>;
/**
* Shows a workspace selection dialog and opens the selected entry.
*/
pickWorkspaceAndOpen(options: IPickAndOpenOptions): Promise<void>;
/**
* Shows a save file dialog and save the file at the chosen file URI.
*/
pickFileToSave(defaultUri: URI, availableFileSystems?: string[]): Promise<URI | undefined>;
/**
* Shows a save file dialog and returns the chosen file URI.
*/
showSaveDialog(options: ISaveDialogOptions): Promise<URI | undefined>;
/**
* Shows a confirm dialog for saving 1-N files.
*/
showSaveConfirm(fileNamesOrResources: (string | URI)[]): Promise<ConfirmResult>;
/**
* Shows a open file dialog and returns the chosen file URI.
*/
showOpenDialog(options: IOpenDialogOptions): Promise<URI[] | undefined>;
}
export const enum ConfirmResult {
SAVE,
DONT_SAVE,
CANCEL
}
const MAX_CONFIRM_FILES = 10;
export function getFileNamesMessage(fileNamesOrResources: readonly (string | URI)[]): string {
const message: string[] = [];
message.push(...fileNamesOrResources.slice(0, MAX_CONFIRM_FILES).map(fileNameOrResource => typeof fileNameOrResource === 'string' ? fileNameOrResource : basename(fileNameOrResource)));
if (fileNamesOrResources.length > MAX_CONFIRM_FILES) {
if (fileNamesOrResources.length - MAX_CONFIRM_FILES === 1) {
message.push(localize('moreFile', "...1 additional file not shown"));
} else {
message.push(localize('moreFiles', "...{0} additional files not shown", fileNamesOrResources.length - MAX_CONFIRM_FILES));
}
}
message.push('');
return message.join('\n');
}
export interface INativeOpenDialogOptions {
readonly forceNewWindow?: boolean;
readonly defaultPath?: string;
readonly telemetryEventName?: string;
readonly telemetryExtraData?: ITelemetryData;
}
|