a4898c6d36f5ee4de630a4c096a7e85a09dbba87319b9834e8bae721b60ecec48cbea4c9af2dbf5a5c768e44713f01d6e58b898e604e745a08d39cfe3b8e01 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import { addDisposableListener, EventHelper, EventType, reset, trackFocus } from '../../dom.js';
  2. import { StandardKeyboardEvent } from '../../keyboardEvent.js';
  3. import { EventType as TouchEventType, Gesture } from '../../touch.js';
  4. import { renderLabelWithIcons } from '../iconLabel/iconLabels.js';
  5. import { Color } from '../../../common/color.js';
  6. import { Emitter } from '../../../common/event.js';
  7. import { Disposable } from '../../../common/lifecycle.js';
  8. import { mixin } from '../../../common/objects.js';
  9. import './button.css';
  10. const defaultOptions = {
  11. buttonBackground: Color.fromHex('#0E639C'),
  12. buttonHoverBackground: Color.fromHex('#006BB3'),
  13. buttonSeparator: Color.white,
  14. buttonForeground: Color.white
  15. };
  16. export class Button extends Disposable {
  17. constructor(container, options) {
  18. super();
  19. this._onDidClick = this._register(new Emitter());
  20. this.options = options || Object.create(null);
  21. mixin(this.options, defaultOptions, false);
  22. this.buttonForeground = this.options.buttonForeground;
  23. this.buttonBackground = this.options.buttonBackground;
  24. this.buttonHoverBackground = this.options.buttonHoverBackground;
  25. this.buttonSecondaryForeground = this.options.buttonSecondaryForeground;
  26. this.buttonSecondaryBackground = this.options.buttonSecondaryBackground;
  27. this.buttonSecondaryHoverBackground = this.options.buttonSecondaryHoverBackground;
  28. this.buttonBorder = this.options.buttonBorder;
  29. this._element = document.createElement('a');
  30. this._element.classList.add('monaco-button');
  31. this._element.tabIndex = 0;
  32. this._element.setAttribute('role', 'button');
  33. container.appendChild(this._element);
  34. this._register(Gesture.addTarget(this._element));
  35. [EventType.CLICK, TouchEventType.Tap].forEach(eventType => {
  36. this._register(addDisposableListener(this._element, eventType, e => {
  37. if (!this.enabled) {
  38. EventHelper.stop(e);
  39. return;
  40. }
  41. this._onDidClick.fire(e);
  42. }));
  43. });
  44. this._register(addDisposableListener(this._element, EventType.KEY_DOWN, e => {
  45. const event = new StandardKeyboardEvent(e);
  46. let eventHandled = false;
  47. if (this.enabled && (event.equals(3 /* KeyCode.Enter */) || event.equals(10 /* KeyCode.Space */))) {
  48. this._onDidClick.fire(e);
  49. eventHandled = true;
  50. }
  51. else if (event.equals(9 /* KeyCode.Escape */)) {
  52. this._element.blur();
  53. eventHandled = true;
  54. }
  55. if (eventHandled) {
  56. EventHelper.stop(event, true);
  57. }
  58. }));
  59. this._register(addDisposableListener(this._element, EventType.MOUSE_OVER, e => {
  60. if (!this._element.classList.contains('disabled')) {
  61. this.setHoverBackground();
  62. }
  63. }));
  64. this._register(addDisposableListener(this._element, EventType.MOUSE_OUT, e => {
  65. this.applyStyles(); // restore standard styles
  66. }));
  67. // Also set hover background when button is focused for feedback
  68. this.focusTracker = this._register(trackFocus(this._element));
  69. this._register(this.focusTracker.onDidFocus(() => { if (this.enabled) {
  70. this.setHoverBackground();
  71. } }));
  72. this._register(this.focusTracker.onDidBlur(() => { if (this.enabled) {
  73. this.applyStyles();
  74. } }));
  75. this.applyStyles();
  76. }
  77. get onDidClick() { return this._onDidClick.event; }
  78. setHoverBackground() {
  79. let hoverBackground;
  80. if (this.options.secondary) {
  81. hoverBackground = this.buttonSecondaryHoverBackground ? this.buttonSecondaryHoverBackground.toString() : null;
  82. }
  83. else {
  84. hoverBackground = this.buttonHoverBackground ? this.buttonHoverBackground.toString() : null;
  85. }
  86. if (hoverBackground) {
  87. this._element.style.backgroundColor = hoverBackground;
  88. }
  89. }
  90. style(styles) {
  91. this.buttonForeground = styles.buttonForeground;
  92. this.buttonBackground = styles.buttonBackground;
  93. this.buttonHoverBackground = styles.buttonHoverBackground;
  94. this.buttonSecondaryForeground = styles.buttonSecondaryForeground;
  95. this.buttonSecondaryBackground = styles.buttonSecondaryBackground;
  96. this.buttonSecondaryHoverBackground = styles.buttonSecondaryHoverBackground;
  97. this.buttonBorder = styles.buttonBorder;
  98. this.applyStyles();
  99. }
  100. applyStyles() {
  101. if (this._element) {
  102. let background, foreground;
  103. if (this.options.secondary) {
  104. foreground = this.buttonSecondaryForeground ? this.buttonSecondaryForeground.toString() : '';
  105. background = this.buttonSecondaryBackground ? this.buttonSecondaryBackground.toString() : '';
  106. }
  107. else {
  108. foreground = this.buttonForeground ? this.buttonForeground.toString() : '';
  109. background = this.buttonBackground ? this.buttonBackground.toString() : '';
  110. }
  111. const border = this.buttonBorder ? this.buttonBorder.toString() : '';
  112. this._element.style.color = foreground;
  113. this._element.style.backgroundColor = background;
  114. this._element.style.borderWidth = border ? '1px' : '';
  115. this._element.style.borderStyle = border ? 'solid' : '';
  116. this._element.style.borderColor = border;
  117. }
  118. }
  119. get element() {
  120. return this._element;
  121. }
  122. set label(value) {
  123. this._element.classList.add('monaco-text-button');
  124. if (this.options.supportIcons) {
  125. reset(this._element, ...renderLabelWithIcons(value));
  126. }
  127. else {
  128. this._element.textContent = value;
  129. }
  130. if (typeof this.options.title === 'string') {
  131. this._element.title = this.options.title;
  132. }
  133. else if (this.options.title) {
  134. this._element.title = value;
  135. }
  136. }
  137. set enabled(value) {
  138. if (value) {
  139. this._element.classList.remove('disabled');
  140. this._element.setAttribute('aria-disabled', String(false));
  141. this._element.tabIndex = 0;
  142. }
  143. else {
  144. this._element.classList.add('disabled');
  145. this._element.setAttribute('aria-disabled', String(true));
  146. }
  147. }
  148. get enabled() {
  149. return !this._element.classList.contains('disabled');
  150. }
  151. }