Browse Source

Break SearchInstance into its own file

Andrew Schlaepfer 6 years ago
parent
commit
d5ac6fb668

+ 3 - 142
packages/documentsearch-extension/src/index.ts

@@ -5,11 +5,11 @@ import '../style/index.css';
 import { SearchProviderRegistry } from './searchproviderregistry';
 
 import { JupyterLab, JupyterLabPlugin } from '@jupyterlab/application';
-import { ICommandPalette, MainAreaWidget } from '@jupyterlab/apputils';
+import { ICommandPalette } from '@jupyterlab/apputils';
 
-import { ISignal, Signal } from '@phosphor/signaling';
-import { createSearchOverlay } from './searchoverlay';
+import { ISignal } from '@phosphor/signaling';
 import { Widget } from '@phosphor/widgets';
+import { SearchInstance } from './searchinstance';
 
 export interface ISearchMatch {
   /**
@@ -204,145 +204,6 @@ const extension: JupyterLabPlugin<void> = {
   }
 };
 
-/**
- * Represents a search on a single widget.
- */
-export class SearchInstance {
-  constructor(widget: Widget, searchProvider: ISearchProvider) {
-    this._widget = widget;
-    this._activeProvider = searchProvider;
-
-    this._searchWidget = createSearchOverlay(
-      this._displayUpdateSignal,
-      this._displayState,
-      this._onCaseSensitiveToggled.bind(this),
-      this._onRegexToggled.bind(this),
-      this._highlightNext.bind(this),
-      this._highlightPrevious.bind(this),
-      this._startSearch.bind(this),
-      this._endSearch.bind(this)
-    );
-
-    // TODO: this does not update if the toolbar changes height.
-    if (this._widget instanceof MainAreaWidget) {
-      // Offset the position of the search widget to not cover the toolbar.
-      this._searchWidget.node.style.top = `${
-        this._widget.toolbar.node.clientHeight
-      }px`;
-    }
-  }
-
-  /**
-   * The search widget.
-   */
-  get searchWidget() {
-    return this._searchWidget;
-  }
-
-  /**
-   * The search provider.
-   */
-  get provider() {
-    return this._activeProvider;
-  }
-
-  /**
-   * Focus the search widget input.
-   */
-  focus(): void {
-    this._displayState.forceFocus = true;
-
-    // Trigger a rerender without resetting the forceFocus.
-    this._displayUpdateSignal.emit(this._displayState);
-  }
-
-  /**
-   * Updates the match index and total display in the search widget.
-   */
-  updateIndices(): void {
-    this._displayState.totalMatches = this._activeProvider.matches.length;
-    this._displayState.currentIndex = this._activeProvider.currentMatchIndex;
-    this._updateDisplay();
-  }
-
-  private _updateDisplay() {
-    // Reset the focus attribute to make sure we don't steal focus.
-    this._displayState.forceFocus = false;
-
-    // Trigger a rerender
-    this._displayUpdateSignal.emit(this._displayState);
-  }
-
-  private _startSearch(query: RegExp) {
-    // save the last query (or set it to the current query if this is the first)
-    this._displayState.query = query;
-    let cleanupPromise = Promise.resolve();
-    if (this._activeProvider) {
-      cleanupPromise = this._activeProvider.endSearch();
-    }
-    cleanupPromise.then(() =>
-      this._activeProvider.startSearch(query, this._widget).then(() => {
-        this.updateIndices();
-        // this signal should get injected when the widget is
-        // created and hooked up to react!
-        this._activeProvider.changed.connect(
-          this.updateIndices,
-          this
-        );
-      })
-    );
-  }
-
-  private _endSearch() {
-    this._activeProvider.endSearch().then(() => {
-      Signal.disconnectAll(this);
-      this._searchWidget.dispose();
-      this._activeProvider.changed.disconnect(this.updateIndices, this);
-    });
-  }
-
-  private _highlightNext() {
-    if (!this._displayState.query) {
-      return;
-    }
-    this._activeProvider.highlightNext().then(this.updateIndices.bind(this));
-  }
-
-  private _highlightPrevious() {
-    if (!this._displayState.query) {
-      return;
-    }
-    this._activeProvider
-      .highlightPrevious()
-      .then(this.updateIndices.bind(this));
-  }
-
-  private _onCaseSensitiveToggled = () => {
-    this._displayState.caseSensitive = !this._displayState.caseSensitive;
-    this._updateDisplay();
-  };
-
-  private _onRegexToggled = () => {
-    this._displayState.useRegex = !this._displayState.useRegex;
-    this._updateDisplay();
-  };
-
-  private _widget: Widget;
-  private _displayState: IDisplayState = {
-    currentIndex: 0,
-    totalMatches: 0,
-    caseSensitive: false,
-    useRegex: false,
-    inputText: '',
-    query: null,
-    errorMessage: '',
-    forceFocus: true
-  };
-  private _displayUpdateSignal = new Signal<this, IDisplayState>(this);
-  private _activeProvider: ISearchProvider;
-  private _searchWidget: Widget;
-}
-
 namespace Private {
   export type ActiveSearchMap = {
     [key: string]: SearchInstance;

+ 148 - 0
packages/documentsearch-extension/src/searchinstance.ts

@@ -0,0 +1,148 @@
+// Copyright (c) Jupyter Development Team.
+// Distributed under the terms of the Modified BSD License.
+
+import { MainAreaWidget } from '@jupyterlab/apputils';
+import { Widget } from '@phosphor/widgets';
+import { Signal } from '@phosphor/signaling';
+
+import { createSearchOverlay } from './searchoverlay';
+import { IDisplayState, ISearchProvider } from '.';
+
+/**
+ * Represents a search on a single widget.
+ */
+export class SearchInstance {
+  constructor(widget: Widget, searchProvider: ISearchProvider) {
+    this._widget = widget;
+    this._activeProvider = searchProvider;
+
+    this._searchWidget = createSearchOverlay(
+      this._displayUpdateSignal,
+      this._displayState,
+      this._onCaseSensitiveToggled.bind(this),
+      this._onRegexToggled.bind(this),
+      this._highlightNext.bind(this),
+      this._highlightPrevious.bind(this),
+      this._startSearch.bind(this),
+      this._endSearch.bind(this)
+    );
+
+    // TODO: this does not update if the toolbar changes height.
+    if (this._widget instanceof MainAreaWidget) {
+      // Offset the position of the search widget to not cover the toolbar.
+      this._searchWidget.node.style.top = `${
+        this._widget.toolbar.node.clientHeight
+      }px`;
+    }
+  }
+
+  /**
+   * The search widget.
+   */
+  get searchWidget() {
+    return this._searchWidget;
+  }
+
+  /**
+   * The search provider.
+   */
+  get provider() {
+    return this._activeProvider;
+  }
+
+  /**
+   * Focus the search widget input.
+   */
+  focus(): void {
+    this._displayState.forceFocus = true;
+
+    // Trigger a rerender without resetting the forceFocus.
+    this._displayUpdateSignal.emit(this._displayState);
+  }
+
+  /**
+   * Updates the match index and total display in the search widget.
+   */
+  updateIndices(): void {
+    this._displayState.totalMatches = this._activeProvider.matches.length;
+    this._displayState.currentIndex = this._activeProvider.currentMatchIndex;
+    this._updateDisplay();
+  }
+
+  private _updateDisplay() {
+    // Reset the focus attribute to make sure we don't steal focus.
+    this._displayState.forceFocus = false;
+
+    // Trigger a rerender
+    this._displayUpdateSignal.emit(this._displayState);
+  }
+
+  private _startSearch(query: RegExp) {
+    // save the last query (or set it to the current query if this is the first)
+    this._displayState.query = query;
+    let cleanupPromise = Promise.resolve();
+    if (this._activeProvider) {
+      cleanupPromise = this._activeProvider.endSearch();
+    }
+    cleanupPromise.then(() =>
+      this._activeProvider.startSearch(query, this._widget).then(() => {
+        this.updateIndices();
+        // this signal should get injected when the widget is
+        // created and hooked up to react!
+        this._activeProvider.changed.connect(
+          this.updateIndices,
+          this
+        );
+      })
+    );
+  }
+
+  private _endSearch() {
+    this._activeProvider.endSearch().then(() => {
+      Signal.disconnectAll(this);
+      this._searchWidget.dispose();
+      this._activeProvider.changed.disconnect(this.updateIndices, this);
+    });
+  }
+
+  private _highlightNext() {
+    if (!this._displayState.query) {
+      return;
+    }
+    this._activeProvider.highlightNext().then(this.updateIndices.bind(this));
+  }
+
+  private _highlightPrevious() {
+    if (!this._displayState.query) {
+      return;
+    }
+    this._activeProvider
+      .highlightPrevious()
+      .then(this.updateIndices.bind(this));
+  }
+
+  private _onCaseSensitiveToggled = () => {
+    this._displayState.caseSensitive = !this._displayState.caseSensitive;
+    this._updateDisplay();
+  };
+
+  private _onRegexToggled = () => {
+    this._displayState.useRegex = !this._displayState.useRegex;
+    this._updateDisplay();
+  };
+
+  private _widget: Widget;
+  private _displayState: IDisplayState = {
+    currentIndex: 0,
+    totalMatches: 0,
+    caseSensitive: false,
+    useRegex: false,
+    inputText: '',
+    query: null,
+    errorMessage: '',
+    forceFocus: true
+  };
+  private _displayUpdateSignal = new Signal<this, IDisplayState>(this);
+  private _activeProvider: ISearchProvider;
+  private _searchWidget: Widget;
+}

+ 2 - 1
packages/documentsearch-extension/src/searchoverlay.tsx

@@ -6,7 +6,8 @@ import '../style/index.css';
 import { ReactWidget, UseSignal } from '@jupyterlab/apputils';
 import { Signal } from '@phosphor/signaling';
 import { Widget } from '@phosphor/widgets';
-import { IDisplayState, SearchInstance } from '.';
+import { IDisplayState } from '.';
+import { SearchInstance } from './searchinstance';
 
 const OVERLAY_CLASS = 'jp-DocumentSearch-overlay';
 const INPUT_CLASS = 'jp-DocumentSearch-input';