a8c8fca4476109bdb26fc097cd76c5ce6b2e696fe7da5910827f25504f5184bb03a74540d4940954fbefa3872d3f59dc0d7efababafe26fb1bfa24a47602bb 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 * as dom from '../../dom.js';
  6. import { Toggle } from '../toggle/toggle.js';
  7. import { HistoryInputBox } from '../inputbox/inputBox.js';
  8. import { Widget } from '../widget.js';
  9. import { Codicon } from '../../../common/codicons.js';
  10. import { Emitter } from '../../../common/event.js';
  11. import './findInput.css';
  12. import * as nls from '../../../../nls.js';
  13. const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input");
  14. const NLS_PRESERVE_CASE_LABEL = nls.localize('label.preserveCaseToggle', "Preserve Case");
  15. export class PreserveCaseToggle extends Toggle {
  16. constructor(opts) {
  17. super({
  18. // TODO: does this need its own icon?
  19. icon: Codicon.preserveCase,
  20. title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,
  21. isChecked: opts.isChecked,
  22. inputActiveOptionBorder: opts.inputActiveOptionBorder,
  23. inputActiveOptionForeground: opts.inputActiveOptionForeground,
  24. inputActiveOptionBackground: opts.inputActiveOptionBackground
  25. });
  26. }
  27. }
  28. export class ReplaceInput extends Widget {
  29. constructor(parent, contextViewProvider, _showOptionButtons, options) {
  30. super();
  31. this._showOptionButtons = _showOptionButtons;
  32. this.fixFocusOnOptionClickEnabled = true;
  33. this.cachedOptionsWidth = 0;
  34. this._onDidOptionChange = this._register(new Emitter());
  35. this.onDidOptionChange = this._onDidOptionChange.event;
  36. this._onKeyDown = this._register(new Emitter());
  37. this.onKeyDown = this._onKeyDown.event;
  38. this._onMouseDown = this._register(new Emitter());
  39. this._onInput = this._register(new Emitter());
  40. this._onKeyUp = this._register(new Emitter());
  41. this._onPreserveCaseKeyDown = this._register(new Emitter());
  42. this.onPreserveCaseKeyDown = this._onPreserveCaseKeyDown.event;
  43. this.contextViewProvider = contextViewProvider;
  44. this.placeholder = options.placeholder || '';
  45. this.validation = options.validation;
  46. this.label = options.label || NLS_DEFAULT_LABEL;
  47. this.inputActiveOptionBorder = options.inputActiveOptionBorder;
  48. this.inputActiveOptionForeground = options.inputActiveOptionForeground;
  49. this.inputActiveOptionBackground = options.inputActiveOptionBackground;
  50. this.inputBackground = options.inputBackground;
  51. this.inputForeground = options.inputForeground;
  52. this.inputBorder = options.inputBorder;
  53. this.inputValidationInfoBorder = options.inputValidationInfoBorder;
  54. this.inputValidationInfoBackground = options.inputValidationInfoBackground;
  55. this.inputValidationInfoForeground = options.inputValidationInfoForeground;
  56. this.inputValidationWarningBorder = options.inputValidationWarningBorder;
  57. this.inputValidationWarningBackground = options.inputValidationWarningBackground;
  58. this.inputValidationWarningForeground = options.inputValidationWarningForeground;
  59. this.inputValidationErrorBorder = options.inputValidationErrorBorder;
  60. this.inputValidationErrorBackground = options.inputValidationErrorBackground;
  61. this.inputValidationErrorForeground = options.inputValidationErrorForeground;
  62. const appendPreserveCaseLabel = options.appendPreserveCaseLabel || '';
  63. const history = options.history || [];
  64. const flexibleHeight = !!options.flexibleHeight;
  65. const flexibleWidth = !!options.flexibleWidth;
  66. const flexibleMaxHeight = options.flexibleMaxHeight;
  67. this.domNode = document.createElement('div');
  68. this.domNode.classList.add('monaco-findInput');
  69. this.inputBox = this._register(new HistoryInputBox(this.domNode, this.contextViewProvider, {
  70. ariaLabel: this.label || '',
  71. placeholder: this.placeholder || '',
  72. validationOptions: {
  73. validation: this.validation
  74. },
  75. inputBackground: this.inputBackground,
  76. inputForeground: this.inputForeground,
  77. inputBorder: this.inputBorder,
  78. inputValidationInfoBackground: this.inputValidationInfoBackground,
  79. inputValidationInfoForeground: this.inputValidationInfoForeground,
  80. inputValidationInfoBorder: this.inputValidationInfoBorder,
  81. inputValidationWarningBackground: this.inputValidationWarningBackground,
  82. inputValidationWarningForeground: this.inputValidationWarningForeground,
  83. inputValidationWarningBorder: this.inputValidationWarningBorder,
  84. inputValidationErrorBackground: this.inputValidationErrorBackground,
  85. inputValidationErrorForeground: this.inputValidationErrorForeground,
  86. inputValidationErrorBorder: this.inputValidationErrorBorder,
  87. history,
  88. showHistoryHint: options.showHistoryHint,
  89. flexibleHeight,
  90. flexibleWidth,
  91. flexibleMaxHeight
  92. }));
  93. this.preserveCase = this._register(new PreserveCaseToggle({
  94. appendTitle: appendPreserveCaseLabel,
  95. isChecked: false,
  96. inputActiveOptionBorder: this.inputActiveOptionBorder,
  97. inputActiveOptionForeground: this.inputActiveOptionForeground,
  98. inputActiveOptionBackground: this.inputActiveOptionBackground,
  99. }));
  100. this._register(this.preserveCase.onChange(viaKeyboard => {
  101. this._onDidOptionChange.fire(viaKeyboard);
  102. if (!viaKeyboard && this.fixFocusOnOptionClickEnabled) {
  103. this.inputBox.focus();
  104. }
  105. this.validate();
  106. }));
  107. this._register(this.preserveCase.onKeyDown(e => {
  108. this._onPreserveCaseKeyDown.fire(e);
  109. }));
  110. if (this._showOptionButtons) {
  111. this.cachedOptionsWidth = this.preserveCase.width();
  112. }
  113. else {
  114. this.cachedOptionsWidth = 0;
  115. }
  116. // Arrow-Key support to navigate between options
  117. const indexes = [this.preserveCase.domNode];
  118. this.onkeydown(this.domNode, (event) => {
  119. if (event.equals(15 /* KeyCode.LeftArrow */) || event.equals(17 /* KeyCode.RightArrow */) || event.equals(9 /* KeyCode.Escape */)) {
  120. const index = indexes.indexOf(document.activeElement);
  121. if (index >= 0) {
  122. let newIndex = -1;
  123. if (event.equals(17 /* KeyCode.RightArrow */)) {
  124. newIndex = (index + 1) % indexes.length;
  125. }
  126. else if (event.equals(15 /* KeyCode.LeftArrow */)) {
  127. if (index === 0) {
  128. newIndex = indexes.length - 1;
  129. }
  130. else {
  131. newIndex = index - 1;
  132. }
  133. }
  134. if (event.equals(9 /* KeyCode.Escape */)) {
  135. indexes[index].blur();
  136. this.inputBox.focus();
  137. }
  138. else if (newIndex >= 0) {
  139. indexes[newIndex].focus();
  140. }
  141. dom.EventHelper.stop(event, true);
  142. }
  143. }
  144. });
  145. const controls = document.createElement('div');
  146. controls.className = 'controls';
  147. controls.style.display = this._showOptionButtons ? 'block' : 'none';
  148. controls.appendChild(this.preserveCase.domNode);
  149. this.domNode.appendChild(controls);
  150. parent === null || parent === void 0 ? void 0 : parent.appendChild(this.domNode);
  151. this.onkeydown(this.inputBox.inputElement, (e) => this._onKeyDown.fire(e));
  152. this.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp.fire(e));
  153. this.oninput(this.inputBox.inputElement, (e) => this._onInput.fire());
  154. this.onmousedown(this.inputBox.inputElement, (e) => this._onMouseDown.fire(e));
  155. }
  156. enable() {
  157. this.domNode.classList.remove('disabled');
  158. this.inputBox.enable();
  159. this.preserveCase.enable();
  160. }
  161. disable() {
  162. this.domNode.classList.add('disabled');
  163. this.inputBox.disable();
  164. this.preserveCase.disable();
  165. }
  166. setEnabled(enabled) {
  167. if (enabled) {
  168. this.enable();
  169. }
  170. else {
  171. this.disable();
  172. }
  173. }
  174. style(styles) {
  175. this.inputActiveOptionBorder = styles.inputActiveOptionBorder;
  176. this.inputActiveOptionForeground = styles.inputActiveOptionForeground;
  177. this.inputActiveOptionBackground = styles.inputActiveOptionBackground;
  178. this.inputBackground = styles.inputBackground;
  179. this.inputForeground = styles.inputForeground;
  180. this.inputBorder = styles.inputBorder;
  181. this.inputValidationInfoBackground = styles.inputValidationInfoBackground;
  182. this.inputValidationInfoForeground = styles.inputValidationInfoForeground;
  183. this.inputValidationInfoBorder = styles.inputValidationInfoBorder;
  184. this.inputValidationWarningBackground = styles.inputValidationWarningBackground;
  185. this.inputValidationWarningForeground = styles.inputValidationWarningForeground;
  186. this.inputValidationWarningBorder = styles.inputValidationWarningBorder;
  187. this.inputValidationErrorBackground = styles.inputValidationErrorBackground;
  188. this.inputValidationErrorForeground = styles.inputValidationErrorForeground;
  189. this.inputValidationErrorBorder = styles.inputValidationErrorBorder;
  190. this.applyStyles();
  191. }
  192. applyStyles() {
  193. if (this.domNode) {
  194. const toggleStyles = {
  195. inputActiveOptionBorder: this.inputActiveOptionBorder,
  196. inputActiveOptionForeground: this.inputActiveOptionForeground,
  197. inputActiveOptionBackground: this.inputActiveOptionBackground,
  198. };
  199. this.preserveCase.style(toggleStyles);
  200. const inputBoxStyles = {
  201. inputBackground: this.inputBackground,
  202. inputForeground: this.inputForeground,
  203. inputBorder: this.inputBorder,
  204. inputValidationInfoBackground: this.inputValidationInfoBackground,
  205. inputValidationInfoForeground: this.inputValidationInfoForeground,
  206. inputValidationInfoBorder: this.inputValidationInfoBorder,
  207. inputValidationWarningBackground: this.inputValidationWarningBackground,
  208. inputValidationWarningForeground: this.inputValidationWarningForeground,
  209. inputValidationWarningBorder: this.inputValidationWarningBorder,
  210. inputValidationErrorBackground: this.inputValidationErrorBackground,
  211. inputValidationErrorForeground: this.inputValidationErrorForeground,
  212. inputValidationErrorBorder: this.inputValidationErrorBorder
  213. };
  214. this.inputBox.style(inputBoxStyles);
  215. }
  216. }
  217. select() {
  218. this.inputBox.select();
  219. }
  220. focus() {
  221. this.inputBox.focus();
  222. }
  223. getPreserveCase() {
  224. return this.preserveCase.checked;
  225. }
  226. setPreserveCase(value) {
  227. this.preserveCase.checked = value;
  228. }
  229. focusOnPreserve() {
  230. this.preserveCase.focus();
  231. }
  232. validate() {
  233. if (this.inputBox) {
  234. this.inputBox.validate();
  235. }
  236. }
  237. set width(newWidth) {
  238. this.inputBox.paddingRight = this.cachedOptionsWidth;
  239. this.inputBox.width = newWidth;
  240. this.domNode.style.width = newWidth + 'px';
  241. }
  242. dispose() {
  243. super.dispose();
  244. }
  245. }