The Great Blink mv for source files, part 2.

Move and rename files.

NOAUTOREVERT=true
NOPRESUBMIT=true
NOTREECHECKS=true
Bug: 768828
[email protected]
NOTRY=true

Change-Id: I66d3b155808bc5bdbf237b80208e1e552bcf7f28
Reviewed-on: https://chromium-review.googlesource.com/1001153
Reviewed-by: Blink Reformat <[email protected]>
Commit-Queue: Blink Reformat <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#549061}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1
diff --git a/front_end/ui/SearchableView.js b/front_end/ui/SearchableView.js
new file mode 100644
index 0000000..a0fa78f
--- /dev/null
+++ b/front_end/ui/SearchableView.js
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc.  All rights reserved.
+ * Copyright (C) 2007 Matt Lilek ([email protected]).
+ * Copyright (C) 2009 Joseph Pecoraro
+ * Copyright (C) 2011 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @unrestricted
+ */
+UI.SearchableView = class extends UI.VBox {
+  /**
+   * @param {!UI.Searchable} searchable
+   * @param {string=} settingName
+   */
+  constructor(searchable, settingName) {
+    super(true);
+    this.registerRequiredCSS('ui/searchableView.css');
+    this.element[UI.SearchableView._symbol] = this;
+
+    this._searchProvider = searchable;
+    this._setting = settingName ? Common.settings.createSetting(settingName, {}) : null;
+    this._replaceable = false;
+
+    this.contentElement.createChild('content');
+    this._footerElementContainer = this.contentElement.createChild('div', 'search-bar hidden');
+    this._footerElementContainer.style.order = 100;
+    this._footerElement = this._footerElementContainer.createChild('div', 'toolbar-search');
+
+    const replaceToggleToolbar = new UI.Toolbar('replace-toggle-toolbar', this._footerElement);
+    this._replaceToggleButton = new UI.ToolbarToggle(Common.UIString('Replace'), 'mediumicon-replace');
+    this._replaceToggleButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleReplace, this);
+    replaceToggleToolbar.appendToolbarItem(this._replaceToggleButton);
+
+    const searchInputElements = this._footerElement.createChild('div', 'toolbar-search-inputs');
+    const searchControlElement = searchInputElements.createChild('div', 'toolbar-search-control');
+
+    this._searchInputElement = UI.HistoryInput.create();
+    this._searchInputElement.classList.add('search-replace');
+    this._searchInputElement.id = 'search-input-field';
+    this._searchInputElement.placeholder = Common.UIString('Find');
+    searchControlElement.appendChild(this._searchInputElement);
+
+    this._matchesElement = searchControlElement.createChild('label', 'search-results-matches');
+    this._matchesElement.setAttribute('for', 'search-input-field');
+
+    const searchNavigationElement = searchControlElement.createChild('div', 'toolbar-search-navigation-controls');
+
+    this._searchNavigationPrevElement =
+        searchNavigationElement.createChild('div', 'toolbar-search-navigation toolbar-search-navigation-prev');
+    this._searchNavigationPrevElement.addEventListener('click', this._onPrevButtonSearch.bind(this), false);
+    this._searchNavigationPrevElement.title = Common.UIString('Search previous');
+
+    this._searchNavigationNextElement =
+        searchNavigationElement.createChild('div', 'toolbar-search-navigation toolbar-search-navigation-next');
+    this._searchNavigationNextElement.addEventListener('click', this._onNextButtonSearch.bind(this), false);
+    this._searchNavigationNextElement.title = Common.UIString('Search next');
+
+    this._searchInputElement.addEventListener('keydown', this._onSearchKeyDown.bind(this), true);
+    this._searchInputElement.addEventListener('input', this._onInput.bind(this), false);
+
+    this._replaceInputElement =
+        searchInputElements.createChild('input', 'search-replace toolbar-replace-control hidden');
+    this._replaceInputElement.addEventListener('keydown', this._onReplaceKeyDown.bind(this), true);
+    this._replaceInputElement.placeholder = Common.UIString('Replace');
+
+    this._buttonsContainer = this._footerElement.createChild('div', 'toolbar-search-buttons');
+    const firstRowButtons = this._buttonsContainer.createChild('div', 'first-row-buttons');
+
+    const toolbar = new UI.Toolbar('toolbar-search-options', firstRowButtons);
+
+    if (this._searchProvider.supportsCaseSensitiveSearch()) {
+      this._caseSensitiveButton = new UI.ToolbarToggle(Common.UIString('Match Case'));
+      this._caseSensitiveButton.setText('Aa');
+      this._caseSensitiveButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleCaseSensitiveSearch, this);
+      toolbar.appendToolbarItem(this._caseSensitiveButton);
+    }
+
+    if (this._searchProvider.supportsRegexSearch()) {
+      this._regexButton = new UI.ToolbarToggle(Common.UIString('Use Regular Expression'));
+      this._regexButton.setText('.*');
+      this._regexButton.addEventListener(UI.ToolbarButton.Events.Click, this._toggleRegexSearch, this);
+      toolbar.appendToolbarItem(this._regexButton);
+    }
+
+    const cancelButtonElement =
+        UI.createTextButton(Common.UIString('Cancel'), this.closeSearch.bind(this), 'search-action-button');
+    firstRowButtons.appendChild(cancelButtonElement);
+
+    this._secondRowButtons = this._buttonsContainer.createChild('div', 'second-row-buttons hidden');
+
+    this._replaceButtonElement =
+        UI.createTextButton(Common.UIString('Replace'), this._replace.bind(this), 'search-action-button');
+    this._replaceButtonElement.disabled = true;
+    this._secondRowButtons.appendChild(this._replaceButtonElement);
+
+    this._replaceAllButtonElement =
+        UI.createTextButton(Common.UIString('Replace all'), this._replaceAll.bind(this), 'search-action-button');
+    this._secondRowButtons.appendChild(this._replaceAllButtonElement);
+    this._replaceAllButtonElement.disabled = true;
+
+    this._minimalSearchQuerySize = 3;
+    this._loadSetting();
+  }
+
+  /**
+   * @param {?Element} element
+   * @return {?UI.SearchableView}
+   */
+  static fromElement(element) {
+    let view = null;
+    while (element && !view) {
+      view = element[UI.SearchableView._symbol];
+      element = element.parentElementOrShadowHost();
+    }
+    return view;
+  }
+
+  _toggleCaseSensitiveSearch() {
+    this._caseSensitiveButton.setToggled(!this._caseSensitiveButton.toggled());
+    this._saveSetting();
+    this._performSearch(false, true);
+  }
+
+  _toggleRegexSearch() {
+    this._regexButton.setToggled(!this._regexButton.toggled());
+    this._saveSetting();
+    this._performSearch(false, true);
+  }
+
+  _toggleReplace() {
+    this._replaceToggleButton.setToggled(!this._replaceToggleButton.toggled());
+    this._updateSecondRowVisibility();
+  }
+
+  _saveSetting() {
+    if (!this._setting)
+      return;
+    const settingValue = this._setting.get() || {};
+    settingValue.caseSensitive = this._caseSensitiveButton.toggled();
+    settingValue.isRegex = this._regexButton.toggled();
+    this._setting.set(settingValue);
+  }
+
+  _loadSetting() {
+    const settingValue = this._setting ? (this._setting.get() || {}) : {};
+    if (this._searchProvider.supportsCaseSensitiveSearch())
+      this._caseSensitiveButton.setToggled(!!settingValue.caseSensitive);
+    if (this._searchProvider.supportsRegexSearch())
+      this._regexButton.setToggled(!!settingValue.isRegex);
+  }
+
+  /**
+   * @param {number} minimalSearchQuerySize
+   */
+  setMinimalSearchQuerySize(minimalSearchQuerySize) {
+    this._minimalSearchQuerySize = minimalSearchQuerySize;
+  }
+
+  /**
+   * @param {string} placeholder
+   */
+  setPlaceholder(placeholder) {
+    this._searchInputElement.placeholder = placeholder;
+  }
+
+  /**
+   * @param {boolean} replaceable
+   */
+  setReplaceable(replaceable) {
+    this._replaceable = replaceable;
+  }
+
+  /**
+   * @param {number} matches
+   */
+  updateSearchMatchesCount(matches) {
+    if (this._searchProvider.currentSearchMatches === matches)
+      return;
+    this._searchProvider.currentSearchMatches = matches;
+    this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentQuery ? matches : 0, -1);
+  }
+
+  /**
+   * @param {number} currentMatchIndex
+   */
+  updateCurrentMatchIndex(currentMatchIndex) {
+    this._updateSearchMatchesCountAndCurrentMatchIndex(this._searchProvider.currentSearchMatches, currentMatchIndex);
+  }
+
+  /**
+   * @return {boolean}
+   */
+  isSearchVisible() {
+    return this._searchIsVisible;
+  }
+
+  closeSearch() {
+    this.cancelSearch();
+    if (this._footerElementContainer.hasFocus())
+      this.focus();
+  }
+
+  _toggleSearchBar(toggled) {
+    this._footerElementContainer.classList.toggle('hidden', !toggled);
+    this.doResize();
+  }
+
+  cancelSearch() {
+    if (!this._searchIsVisible)
+      return;
+    this.resetSearch();
+    delete this._searchIsVisible;
+    this._toggleSearchBar(false);
+  }
+
+  resetSearch() {
+    this._clearSearch();
+    this._updateReplaceVisibility();
+    this._matchesElement.textContent = '';
+  }
+
+  refreshSearch() {
+    if (!this._searchIsVisible)
+      return;
+    this.resetSearch();
+    this._performSearch(false, false);
+  }
+
+  /**
+   * @return {boolean}
+   */
+  handleFindNextShortcut() {
+    if (!this._searchIsVisible)
+      return false;
+    this._searchProvider.jumpToNextSearchResult();
+    return true;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  handleFindPreviousShortcut() {
+    if (!this._searchIsVisible)
+      return false;
+    this._searchProvider.jumpToPreviousSearchResult();
+    return true;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  handleFindShortcut() {
+    this.showSearchField();
+    return true;
+  }
+
+  /**
+   * @return {boolean}
+   */
+  handleCancelSearchShortcut() {
+    if (!this._searchIsVisible)
+      return false;
+    this.closeSearch();
+    return true;
+  }
+
+  /**
+   * @param {boolean} enabled
+   */
+  _updateSearchNavigationButtonState(enabled) {
+    this._replaceButtonElement.disabled = !enabled;
+    this._replaceAllButtonElement.disabled = !enabled;
+    this._searchNavigationPrevElement.classList.toggle('enabled', enabled);
+    this._searchNavigationNextElement.classList.toggle('enabled', enabled);
+  }
+
+  /**
+   * @param {number} matches
+   * @param {number} currentMatchIndex
+   */
+  _updateSearchMatchesCountAndCurrentMatchIndex(matches, currentMatchIndex) {
+    if (!this._currentQuery)
+      this._matchesElement.textContent = '';
+    else if (matches === 0 || currentMatchIndex >= 0)
+      this._matchesElement.textContent = Common.UIString('%d of %d', currentMatchIndex + 1, matches);
+    else if (matches === 1)
+      this._matchesElement.textContent = Common.UIString('1 match');
+    else
+      this._matchesElement.textContent = Common.UIString('%d matches', matches);
+    this._updateSearchNavigationButtonState(matches > 0);
+  }
+
+  showSearchField() {
+    if (this._searchIsVisible)
+      this.cancelSearch();
+
+    let queryCandidate;
+    if (!this._searchInputElement.hasFocus()) {
+      const selection = UI.inspectorView.element.window().getSelection();
+      if (selection.rangeCount)
+        queryCandidate = selection.toString().replace(/\r?\n.*/, '');
+    }
+
+    this._toggleSearchBar(true);
+    this._updateReplaceVisibility();
+    if (queryCandidate)
+      this._searchInputElement.value = queryCandidate;
+    this._performSearch(false, false);
+    this._searchInputElement.focus();
+    this._searchInputElement.select();
+    this._searchIsVisible = true;
+  }
+
+  _updateReplaceVisibility() {
+    this._replaceToggleButton.setVisible(this._replaceable);
+    if (!this._replaceable) {
+      this._replaceToggleButton.setToggled(false);
+      this._updateSecondRowVisibility();
+    }
+  }
+
+  /**
+   * @param {!Event} event
+   */
+  _onSearchKeyDown(event) {
+    if (isEscKey(event)) {
+      this.closeSearch();
+      event.consume(true);
+      return;
+    }
+    if (!isEnterKey(event))
+      return;
+
+    if (!this._currentQuery)
+      this._performSearch(true, true, event.shiftKey);
+    else
+      this._jumpToNextSearchResult(event.shiftKey);
+  }
+
+  /**
+   * @param {!Event} event
+   */
+  _onReplaceKeyDown(event) {
+    if (isEnterKey(event))
+      this._replace();
+  }
+
+  /**
+   * @param {boolean=} isBackwardSearch
+   */
+  _jumpToNextSearchResult(isBackwardSearch) {
+    if (!this._currentQuery || !this._searchNavigationPrevElement.classList.contains('enabled'))
+      return;
+
+    if (isBackwardSearch)
+      this._searchProvider.jumpToPreviousSearchResult();
+    else
+      this._searchProvider.jumpToNextSearchResult();
+  }
+
+  _onNextButtonSearch(event) {
+    if (!this._searchNavigationNextElement.classList.contains('enabled'))
+      return;
+    this._jumpToNextSearchResult();
+    this._searchInputElement.focus();
+  }
+
+  _onPrevButtonSearch(event) {
+    if (!this._searchNavigationPrevElement.classList.contains('enabled'))
+      return;
+    this._jumpToNextSearchResult(true);
+    this._searchInputElement.focus();
+  }
+
+  _onFindClick(event) {
+    if (!this._currentQuery)
+      this._performSearch(true, true);
+    else
+      this._jumpToNextSearchResult();
+    this._searchInputElement.focus();
+  }
+
+  _onPreviousClick(event) {
+    if (!this._currentQuery)
+      this._performSearch(true, true, true);
+    else
+      this._jumpToNextSearchResult(true);
+    this._searchInputElement.focus();
+  }
+
+  _clearSearch() {
+    delete this._currentQuery;
+    if (!!this._searchProvider.currentQuery) {
+      delete this._searchProvider.currentQuery;
+      this._searchProvider.searchCanceled();
+    }
+    this._updateSearchMatchesCountAndCurrentMatchIndex(0, -1);
+  }
+
+  /**
+   * @param {boolean} forceSearch
+   * @param {boolean} shouldJump
+   * @param {boolean=} jumpBackwards
+   */
+  _performSearch(forceSearch, shouldJump, jumpBackwards) {
+    const query = this._searchInputElement.value;
+    if (!query || (!forceSearch && query.length < this._minimalSearchQuerySize && !this._currentQuery)) {
+      this._clearSearch();
+      return;
+    }
+
+    this._currentQuery = query;
+    this._searchProvider.currentQuery = query;
+
+    const searchConfig = this._currentSearchConfig();
+    this._searchProvider.performSearch(searchConfig, shouldJump, jumpBackwards);
+  }
+
+  /**
+   * @return {!UI.SearchableView.SearchConfig}
+   */
+  _currentSearchConfig() {
+    const query = this._searchInputElement.value;
+    const caseSensitive = this._caseSensitiveButton ? this._caseSensitiveButton.toggled() : false;
+    const isRegex = this._regexButton ? this._regexButton.toggled() : false;
+    return new UI.SearchableView.SearchConfig(query, caseSensitive, isRegex);
+  }
+
+  _updateSecondRowVisibility() {
+    const secondRowVisible = this._replaceToggleButton.toggled();
+    this._footerElementContainer.classList.toggle('replaceable', secondRowVisible);
+    this._secondRowButtons.classList.toggle('hidden', !secondRowVisible);
+    this._replaceInputElement.classList.toggle('hidden', !secondRowVisible);
+
+    if (secondRowVisible)
+      this._replaceInputElement.focus();
+    else
+      this._searchInputElement.focus();
+    this.doResize();
+  }
+
+  _replace() {
+    const searchConfig = this._currentSearchConfig();
+    /** @type {!UI.Replaceable} */ (this._searchProvider)
+        .replaceSelectionWith(searchConfig, this._replaceInputElement.value);
+    delete this._currentQuery;
+    this._performSearch(true, true);
+  }
+
+  _replaceAll() {
+    const searchConfig = this._currentSearchConfig();
+    /** @type {!UI.Replaceable} */ (this._searchProvider).replaceAllWith(searchConfig, this._replaceInputElement.value);
+  }
+
+  /**
+   * @param {!Event} event
+   */
+  _onInput(event) {
+    if (this._valueChangedTimeoutId)
+      clearTimeout(this._valueChangedTimeoutId);
+    const timeout = this._searchInputElement.value.length < 3 ? 200 : 0;
+    this._valueChangedTimeoutId = setTimeout(this._onValueChanged.bind(this), timeout);
+  }
+
+  _onValueChanged() {
+    if (!this._searchIsVisible)
+      return;
+    delete this._valueChangedTimeoutId;
+    this._performSearch(false, true);
+  }
+};
+
+
+UI.SearchableView._symbol = Symbol('searchableView');
+
+
+/**
+ * @interface
+ */
+UI.Searchable = function() {};
+
+UI.Searchable.prototype = {
+  searchCanceled() {},
+
+  /**
+   * @param {!UI.SearchableView.SearchConfig} searchConfig
+   * @param {boolean} shouldJump
+   * @param {boolean=} jumpBackwards
+   */
+  performSearch(searchConfig, shouldJump, jumpBackwards) {},
+
+  jumpToNextSearchResult() {},
+
+  jumpToPreviousSearchResult() {},
+
+  /**
+   * @return {boolean}
+   */
+  supportsCaseSensitiveSearch() {},
+
+  /**
+   * @return {boolean}
+   */
+  supportsRegexSearch() {}
+};
+
+/**
+ * @interface
+ */
+UI.Replaceable = function() {};
+
+UI.Replaceable.prototype = {
+  /**
+   * @param {!UI.SearchableView.SearchConfig} searchConfig
+   * @param {string} replacement
+   */
+  replaceSelectionWith(searchConfig, replacement) {},
+
+  /**
+   * @param {!UI.SearchableView.SearchConfig} searchConfig
+   * @param {string} replacement
+   */
+  replaceAllWith(searchConfig, replacement) {}
+};
+
+/**
+ * @unrestricted
+ */
+UI.SearchableView.SearchConfig = class {
+  /**
+   * @param {string} query
+   * @param {boolean} caseSensitive
+   * @param {boolean} isRegex
+   */
+  constructor(query, caseSensitive, isRegex) {
+    this.query = query;
+    this.caseSensitive = caseSensitive;
+    this.isRegex = isRegex;
+  }
+
+  /**
+   * @param {boolean=} global
+   * @return {!RegExp}
+   */
+  toSearchRegex(global) {
+    let modifiers = this.caseSensitive ? '' : 'i';
+    if (global)
+      modifiers += 'g';
+    const query = this.isRegex ? '/' + this.query + '/' : this.query;
+
+    let regex;
+
+    // First try creating regex if user knows the / / hint.
+    try {
+      if (/^\/.+\/$/.test(query)) {
+        regex = new RegExp(query.substring(1, query.length - 1), modifiers);
+        regex.__fromRegExpQuery = true;
+      }
+    } catch (e) {
+      // Silent catch.
+    }
+
+    // Otherwise just do a plain text search.
+    if (!regex)
+      regex = createPlainTextSearchRegex(query, modifiers);
+
+    return regex;
+  }
+};