bf153c435812c155c4817fa52b122ec2c50227aebb689eaa1e9217c708a7a34a158ae3bf3029b01bc9d5b35847c8917192163d975a06538ee9d72868edc365 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  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. import { show } from '../../dom.js';
  6. import { RunOnceScheduler } from '../../../common/async.js';
  7. import { Color } from '../../../common/color.js';
  8. import { Disposable } from '../../../common/lifecycle.js';
  9. import { mixin } from '../../../common/objects.js';
  10. import './progressbar.css';
  11. const CSS_DONE = 'done';
  12. const CSS_ACTIVE = 'active';
  13. const CSS_INFINITE = 'infinite';
  14. const CSS_INFINITE_LONG_RUNNING = 'infinite-long-running';
  15. const CSS_DISCRETE = 'discrete';
  16. const defaultOpts = {
  17. progressBarBackground: Color.fromHex('#0E70C0')
  18. };
  19. /**
  20. * A progress bar with support for infinite or discrete progress.
  21. */
  22. export class ProgressBar extends Disposable {
  23. constructor(container, options) {
  24. super();
  25. this.options = options || Object.create(null);
  26. mixin(this.options, defaultOpts, false);
  27. this.workedVal = 0;
  28. this.progressBarBackground = this.options.progressBarBackground;
  29. this.showDelayedScheduler = this._register(new RunOnceScheduler(() => show(this.element), 0));
  30. this.longRunningScheduler = this._register(new RunOnceScheduler(() => this.infiniteLongRunning(), ProgressBar.LONG_RUNNING_INFINITE_THRESHOLD));
  31. this.create(container);
  32. }
  33. create(container) {
  34. this.element = document.createElement('div');
  35. this.element.classList.add('monaco-progress-container');
  36. this.element.setAttribute('role', 'progressbar');
  37. this.element.setAttribute('aria-valuemin', '0');
  38. container.appendChild(this.element);
  39. this.bit = document.createElement('div');
  40. this.bit.classList.add('progress-bit');
  41. this.element.appendChild(this.bit);
  42. this.applyStyles();
  43. }
  44. off() {
  45. this.bit.style.width = 'inherit';
  46. this.bit.style.opacity = '1';
  47. this.element.classList.remove(CSS_ACTIVE, CSS_INFINITE, CSS_INFINITE_LONG_RUNNING, CSS_DISCRETE);
  48. this.workedVal = 0;
  49. this.totalWork = undefined;
  50. this.longRunningScheduler.cancel();
  51. }
  52. /**
  53. * Stops the progressbar from showing any progress instantly without fading out.
  54. */
  55. stop() {
  56. return this.doDone(false);
  57. }
  58. doDone(delayed) {
  59. this.element.classList.add(CSS_DONE);
  60. // discrete: let it grow to 100% width and hide afterwards
  61. if (!this.element.classList.contains(CSS_INFINITE)) {
  62. this.bit.style.width = 'inherit';
  63. if (delayed) {
  64. setTimeout(() => this.off(), 200);
  65. }
  66. else {
  67. this.off();
  68. }
  69. }
  70. // infinite: let it fade out and hide afterwards
  71. else {
  72. this.bit.style.opacity = '0';
  73. if (delayed) {
  74. setTimeout(() => this.off(), 200);
  75. }
  76. else {
  77. this.off();
  78. }
  79. }
  80. return this;
  81. }
  82. /**
  83. * Use this mode to indicate progress that has no total number of work units.
  84. */
  85. infinite() {
  86. this.bit.style.width = '2%';
  87. this.bit.style.opacity = '1';
  88. this.element.classList.remove(CSS_DISCRETE, CSS_DONE, CSS_INFINITE_LONG_RUNNING);
  89. this.element.classList.add(CSS_ACTIVE, CSS_INFINITE);
  90. this.longRunningScheduler.schedule();
  91. return this;
  92. }
  93. infiniteLongRunning() {
  94. this.element.classList.add(CSS_INFINITE_LONG_RUNNING);
  95. }
  96. getContainer() {
  97. return this.element;
  98. }
  99. style(styles) {
  100. this.progressBarBackground = styles.progressBarBackground;
  101. this.applyStyles();
  102. }
  103. applyStyles() {
  104. if (this.bit) {
  105. const background = this.progressBarBackground ? this.progressBarBackground.toString() : '';
  106. this.bit.style.backgroundColor = background;
  107. }
  108. }
  109. }
  110. /**
  111. * After a certain time of showing the progress bar, switch
  112. * to long-running mode and throttle animations to reduce
  113. * the pressure on the GPU process.
  114. *
  115. * https://github.com/microsoft/vscode/issues/97900
  116. * https://github.com/microsoft/vscode/issues/138396
  117. */
  118. ProgressBar.LONG_RUNNING_INFINITE_THRESHOLD = 10000;