Delete unused files

This commit is contained in:
Daniel Imms
2024-07-09 13:29:20 -07:00
parent 86c875f7e9
commit c33ed46161
88 changed files with 0 additions and 20344 deletions
-70
View File
@@ -1,70 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { mainWindow } from 'vs/base/browser/window';
import { getErrorMessage } from 'vs/base/common/errors';
import { Emitter } from 'vs/base/common/event';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
export class BroadcastDataChannel<T> extends Disposable {
private broadcastChannel: BroadcastChannel | undefined;
private readonly _onDidReceiveData = this._register(new Emitter<T>());
readonly onDidReceiveData = this._onDidReceiveData.event;
constructor(private readonly channelName: string) {
super();
// Use BroadcastChannel
if ('BroadcastChannel' in mainWindow) {
try {
this.broadcastChannel = new BroadcastChannel(channelName);
const listener = (event: MessageEvent) => {
this._onDidReceiveData.fire(event.data);
};
this.broadcastChannel.addEventListener('message', listener);
this._register(toDisposable(() => {
if (this.broadcastChannel) {
this.broadcastChannel.removeEventListener('message', listener);
this.broadcastChannel.close();
}
}));
} catch (error) {
console.warn('Error while creating broadcast channel. Falling back to localStorage.', getErrorMessage(error));
}
}
// BroadcastChannel is not supported. Use storage.
if (!this.broadcastChannel) {
this.channelName = `BroadcastDataChannel.${channelName}`;
this.createBroadcastChannel();
}
}
private createBroadcastChannel(): void {
const listener = (event: StorageEvent) => {
if (event.key === this.channelName && event.newValue) {
this._onDidReceiveData.fire(JSON.parse(event.newValue));
}
};
mainWindow.addEventListener('storage', listener);
this._register(toDisposable(() => mainWindow.removeEventListener('storage', listener)));
}
/**
* Sends the data to other BroadcastChannel objects set up for this channel. Data can be structured objects, e.g. nested objects and arrays.
* @param data data to broadcast
*/
postData(data: T): void {
if (this.broadcastChannel) {
this.broadcastChannel.postMessage(data);
} else {
// remove previous changes so that event is triggered even if new changes are same as old changes
localStorage.removeItem(this.channelName);
localStorage.setItem(this.channelName, JSON.stringify(data));
}
}
}
-174
View File
@@ -1,174 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes';
import { onUnexpectedError } from 'vs/base/common/errors';
import { COI } from 'vs/base/common/network';
import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
const ttPolicy = createTrustedTypesPolicy('defaultWorkerFactory', { createScriptURL: value => value });
export function createBlobWorker(blobUrl: string, options?: WorkerOptions): Worker {
if (!blobUrl.startsWith('blob:')) {
throw new URIError('Not a blob-url: ' + blobUrl);
}
return new Worker(ttPolicy ? ttPolicy.createScriptURL(blobUrl) as unknown as string : blobUrl, options);
}
function getWorker(label: string): Worker | Promise<Worker> {
// Option for hosts to overwrite the worker script (used in the standalone editor)
interface IMonacoEnvironment {
getWorker?(moduleId: string, label: string): Worker | Promise<Worker>;
getWorkerUrl?(moduleId: string, label: string): string;
}
const monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment;
if (monacoEnvironment) {
if (typeof monacoEnvironment.getWorker === 'function') {
return monacoEnvironment.getWorker('workerMain.js', label);
}
if (typeof monacoEnvironment.getWorkerUrl === 'function') {
const workerUrl = monacoEnvironment.getWorkerUrl('workerMain.js', label);
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label });
}
}
// ESM-comment-begin
if (typeof require === 'function') {
// check if the JS lives on a different origin
const workerMain = require.toUrl('vs/base/worker/workerMain.js'); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const workerUrl = getWorkerBootstrapUrl(workerMain, label);
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label });
}
// ESM-comment-end
throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);
}
// ESM-comment-begin
export function getWorkerBootstrapUrl(scriptPath: string, label: string): string {
if (/^((http:)|(https:)|(file:))/.test(scriptPath) && scriptPath.substring(0, globalThis.origin.length) !== globalThis.origin) {
// this is the cross-origin case
// i.e. the webpage is running at a different origin than where the scripts are loaded from
} else {
const start = scriptPath.lastIndexOf('?');
const end = scriptPath.lastIndexOf('#', start);
const params = start > 0
? new URLSearchParams(scriptPath.substring(start + 1, ~end ? end : undefined))
: new URLSearchParams();
COI.addSearchParam(params, true, true);
const search = params.toString();
if (!search) {
scriptPath = `${scriptPath}#${label}`;
} else {
scriptPath = `${scriptPath}?${params.toString()}#${label}`;
}
}
const factoryModuleId = 'vs/base/worker/defaultWorkerFactory.js';
const workerBaseUrl = require.toUrl(factoryModuleId).slice(0, -factoryModuleId.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const blob = new Blob([[
`/*${label}*/`,
`globalThis.MonacoEnvironment = { baseUrl: '${workerBaseUrl}' };`,
// VSCODE_GLOBALS: NLS
`globalThis._VSCODE_NLS_MESSAGES = ${JSON.stringify(globalThis._VSCODE_NLS_MESSAGES)};`,
`globalThis._VSCODE_NLS_LANGUAGE = ${JSON.stringify(globalThis._VSCODE_NLS_LANGUAGE)};`,
`const ttPolicy = globalThis.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });`,
`importScripts(ttPolicy?.createScriptURL('${scriptPath}') ?? '${scriptPath}');`,
`/*${label}*/`
].join('')], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
// ESM-comment-end
function isPromiseLike<T>(obj: any): obj is PromiseLike<T> {
if (typeof obj.then === 'function') {
return true;
}
return false;
}
/**
* A worker that uses HTML5 web workers so that is has
* its own global scope and its own thread.
*/
class WebWorker extends Disposable implements IWorker {
private readonly id: number;
private readonly label: string;
private worker: Promise<Worker> | null;
constructor(moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) {
super();
this.id = id;
this.label = label;
const workerOrPromise = getWorker(label);
if (isPromiseLike(workerOrPromise)) {
this.worker = workerOrPromise;
} else {
this.worker = Promise.resolve(workerOrPromise);
}
this.postMessage(moduleId, []);
this.worker.then((w) => {
w.onmessage = function (ev) {
onMessageCallback(ev.data);
};
w.onmessageerror = onErrorCallback;
if (typeof w.addEventListener === 'function') {
w.addEventListener('error', onErrorCallback);
}
});
this._register(toDisposable(() => {
this.worker?.then(w => {
w.onmessage = null;
w.onmessageerror = null;
w.removeEventListener('error', onErrorCallback);
w.terminate();
});
this.worker = null;
}));
}
public getId(): number {
return this.id;
}
public postMessage(message: any, transfer: Transferable[]): void {
this.worker?.then(w => {
try {
w.postMessage(message, transfer);
} catch (err) {
onUnexpectedError(err);
onUnexpectedError(new Error(`FAILED to post message to '${this.label}'-worker`, { cause: err }));
}
});
}
}
export class DefaultWorkerFactory implements IWorkerFactory {
private static LAST_WORKER_ID = 0;
private _label: string | undefined;
private _webWorkerFailedBeforeError: any;
constructor(label: string | undefined) {
this._label = label;
this._webWorkerFailedBeforeError = false;
}
public create(moduleId: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker {
const workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);
if (this._webWorkerFailedBeforeError) {
throw this._webWorkerFailedBeforeError;
}
return new WebWorker(moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {
logOnceWebWorkerWarning(err);
this._webWorkerFailedBeforeError = err;
onErrorCallback(err);
});
}
}
-108
View File
@@ -1,108 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// https://wicg.github.io/webusb/
export interface UsbDeviceData {
readonly deviceClass: number;
readonly deviceProtocol: number;
readonly deviceSubclass: number;
readonly deviceVersionMajor: number;
readonly deviceVersionMinor: number;
readonly deviceVersionSubminor: number;
readonly manufacturerName?: string;
readonly productId: number;
readonly productName?: string;
readonly serialNumber?: string;
readonly usbVersionMajor: number;
readonly usbVersionMinor: number;
readonly usbVersionSubminor: number;
readonly vendorId: number;
}
export async function requestUsbDevice(options?: { filters?: unknown[] }): Promise<UsbDeviceData | undefined> {
const usb = (navigator as any).usb;
if (!usb) {
return undefined;
}
const device = await usb.requestDevice({ filters: options?.filters ?? [] });
if (!device) {
return undefined;
}
return {
deviceClass: device.deviceClass,
deviceProtocol: device.deviceProtocol,
deviceSubclass: device.deviceSubclass,
deviceVersionMajor: device.deviceVersionMajor,
deviceVersionMinor: device.deviceVersionMinor,
deviceVersionSubminor: device.deviceVersionSubminor,
manufacturerName: device.manufacturerName,
productId: device.productId,
productName: device.productName,
serialNumber: device.serialNumber,
usbVersionMajor: device.usbVersionMajor,
usbVersionMinor: device.usbVersionMinor,
usbVersionSubminor: device.usbVersionSubminor,
vendorId: device.vendorId,
};
}
// https://wicg.github.io/serial/
export interface SerialPortData {
readonly usbVendorId?: number | undefined;
readonly usbProductId?: number | undefined;
}
export async function requestSerialPort(options?: { filters?: unknown[] }): Promise<SerialPortData | undefined> {
const serial = (navigator as any).serial;
if (!serial) {
return undefined;
}
const port = await serial.requestPort({ filters: options?.filters ?? [] });
if (!port) {
return undefined;
}
const info = port.getInfo();
return {
usbVendorId: info.usbVendorId,
usbProductId: info.usbProductId
};
}
// https://wicg.github.io/webhid/
export interface HidDeviceData {
readonly opened: boolean;
readonly vendorId: number;
readonly productId: number;
readonly productName: string;
readonly collections: [];
}
export async function requestHidDevice(options?: { filters?: unknown[] }): Promise<HidDeviceData | undefined> {
const hid = (navigator as any).hid;
if (!hid) {
return undefined;
}
const devices = await hid.requestDevice({ filters: options?.filters ?? [] });
if (!devices.length) {
return undefined;
}
const device = devices[0];
return {
opened: device.opened,
vendorId: device.vendorId,
productId: device.productId,
productName: device.productName,
collections: device.collections
};
}
-110
View File
@@ -1,110 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { addDisposableListener, getWindow } from 'vs/base/browser/dom';
import { Disposable } from 'vs/base/common/lifecycle';
import { Mimes } from 'vs/base/common/mime';
/**
* A helper that will execute a provided function when the provided HTMLElement receives
* dragover event for 800ms. If the drag is aborted before, the callback will not be triggered.
*/
export class DelayedDragHandler extends Disposable {
private timeout: any;
constructor(container: HTMLElement, callback: () => void) {
super();
this._register(addDisposableListener(container, 'dragover', e => {
e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome)
if (!this.timeout) {
this.timeout = setTimeout(() => {
callback();
this.timeout = null;
}, 800);
}
}));
['dragleave', 'drop', 'dragend'].forEach(type => {
this._register(addDisposableListener(container, type, () => {
this.clearDragTimeout();
}));
});
}
private clearDragTimeout(): void {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
}
override dispose(): void {
super.dispose();
this.clearDragTimeout();
}
}
// Common data transfers
export const DataTransfers = {
/**
* Application specific resource transfer type
*/
RESOURCES: 'ResourceURLs',
/**
* Browser specific transfer type to download
*/
DOWNLOAD_URL: 'DownloadURL',
/**
* Browser specific transfer type for files
*/
FILES: 'Files',
/**
* Typically transfer type for copy/paste transfers.
*/
TEXT: Mimes.text,
/**
* Internal type used to pass around text/uri-list data.
*
* This is needed to work around https://bugs.chromium.org/p/chromium/issues/detail?id=239745.
*/
INTERNAL_URI_LIST: 'application/vnd.code.uri-list',
};
export function applyDragImage(event: DragEvent, label: string | null, clazz: string, backgroundColor?: string | null, foregroundColor?: string | null): void {
const dragImage = document.createElement('div');
dragImage.className = clazz;
dragImage.textContent = label;
if (foregroundColor) {
dragImage.style.color = foregroundColor;
}
if (backgroundColor) {
dragImage.style.background = backgroundColor;
}
if (event.dataTransfer) {
const ownerDocument = getWindow(event).document;
ownerDocument.body.appendChild(dragImage);
event.dataTransfer.setDragImage(dragImage, -10, -10);
// Removes the element when the DND operation is done
setTimeout(() => dragImage.remove(), 0);
}
}
export interface IDragAndDropData {
update(dataTransfer: DataTransfer): void;
getData(): unknown;
}
-17
View File
@@ -1,17 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createStyleSheet2 } from 'vs/base/browser/dom';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import { autorun, IObservable } from 'vs/base/common/observable';
export function createStyleSheetFromObservable(css: IObservable<string>): IDisposable {
const store = new DisposableStore();
const w = store.add(createStyleSheet2());
store.add(autorun(reader => {
w.setStyle(css.read(reader));
}));
return store;
}
-50
View File
@@ -1,50 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { GestureEvent } from 'vs/base/browser/touch';
import { Emitter, Event as BaseEvent } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
export type EventHandler = HTMLElement | HTMLDocument | Window;
export interface IDomEvent {
<K extends keyof HTMLElementEventMap>(element: EventHandler, type: K, useCapture?: boolean): BaseEvent<HTMLElementEventMap[K]>;
(element: EventHandler, type: string, useCapture?: boolean): BaseEvent<unknown>;
}
export interface DOMEventMap extends HTMLElementEventMap, DocumentEventMap, WindowEventMap {
'-monaco-gesturetap': GestureEvent;
'-monaco-gesturechange': GestureEvent;
'-monaco-gesturestart': GestureEvent;
'-monaco-gesturesend': GestureEvent;
'-monaco-gesturecontextmenu': GestureEvent;
'compositionstart': CompositionEvent;
'compositionupdate': CompositionEvent;
'compositionend': CompositionEvent;
}
export class DomEmitter<K extends keyof DOMEventMap> implements IDisposable {
private emitter: Emitter<DOMEventMap[K]>;
get event(): BaseEvent<DOMEventMap[K]> {
return this.emitter.event;
}
constructor(element: Window & typeof globalThis, type: WindowEventMap, useCapture?: boolean);
constructor(element: Document, type: DocumentEventMap, useCapture?: boolean);
constructor(element: EventHandler, type: K, useCapture?: boolean);
constructor(element: EventHandler, type: K, useCapture?: boolean) {
const fn = (e: Event) => this.emitter.fire(e as DOMEventMap[K]);
this.emitter = new Emitter({
onWillAddFirstListener: () => element.addEventListener(type, fn, useCapture),
onDidRemoveLastListener: () => element.removeEventListener(type, fn, useCapture)
});
}
dispose(): void {
this.emitter.dispose();
}
}
-16
View File
@@ -1,16 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { isMacintosh, isWindows } from 'vs/base/common/platform';
/**
* The best font-family to be used in CSS based on the platform:
* - Windows: Segoe preferred, fallback to sans-serif
* - macOS: standard system font, fallback to sans-serif
* - Linux: standard system font preferred, fallback to Ubuntu fonts
*
* Note: this currently does not adjust for different locales.
*/
export const DEFAULT_FONT_FAMILY = isWindows ? '"Segoe WPC", "Segoe UI", sans-serif' : isMacintosh ? '-apple-system, BlinkMacSystemFont, sans-serif' : 'system-ui, "Ubuntu", "Droid Sans", sans-serif';
@@ -1,226 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { DisposableStore } from 'vs/base/common/lifecycle';
export interface IContentActionHandler {
callback: (content: string, event: IMouseEvent | IKeyboardEvent) => void;
readonly disposables: DisposableStore;
}
export interface FormattedTextRenderOptions {
readonly className?: string;
readonly inline?: boolean;
readonly actionHandler?: IContentActionHandler;
readonly renderCodeSegments?: boolean;
}
export function renderText(text: string, options: FormattedTextRenderOptions = {}): HTMLElement {
const element = createElement(options);
element.textContent = text;
return element;
}
export function renderFormattedText(formattedText: string, options: FormattedTextRenderOptions = {}): HTMLElement {
const element = createElement(options);
_renderFormattedText(element, parseFormattedText(formattedText, !!options.renderCodeSegments), options.actionHandler, options.renderCodeSegments);
return element;
}
export function createElement(options: FormattedTextRenderOptions): HTMLElement {
const tagName = options.inline ? 'span' : 'div';
const element = document.createElement(tagName);
if (options.className) {
element.className = options.className;
}
return element;
}
class StringStream {
private source: string;
private index: number;
constructor(source: string) {
this.source = source;
this.index = 0;
}
public eos(): boolean {
return this.index >= this.source.length;
}
public next(): string {
const next = this.peek();
this.advance();
return next;
}
public peek(): string {
return this.source[this.index];
}
public advance(): void {
this.index++;
}
}
const enum FormatType {
Invalid,
Root,
Text,
Bold,
Italics,
Action,
ActionClose,
Code,
NewLine
}
interface IFormatParseTree {
type: FormatType;
content?: string;
index?: number;
children?: IFormatParseTree[];
}
function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionHandler?: IContentActionHandler, renderCodeSegments?: boolean) {
let child: Node | undefined;
if (treeNode.type === FormatType.Text) {
child = document.createTextNode(treeNode.content || '');
} else if (treeNode.type === FormatType.Bold) {
child = document.createElement('b');
} else if (treeNode.type === FormatType.Italics) {
child = document.createElement('i');
} else if (treeNode.type === FormatType.Code && renderCodeSegments) {
child = document.createElement('code');
} else if (treeNode.type === FormatType.Action && actionHandler) {
const a = document.createElement('a');
actionHandler.disposables.add(DOM.addStandardDisposableListener(a, 'click', (event) => {
actionHandler.callback(String(treeNode.index), event);
}));
child = a;
} else if (treeNode.type === FormatType.NewLine) {
child = document.createElement('br');
} else if (treeNode.type === FormatType.Root) {
child = element;
}
if (child && element !== child) {
element.appendChild(child);
}
if (child && Array.isArray(treeNode.children)) {
treeNode.children.forEach((nodeChild) => {
_renderFormattedText(child, nodeChild, actionHandler, renderCodeSegments);
});
}
}
function parseFormattedText(content: string, parseCodeSegments: boolean): IFormatParseTree {
const root: IFormatParseTree = {
type: FormatType.Root,
children: []
};
let actionViewItemIndex = 0;
let current = root;
const stack: IFormatParseTree[] = [];
const stream = new StringStream(content);
while (!stream.eos()) {
let next = stream.next();
const isEscapedFormatType = (next === '\\' && formatTagType(stream.peek(), parseCodeSegments) !== FormatType.Invalid);
if (isEscapedFormatType) {
next = stream.next(); // unread the backslash if it escapes a format tag type
}
if (!isEscapedFormatType && isFormatTag(next, parseCodeSegments) && next === stream.peek()) {
stream.advance();
if (current.type === FormatType.Text) {
current = stack.pop()!;
}
const type = formatTagType(next, parseCodeSegments);
if (current.type === type || (current.type === FormatType.Action && type === FormatType.ActionClose)) {
current = stack.pop()!;
} else {
const newCurrent: IFormatParseTree = {
type: type,
children: []
};
if (type === FormatType.Action) {
newCurrent.index = actionViewItemIndex;
actionViewItemIndex++;
}
current.children!.push(newCurrent);
stack.push(current);
current = newCurrent;
}
} else if (next === '\n') {
if (current.type === FormatType.Text) {
current = stack.pop()!;
}
current.children!.push({
type: FormatType.NewLine
});
} else {
if (current.type !== FormatType.Text) {
const textCurrent: IFormatParseTree = {
type: FormatType.Text,
content: next
};
current.children!.push(textCurrent);
stack.push(current);
current = textCurrent;
} else {
current.content += next;
}
}
}
if (current.type === FormatType.Text) {
current = stack.pop()!;
}
if (stack.length) {
// incorrectly formatted string literal
}
return root;
}
function isFormatTag(char: string, supportCodeSegments: boolean): boolean {
return formatTagType(char, supportCodeSegments) !== FormatType.Invalid;
}
function formatTagType(char: string, supportCodeSegments: boolean): FormatType {
switch (char) {
case '*':
return FormatType.Bold;
case '_':
return FormatType.Italics;
case '[':
return FormatType.Action;
case ']':
return FormatType.ActionClose;
case '`':
return supportCodeSegments ? FormatType.Code : FormatType.Invalid;
default:
return FormatType.Invalid;
}
}
-32
View File
@@ -1,32 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { VSBuffer } from 'vs/base/common/buffer';
import { StringSHA1, toHexString } from 'vs/base/common/hash';
export async function sha1Hex(str: string): Promise<string> {
// Prefer to use browser's crypto module
if (globalThis?.crypto?.subtle) {
// Careful to use `dontUseNodeBuffer` when passing the
// buffer to the browser `crypto` API. Users reported
// native crashes in certain cases that we could trace
// back to passing node.js `Buffer` around
// (https://github.com/microsoft/vscode/issues/114227)
const buffer = VSBuffer.fromString(str, { dontUseNodeBuffer: true }).buffer;
const hash = await globalThis.crypto.subtle.digest({ name: 'sha-1' }, buffer);
return toHexString(hash);
}
// Otherwise fallback to `StringSHA1`
else {
const computer = new StringSHA1();
computer.update(str);
return computer.digest();
}
}
-20
View File
@@ -1,20 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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';
export interface IHistoryNavigationWidget {
readonly element: HTMLElement;
showPreviousValue(): void;
showNextValue(): void;
onDidFocus: Event<void>;
onDidBlur: Event<void>;
}
-177
View File
@@ -1,177 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ErrorNoTelemetry, getErrorMessage } from 'vs/base/common/errors';
import { mark } from 'vs/base/common/performance';
class MissingStoresError extends Error {
constructor(readonly db: IDBDatabase) {
super('Missing stores');
}
}
export class DBClosedError extends Error {
readonly code = 'DBClosed';
constructor(dbName: string) {
super(`IndexedDB database '${dbName}' is closed.`);
}
}
export class IndexedDB {
static async create(name: string, version: number | undefined, stores: string[]): Promise<IndexedDB> {
const database = await IndexedDB.openDatabase(name, version, stores);
return new IndexedDB(database, name);
}
private static async openDatabase(name: string, version: number | undefined, stores: string[]): Promise<IDBDatabase> {
mark(`code/willOpenDatabase/${name}`);
try {
return await IndexedDB.doOpenDatabase(name, version, stores);
} catch (err) {
if (err instanceof MissingStoresError) {
console.info(`Attempting to recreate the IndexedDB once.`, name);
try {
// Try to delete the db
await IndexedDB.deleteDatabase(err.db);
} catch (error) {
console.error(`Error while deleting the IndexedDB`, getErrorMessage(error));
throw error;
}
return await IndexedDB.doOpenDatabase(name, version, stores);
}
throw err;
} finally {
mark(`code/didOpenDatabase/${name}`);
}
}
private static doOpenDatabase(name: string, version: number | undefined, stores: string[]): Promise<IDBDatabase> {
return new Promise((c, e) => {
const request = indexedDB.open(name, version);
request.onerror = () => e(request.error);
request.onsuccess = () => {
const db = request.result;
for (const store of stores) {
if (!db.objectStoreNames.contains(store)) {
console.error(`Error while opening IndexedDB. Could not find '${store}'' object store`);
e(new MissingStoresError(db));
return;
}
}
c(db);
};
request.onupgradeneeded = () => {
const db = request.result;
for (const store of stores) {
if (!db.objectStoreNames.contains(store)) {
db.createObjectStore(store);
}
}
};
});
}
private static deleteDatabase(database: IDBDatabase): Promise<void> {
return new Promise((c, e) => {
// Close any opened connections
database.close();
// Delete the db
const deleteRequest = indexedDB.deleteDatabase(database.name);
deleteRequest.onerror = (err) => e(deleteRequest.error);
deleteRequest.onsuccess = () => c();
});
}
private database: IDBDatabase | null = null;
private readonly pendingTransactions: IDBTransaction[] = [];
constructor(database: IDBDatabase, private readonly name: string) {
this.database = database;
}
hasPendingTransactions(): boolean {
return this.pendingTransactions.length > 0;
}
close(): void {
if (this.pendingTransactions.length) {
this.pendingTransactions.splice(0, this.pendingTransactions.length).forEach(transaction => transaction.abort());
}
this.database?.close();
this.database = null;
}
runInTransaction<T>(store: string, transactionMode: IDBTransactionMode, dbRequestFn: (store: IDBObjectStore) => IDBRequest<T>[]): Promise<T[]>;
runInTransaction<T>(store: string, transactionMode: IDBTransactionMode, dbRequestFn: (store: IDBObjectStore) => IDBRequest<T>): Promise<T>;
async runInTransaction<T>(store: string, transactionMode: IDBTransactionMode, dbRequestFn: (store: IDBObjectStore) => IDBRequest<T> | IDBRequest<T>[]): Promise<T | T[]> {
if (!this.database) {
throw new DBClosedError(this.name);
}
const transaction = this.database.transaction(store, transactionMode);
this.pendingTransactions.push(transaction);
return new Promise<T | T[]>((c, e) => {
transaction.oncomplete = () => {
if (Array.isArray(request)) {
c(request.map(r => r.result));
} else {
c(request.result);
}
};
transaction.onerror = () => e(transaction.error ? ErrorNoTelemetry.fromError(transaction.error) : new ErrorNoTelemetry('unknown error'));
transaction.onabort = () => e(transaction.error ? ErrorNoTelemetry.fromError(transaction.error) : new ErrorNoTelemetry('unknown error'));
const request = dbRequestFn(transaction.objectStore(store));
}).finally(() => this.pendingTransactions.splice(this.pendingTransactions.indexOf(transaction), 1));
}
async getKeyValues<V>(store: string, isValid: (value: unknown) => value is V): Promise<Map<string, V>> {
if (!this.database) {
throw new DBClosedError(this.name);
}
const transaction = this.database.transaction(store, 'readonly');
this.pendingTransactions.push(transaction);
return new Promise<Map<string, V>>(resolve => {
const items = new Map<string, V>();
const objectStore = transaction.objectStore(store);
// Open a IndexedDB Cursor to iterate over key/values
const cursor = objectStore.openCursor();
if (!cursor) {
return resolve(items); // this means the `ItemTable` was empty
}
// Iterate over rows of `ItemTable` until the end
cursor.onsuccess = () => {
if (cursor.result) {
// Keep cursor key/value in our map
if (isValid(cursor.result.value)) {
items.set(cursor.result.key.toString(), cursor.result.value);
}
// Advance cursor to next row
cursor.result.continue();
} else {
resolve(items); // reached end of table
}
};
// Error handlers
const onError = (error: Error | null) => {
console.error(`IndexedDB getKeyValues(): ${toErrorMessage(error, true)}`);
resolve(items);
};
cursor.onerror = () => onError(cursor.error);
transaction.onerror = () => onError(transaction.error);
}).finally(() => this.pendingTransactions.splice(this.pendingTransactions.indexOf(transaction), 1));
}
}
-9
View File
@@ -1,9 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-aria-container {
position: absolute; /* try to hide from window but not from screen readers */
left:-999em;
}
-163
View File
@@ -1,163 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
// import 'vs/css!./aria';
// Use a max length since we are inserting the whole msg in the DOM and that can cause browsers to freeze for long messages #94233
const MAX_MESSAGE_LENGTH = 20000;
let ariaContainer: HTMLElement;
let alertContainer: HTMLElement;
let alertContainer2: HTMLElement;
let statusContainer: HTMLElement;
let statusContainer2: HTMLElement;
export function setARIAContainer(parent: HTMLElement) {
ariaContainer = document.createElement('div');
ariaContainer.className = 'monaco-aria-container';
const createAlertContainer = () => {
const element = document.createElement('div');
element.className = 'monaco-alert';
element.setAttribute('role', 'alert');
element.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(element);
return element;
};
alertContainer = createAlertContainer();
alertContainer2 = createAlertContainer();
const createStatusContainer = () => {
const element = document.createElement('div');
element.className = 'monaco-status';
element.setAttribute('aria-live', 'polite');
element.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(element);
return element;
};
statusContainer = createStatusContainer();
statusContainer2 = createStatusContainer();
parent.appendChild(ariaContainer);
}
/**
* Given the provided message, will make sure that it is read as alert to screen readers.
*/
export function alert(msg: string): void {
if (!ariaContainer) {
return;
}
// Use alternate containers such that duplicated messages get read out by screen readers #99466
if (alertContainer.textContent !== msg) {
dom.clearNode(alertContainer2);
insertMessage(alertContainer, msg);
} else {
dom.clearNode(alertContainer);
insertMessage(alertContainer2, msg);
}
}
/**
* Given the provided message, will make sure that it is read as status to screen readers.
*/
export function status(msg: string): void {
if (!ariaContainer) {
return;
}
if (statusContainer.textContent !== msg) {
dom.clearNode(statusContainer2);
insertMessage(statusContainer, msg);
} else {
dom.clearNode(statusContainer);
insertMessage(statusContainer2, msg);
}
}
function insertMessage(target: HTMLElement, msg: string): void {
dom.clearNode(target);
if (msg.length > MAX_MESSAGE_LENGTH) {
msg = msg.substr(0, MAX_MESSAGE_LENGTH);
}
target.textContent = msg;
// See https://www.paciellogroup.com/blog/2012/06/html5-accessibility-chops-aria-rolealert-browser-support/
target.style.visibility = 'hidden';
target.style.visibility = 'visible';
}
// Copied from @types/react which original came from https://www.w3.org/TR/wai-aria-1.1/#role_definitions
export type AriaRole =
| 'alert'
| 'alertdialog'
| 'application'
| 'article'
| 'banner'
| 'button'
| 'cell'
| 'checkbox'
| 'columnheader'
| 'combobox'
| 'complementary'
| 'contentinfo'
| 'definition'
| 'dialog'
| 'directory'
| 'document'
| 'feed'
| 'figure'
| 'form'
| 'grid'
| 'gridcell'
| 'group'
| 'heading'
| 'img'
| 'link'
| 'list'
| 'listbox'
| 'listitem'
| 'log'
| 'main'
| 'marquee'
| 'math'
| 'menu'
| 'menubar'
| 'menuitem'
| 'menuitemcheckbox'
| 'menuitemradio'
| 'navigation'
| 'none'
| 'note'
| 'option'
| 'presentation'
| 'progressbar'
| 'radio'
| 'radiogroup'
| 'region'
| 'row'
| 'rowgroup'
| 'rowheader'
| 'scrollbar'
| 'search'
| 'searchbox'
| 'separator'
| 'slider'
| 'spinbutton'
| 'status'
| 'switch'
| 'tab'
| 'table'
| 'tablist'
| 'tabpanel'
| 'term'
| 'textbox'
| 'timer'
| 'toolbar'
| 'tooltip'
| 'tree'
| 'treegrid'
| 'treeitem'
| (string & {}) // Prevent type collapsing to `string`
;
@@ -1,36 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-breadcrumbs {
user-select: none;
-webkit-user-select: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
outline-style: none;
}
.monaco-breadcrumbs .monaco-breadcrumb-item {
display: flex;
align-items: center;
flex: 0 1 auto;
white-space: nowrap;
cursor: pointer;
align-self: center;
height: 100%;
outline: none;
}
.monaco-breadcrumbs.disabled .monaco-breadcrumb-item {
cursor: default;
}
.monaco-breadcrumbs .monaco-breadcrumb-item .codicon-breadcrumb-separator {
color: inherit;
}
.monaco-breadcrumbs .monaco-breadcrumb-item:first-of-type::before {
content: ' ';
}
@@ -1,356 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from 'vs/base/browser/dom';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { commonPrefixLength } from 'vs/base/common/arrays';
import { ThemeIcon } from 'vs/base/common/themables';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
// import 'vs/css!./breadcrumbsWidget';
export abstract class BreadcrumbsItem {
abstract dispose(): void;
abstract equals(other: BreadcrumbsItem): boolean;
abstract render(container: HTMLElement): void;
}
export interface IBreadcrumbsWidgetStyles {
readonly breadcrumbsBackground: string | undefined;
readonly breadcrumbsForeground: string | undefined;
readonly breadcrumbsHoverForeground: string | undefined;
readonly breadcrumbsFocusForeground: string | undefined;
readonly breadcrumbsFocusAndSelectionForeground: string | undefined;
}
export interface IBreadcrumbsItemEvent {
type: 'select' | 'focus';
item: BreadcrumbsItem;
node: HTMLElement;
payload: any;
}
export class BreadcrumbsWidget {
private readonly _disposables = new DisposableStore();
private readonly _domNode: HTMLDivElement;
private readonly _scrollable: DomScrollableElement;
private readonly _onDidSelectItem = new Emitter<IBreadcrumbsItemEvent>();
private readonly _onDidFocusItem = new Emitter<IBreadcrumbsItemEvent>();
private readonly _onDidChangeFocus = new Emitter<boolean>();
readonly onDidSelectItem: Event<IBreadcrumbsItemEvent> = this._onDidSelectItem.event;
readonly onDidFocusItem: Event<IBreadcrumbsItemEvent> = this._onDidFocusItem.event;
readonly onDidChangeFocus: Event<boolean> = this._onDidChangeFocus.event;
private readonly _items = new Array<BreadcrumbsItem>();
private readonly _nodes = new Array<HTMLDivElement>();
private readonly _freeNodes = new Array<HTMLDivElement>();
private readonly _separatorIcon: ThemeIcon;
private _enabled: boolean = true;
private _focusedItemIdx: number = -1;
private _selectedItemIdx: number = -1;
private _pendingDimLayout: IDisposable | undefined;
private _pendingLayout: IDisposable | undefined;
private _dimension: dom.Dimension | undefined;
constructor(
container: HTMLElement,
horizontalScrollbarSize: number,
separatorIcon: ThemeIcon,
styles: IBreadcrumbsWidgetStyles
) {
this._domNode = document.createElement('div');
this._domNode.className = 'monaco-breadcrumbs';
this._domNode.tabIndex = 0;
this._domNode.setAttribute('role', 'list');
this._scrollable = new DomScrollableElement(this._domNode, {
vertical: ScrollbarVisibility.Hidden,
horizontal: ScrollbarVisibility.Auto,
horizontalScrollbarSize,
useShadows: false,
scrollYToX: true
});
this._separatorIcon = separatorIcon;
this._disposables.add(this._scrollable);
this._disposables.add(dom.addStandardDisposableListener(this._domNode, 'click', e => this._onClick(e)));
container.appendChild(this._scrollable.getDomNode());
const styleElement = dom.createStyleSheet(this._domNode);
this._style(styleElement, styles);
const focusTracker = dom.trackFocus(this._domNode);
this._disposables.add(focusTracker);
this._disposables.add(focusTracker.onDidBlur(_ => this._onDidChangeFocus.fire(false)));
this._disposables.add(focusTracker.onDidFocus(_ => this._onDidChangeFocus.fire(true)));
}
setHorizontalScrollbarSize(size: number) {
this._scrollable.updateOptions({
horizontalScrollbarSize: size
});
}
dispose(): void {
this._disposables.dispose();
this._pendingLayout?.dispose();
this._pendingDimLayout?.dispose();
this._onDidSelectItem.dispose();
this._onDidFocusItem.dispose();
this._onDidChangeFocus.dispose();
this._domNode.remove();
this._nodes.length = 0;
this._freeNodes.length = 0;
}
layout(dim: dom.Dimension | undefined): void {
if (dim && dom.Dimension.equals(dim, this._dimension)) {
return;
}
if (dim) {
// only measure
this._pendingDimLayout?.dispose();
this._pendingDimLayout = this._updateDimensions(dim);
} else {
this._pendingLayout?.dispose();
this._pendingLayout = this._updateScrollbar();
}
}
private _updateDimensions(dim: dom.Dimension): IDisposable {
const disposables = new DisposableStore();
disposables.add(dom.modify(dom.getWindow(this._domNode), () => {
this._dimension = dim;
this._domNode.style.width = `${dim.width}px`;
this._domNode.style.height = `${dim.height}px`;
disposables.add(this._updateScrollbar());
}));
return disposables;
}
private _updateScrollbar(): IDisposable {
return dom.measure(dom.getWindow(this._domNode), () => {
dom.measure(dom.getWindow(this._domNode), () => { // double RAF
this._scrollable.setRevealOnScroll(false);
this._scrollable.scanDomNode();
this._scrollable.setRevealOnScroll(true);
});
});
}
private _style(styleElement: HTMLStyleElement, style: IBreadcrumbsWidgetStyles): void {
let content = '';
if (style.breadcrumbsBackground) {
content += `.monaco-breadcrumbs { background-color: ${style.breadcrumbsBackground}}`;
}
if (style.breadcrumbsForeground) {
content += `.monaco-breadcrumbs .monaco-breadcrumb-item { color: ${style.breadcrumbsForeground}}\n`;
}
if (style.breadcrumbsFocusForeground) {
content += `.monaco-breadcrumbs .monaco-breadcrumb-item.focused { color: ${style.breadcrumbsFocusForeground}}\n`;
}
if (style.breadcrumbsFocusAndSelectionForeground) {
content += `.monaco-breadcrumbs .monaco-breadcrumb-item.focused.selected { color: ${style.breadcrumbsFocusAndSelectionForeground}}\n`;
}
if (style.breadcrumbsHoverForeground) {
content += `.monaco-breadcrumbs:not(.disabled ) .monaco-breadcrumb-item:hover:not(.focused):not(.selected) { color: ${style.breadcrumbsHoverForeground}}\n`;
}
styleElement.innerText = content;
}
setEnabled(value: boolean) {
this._enabled = value;
this._domNode.classList.toggle('disabled', !this._enabled);
}
domFocus(): void {
const idx = this._focusedItemIdx >= 0 ? this._focusedItemIdx : this._items.length - 1;
if (idx >= 0 && idx < this._items.length) {
this._focus(idx, undefined);
} else {
this._domNode.focus();
}
}
isDOMFocused(): boolean {
return dom.isAncestorOfActiveElement(this._domNode);
}
getFocused(): BreadcrumbsItem {
return this._items[this._focusedItemIdx];
}
setFocused(item: BreadcrumbsItem | undefined, payload?: any): void {
this._focus(this._items.indexOf(item!), payload);
}
focusPrev(payload?: any): any {
if (this._focusedItemIdx > 0) {
this._focus(this._focusedItemIdx - 1, payload);
}
}
focusNext(payload?: any): any {
if (this._focusedItemIdx + 1 < this._nodes.length) {
this._focus(this._focusedItemIdx + 1, payload);
}
}
private _focus(nth: number, payload: any): void {
this._focusedItemIdx = -1;
for (let i = 0; i < this._nodes.length; i++) {
const node = this._nodes[i];
if (i !== nth) {
node.classList.remove('focused');
} else {
this._focusedItemIdx = i;
node.classList.add('focused');
node.focus();
}
}
this._reveal(this._focusedItemIdx, true);
this._onDidFocusItem.fire({ type: 'focus', item: this._items[this._focusedItemIdx], node: this._nodes[this._focusedItemIdx], payload });
}
reveal(item: BreadcrumbsItem): void {
const idx = this._items.indexOf(item);
if (idx >= 0) {
this._reveal(idx, false);
}
}
revealLast(): void {
this._reveal(this._items.length - 1, false);
}
private _reveal(nth: number, minimal: boolean): void {
if (nth < 0 || nth >= this._nodes.length) {
return;
}
const node = this._nodes[nth];
if (!node) {
return;
}
const { width } = this._scrollable.getScrollDimensions();
const { scrollLeft } = this._scrollable.getScrollPosition();
if (!minimal || node.offsetLeft > scrollLeft + width || node.offsetLeft < scrollLeft) {
this._scrollable.setRevealOnScroll(false);
this._scrollable.setScrollPosition({ scrollLeft: node.offsetLeft });
this._scrollable.setRevealOnScroll(true);
}
}
getSelection(): BreadcrumbsItem {
return this._items[this._selectedItemIdx];
}
setSelection(item: BreadcrumbsItem | undefined, payload?: any): void {
this._select(this._items.indexOf(item!), payload);
}
private _select(nth: number, payload: any): void {
this._selectedItemIdx = -1;
for (let i = 0; i < this._nodes.length; i++) {
const node = this._nodes[i];
if (i !== nth) {
node.classList.remove('selected');
} else {
this._selectedItemIdx = i;
node.classList.add('selected');
}
}
this._onDidSelectItem.fire({ type: 'select', item: this._items[this._selectedItemIdx], node: this._nodes[this._selectedItemIdx], payload });
}
getItems(): readonly BreadcrumbsItem[] {
return this._items;
}
setItems(items: BreadcrumbsItem[]): void {
let prefix: number | undefined;
let removed: BreadcrumbsItem[] = [];
try {
prefix = commonPrefixLength(this._items, items, (a, b) => a.equals(b));
removed = this._items.splice(prefix, this._items.length - prefix, ...items.slice(prefix));
this._render(prefix);
dispose(removed);
this._focus(-1, undefined);
} catch (e) {
const newError = new Error(`BreadcrumbsItem#setItems: newItems: ${items.length}, prefix: ${prefix}, removed: ${removed.length}`);
newError.name = e.name;
newError.stack = e.stack;
throw newError;
}
}
private _render(start: number): void {
let didChange = false;
for (; start < this._items.length && start < this._nodes.length; start++) {
const item = this._items[start];
const node = this._nodes[start];
this._renderItem(item, node);
didChange = true;
}
// case a: more nodes -> remove them
while (start < this._nodes.length) {
const free = this._nodes.pop();
if (free) {
this._freeNodes.push(free);
free.remove();
didChange = true;
}
}
// case b: more items -> render them
for (; start < this._items.length; start++) {
const item = this._items[start];
const node = this._freeNodes.length > 0 ? this._freeNodes.pop() : document.createElement('div');
if (node) {
this._renderItem(item, node);
this._domNode.appendChild(node);
this._nodes.push(node);
didChange = true;
}
}
if (didChange) {
this.layout(undefined);
}
}
private _renderItem(item: BreadcrumbsItem, container: HTMLDivElement): void {
dom.clearNode(container);
container.className = '';
try {
item.render(container);
} catch (err) {
container.innerText = '<<RENDER ERROR>>';
console.error(err);
}
container.tabIndex = -1;
container.setAttribute('role', 'listitem');
container.classList.add('monaco-breadcrumb-item');
const iconContainer = dom.$(ThemeIcon.asCSSSelector(this._separatorIcon));
container.appendChild(iconContainer);
}
private _onClick(event: IMouseEvent): void {
if (!this._enabled) {
return;
}
for (let el: HTMLElement | null = event.target; el; el = el.parentElement) {
const idx = this._nodes.indexOf(el as HTMLDivElement);
if (idx >= 0) {
this._focus(idx, event);
this._select(idx, event);
break;
}
}
}
}
@@ -1,225 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { $, IDomNodePagePosition } from 'vs/base/browser/dom';
import { IView, IViewSize } from 'vs/base/browser/ui/grid/grid';
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
import { DistributeSizing, ISplitViewStyles, IView as ISplitViewView, Orientation, SplitView } from 'vs/base/browser/ui/splitview/splitview';
import { Color } from 'vs/base/common/color';
import { Event } from 'vs/base/common/event';
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
export interface CenteredViewState {
// width of the fixed centered layout
targetWidth: number;
// proportional size of left margin
leftMarginRatio: number;
// proportional size of right margin
rightMarginRatio: number;
}
const defaultState: CenteredViewState = {
targetWidth: 900,
leftMarginRatio: 0.1909,
rightMarginRatio: 0.1909,
};
const distributeSizing: DistributeSizing = { type: 'distribute' };
function createEmptyView(background: Color | undefined): ISplitViewView<{ top: number; left: number }> {
const element = $('.centered-layout-margin');
element.style.height = '100%';
if (background) {
element.style.backgroundColor = background.toString();
}
return {
element,
layout: () => undefined,
minimumSize: 60,
maximumSize: Number.POSITIVE_INFINITY,
onDidChange: Event.None
};
}
function toSplitViewView(view: IView, getHeight: () => number): ISplitViewView<{ top: number; left: number }> {
return {
element: view.element,
get maximumSize() { return view.maximumWidth; },
get minimumSize() { return view.minimumWidth; },
onDidChange: Event.map(view.onDidChange, e => e && e.width),
layout: (size, offset, ctx) => view.layout(size, getHeight(), ctx?.top ?? 0, (ctx?.left ?? 0) + offset)
};
}
export interface ICenteredViewStyles extends ISplitViewStyles {
background: Color;
}
export class CenteredViewLayout implements IDisposable {
private splitView?: SplitView<{ top: number; left: number }>;
private lastLayoutPosition: IDomNodePagePosition = { width: 0, height: 0, left: 0, top: 0 };
private style!: ICenteredViewStyles;
private didLayout = false;
private emptyViews: ISplitViewView<{ top: number; left: number }>[] | undefined;
private readonly splitViewDisposables = new DisposableStore();
constructor(
private container: HTMLElement,
private view: IView,
public state: CenteredViewState = { ...defaultState },
private centeredLayoutFixedWidth: boolean = false
) {
this.container.appendChild(this.view.element);
// Make sure to hide the split view overflow like sashes #52892
this.container.style.overflow = 'hidden';
}
get minimumWidth(): number { return this.splitView ? this.splitView.minimumSize : this.view.minimumWidth; }
get maximumWidth(): number { return this.splitView ? this.splitView.maximumSize : this.view.maximumWidth; }
get minimumHeight(): number { return this.view.minimumHeight; }
get maximumHeight(): number { return this.view.maximumHeight; }
get onDidChange(): Event<IViewSize | undefined> { return this.view.onDidChange; }
private _boundarySashes: IBoundarySashes = {};
get boundarySashes(): IBoundarySashes { return this._boundarySashes; }
set boundarySashes(boundarySashes: IBoundarySashes) {
this._boundarySashes = boundarySashes;
if (!this.splitView) {
return;
}
this.splitView.orthogonalStartSash = boundarySashes.top;
this.splitView.orthogonalEndSash = boundarySashes.bottom;
}
layout(width: number, height: number, top: number, left: number): void {
this.lastLayoutPosition = { width, height, top, left };
if (this.splitView) {
this.splitView.layout(width, this.lastLayoutPosition);
if (!this.didLayout || this.centeredLayoutFixedWidth) {
this.resizeSplitViews();
}
} else {
this.view.layout(width, height, top, left);
}
this.didLayout = true;
}
private resizeSplitViews(): void {
if (!this.splitView) {
return;
}
if (this.centeredLayoutFixedWidth) {
const centerViewWidth = Math.min(this.lastLayoutPosition.width, this.state.targetWidth);
const marginWidthFloat = (this.lastLayoutPosition.width - centerViewWidth) / 2;
this.splitView.resizeView(0, Math.floor(marginWidthFloat));
this.splitView.resizeView(1, centerViewWidth);
this.splitView.resizeView(2, Math.ceil(marginWidthFloat));
} else {
const leftMargin = this.state.leftMarginRatio * this.lastLayoutPosition.width;
const rightMargin = this.state.rightMarginRatio * this.lastLayoutPosition.width;
const center = this.lastLayoutPosition.width - leftMargin - rightMargin;
this.splitView.resizeView(0, leftMargin);
this.splitView.resizeView(1, center);
this.splitView.resizeView(2, rightMargin);
}
}
setFixedWidth(option: boolean) {
this.centeredLayoutFixedWidth = option;
if (!!this.splitView) {
this.updateState();
this.resizeSplitViews();
}
}
private updateState() {
if (!!this.splitView) {
this.state.targetWidth = this.splitView.getViewSize(1);
this.state.leftMarginRatio = this.splitView.getViewSize(0) / this.lastLayoutPosition.width;
this.state.rightMarginRatio = this.splitView.getViewSize(2) / this.lastLayoutPosition.width;
}
}
isActive(): boolean {
return !!this.splitView;
}
styles(style: ICenteredViewStyles): void {
this.style = style;
if (this.splitView && this.emptyViews) {
this.splitView.style(this.style);
this.emptyViews[0].element.style.backgroundColor = this.style.background.toString();
this.emptyViews[1].element.style.backgroundColor = this.style.background.toString();
}
}
activate(active: boolean): void {
if (active === this.isActive()) {
return;
}
if (active) {
this.view.element.remove();
this.splitView = new SplitView(this.container, {
inverseAltBehavior: true,
orientation: Orientation.HORIZONTAL,
styles: this.style
});
this.splitView.orthogonalStartSash = this.boundarySashes.top;
this.splitView.orthogonalEndSash = this.boundarySashes.bottom;
this.splitViewDisposables.add(this.splitView.onDidSashChange(() => {
if (!!this.splitView) {
this.updateState();
}
}));
this.splitViewDisposables.add(this.splitView.onDidSashReset(() => {
this.state = { ...defaultState };
this.resizeSplitViews();
}));
this.splitView.layout(this.lastLayoutPosition.width, this.lastLayoutPosition);
const backgroundColor = this.style ? this.style.background : undefined;
this.emptyViews = [createEmptyView(backgroundColor), createEmptyView(backgroundColor)];
this.splitView.addView(this.emptyViews[0], distributeSizing, 0);
this.splitView.addView(toSplitViewView(this.view, () => this.lastLayoutPosition.height), distributeSizing, 1);
this.splitView.addView(this.emptyViews[1], distributeSizing, 2);
this.resizeSplitViews();
} else {
this.splitView?.el.remove();
this.splitViewDisposables.clear();
this.splitView?.dispose();
this.splitView = undefined;
this.emptyViews = undefined;
this.container.appendChild(this.view.element);
this.view.layout(this.lastLayoutPosition.width, this.lastLayoutPosition.height, this.lastLayoutPosition.top, this.lastLayoutPosition.left);
}
}
isDefault(state: CenteredViewState): boolean {
if (this.centeredLayoutFixedWidth) {
return state.targetWidth === defaultState.targetWidth;
} else {
return state.leftMarginRatio === defaultState.leftMarginRatio
&& state.rightMarginRatio === defaultState.rightMarginRatio;
}
}
dispose(): void {
this.splitViewDisposables.dispose();
if (this.splitView) {
this.splitView.dispose();
this.splitView = undefined;
}
}
}
@@ -1,33 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.codicon-wrench-subaction {
opacity: 0.5;
}
@keyframes codicon-spin {
100% {
transform:rotate(360deg);
}
}
.codicon-sync.codicon-modifier-spin,
.codicon-loading.codicon-modifier-spin,
.codicon-gear.codicon-modifier-spin,
.codicon-notebook-state-executing.codicon-modifier-spin {
/* Use steps to throttle FPS to reduce CPU usage */
animation: codicon-spin 1.5s steps(30) infinite;
}
.codicon-modifier-disabled {
opacity: 0.4;
}
/* custom speed & easing for loading icon */
.codicon-loading,
.codicon-tree-item-loading::before {
animation-duration: 1s !important;
animation-timing-function: cubic-bezier(0.53, 0.21, 0.29, 0.67) !important;
}
@@ -1,25 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
@font-face {
font-family: "codicon";
font-display: block;
src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype");
}
.codicon[class*='codicon-'] {
font: normal normal normal 16px/1 codicon;
display: inline-block;
text-decoration: none;
text-rendering: auto;
text-align: center;
text-transform: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
user-select: none;
-webkit-user-select: none;
}
/* icon rules are dynamically created by the platform theme service (see iconsStyleSheet.ts) */
@@ -1,7 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// import 'vs/css!./codicon/codicon';
// import 'vs/css!./codicon/codicon-modifiers';
@@ -1,24 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-count-badge {
padding: 3px 6px;
border-radius: 11px;
font-size: 11px;
min-width: 18px;
min-height: 18px;
line-height: 11px;
font-weight: normal;
text-align: center;
display: inline-block;
box-sizing: border-box;
}
.monaco-count-badge.long {
padding: 2px 3px;
border-radius: 2px;
min-height: auto;
line-height: normal;
}

Some files were not shown because too many files have changed in this diff Show More