UNPKG

sussudio

Version:

An unofficial VS Code Internal API

167 lines (166 loc) 5.94 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { hide, show } from "../../dom.mjs"; import { RunOnceScheduler } from "../../../common/async.mjs"; import { Disposable } from "../../../common/lifecycle.mjs"; import { isNumber } from "../../../common/types.mjs"; import "../../../../css!./progressbar.mjs"; const CSS_DONE = 'done'; const CSS_ACTIVE = 'active'; const CSS_INFINITE = 'infinite'; const CSS_INFINITE_LONG_RUNNING = 'infinite-long-running'; const CSS_DISCRETE = 'discrete'; /** * A progress bar with support for infinite or discrete progress. */ export class ProgressBar extends Disposable { /** * After a certain time of showing the progress bar, switch * to long-running mode and throttle animations to reduce * the pressure on the GPU process. * * https://github.com/microsoft/vscode/issues/97900 * https://github.com/microsoft/vscode/issues/138396 */ static LONG_RUNNING_INFINITE_THRESHOLD = 10000; workedVal; element; bit; totalWork; showDelayedScheduler; longRunningScheduler; constructor(container, options) { super(); this.workedVal = 0; this.showDelayedScheduler = this._register(new RunOnceScheduler(() => show(this.element), 0)); this.longRunningScheduler = this._register(new RunOnceScheduler(() => this.infiniteLongRunning(), ProgressBar.LONG_RUNNING_INFINITE_THRESHOLD)); this.create(container, options); } create(container, options) { this.element = document.createElement('div'); this.element.classList.add('monaco-progress-container'); this.element.setAttribute('role', 'progressbar'); this.element.setAttribute('aria-valuemin', '0'); container.appendChild(this.element); this.bit = document.createElement('div'); this.bit.classList.add('progress-bit'); this.bit.style.backgroundColor = options?.progressBarBackground || '#0E70C0'; this.element.appendChild(this.bit); } off() { this.bit.style.width = 'inherit'; this.bit.style.opacity = '1'; this.element.classList.remove(CSS_ACTIVE, CSS_INFINITE, CSS_INFINITE_LONG_RUNNING, CSS_DISCRETE); this.workedVal = 0; this.totalWork = undefined; this.longRunningScheduler.cancel(); } /** * Indicates to the progress bar that all work is done. */ done() { return this.doDone(true); } /** * Stops the progressbar from showing any progress instantly without fading out. */ stop() { return this.doDone(false); } doDone(delayed) { this.element.classList.add(CSS_DONE); // discrete: let it grow to 100% width and hide afterwards if (!this.element.classList.contains(CSS_INFINITE)) { this.bit.style.width = 'inherit'; if (delayed) { setTimeout(() => this.off(), 200); } else { this.off(); } } // infinite: let it fade out and hide afterwards else { this.bit.style.opacity = '0'; if (delayed) { setTimeout(() => this.off(), 200); } else { this.off(); } } return this; } /** * Use this mode to indicate progress that has no total number of work units. */ infinite() { this.bit.style.width = '2%'; this.bit.style.opacity = '1'; this.element.classList.remove(CSS_DISCRETE, CSS_DONE, CSS_INFINITE_LONG_RUNNING); this.element.classList.add(CSS_ACTIVE, CSS_INFINITE); this.longRunningScheduler.schedule(); return this; } infiniteLongRunning() { this.element.classList.add(CSS_INFINITE_LONG_RUNNING); } /** * Tells the progress bar the total number of work. Use in combination with workedVal() to let * the progress bar show the actual progress based on the work that is done. */ total(value) { this.workedVal = 0; this.totalWork = value; this.element.setAttribute('aria-valuemax', value.toString()); return this; } /** * Finds out if this progress bar is configured with total work */ hasTotal() { return isNumber(this.totalWork); } /** * Tells the progress bar that an increment of work has been completed. */ worked(value) { value = Math.max(1, Number(value)); return this.doSetWorked(this.workedVal + value); } /** * Tells the progress bar the total amount of work that has been completed. */ setWorked(value) { value = Math.max(1, Number(value)); return this.doSetWorked(value); } doSetWorked(value) { const totalWork = this.totalWork || 100; this.workedVal = value; this.workedVal = Math.min(totalWork, this.workedVal); this.element.classList.remove(CSS_INFINITE, CSS_INFINITE_LONG_RUNNING, CSS_DONE); this.element.classList.add(CSS_ACTIVE, CSS_DISCRETE); this.element.setAttribute('aria-valuenow', value.toString()); this.bit.style.width = 100 * (this.workedVal / (totalWork)) + '%'; return this; } getContainer() { return this.element; } show(delay) { this.showDelayedScheduler.cancel(); if (typeof delay === 'number') { this.showDelayedScheduler.schedule(delay); } else { show(this.element); } } hide() { hide(this.element); this.showDelayedScheduler.cancel(); } }