Browse Source

apply better searchable widget accounting when registering and deregistering search providers

Andrew Schlaepfer 6 years ago
parent
commit
2fc1cddcb5

+ 27 - 4
packages/documentsearch-extension/src/index.ts

@@ -16,6 +16,7 @@ import {
 } from '@jupyterlab/documentsearch';
 
 import { IMainMenu } from '@jupyterlab/mainmenu';
+import { Widget } from '@phosphor/widgets';
 
 const SEARCHABLE_CLASS = 'jp-mod-searchable';
 
@@ -28,15 +29,37 @@ const labShellWidgetListener: JupyterFrontEndPlugin<void> = {
     labShell: ILabShell,
     registry: ISearchProviderRegistry
   ) => {
+    // If a given widget is searchable, apply the searchable class.
+    // If it's not searchable, remove the class.
+    const transformWidgetSearchability = (widget: Widget) => {
+      if (!widget) {
+        return;
+      }
+      const providerForWidget = registry.getProviderForWidget(widget);
+      if (providerForWidget) {
+        widget.addClass(SEARCHABLE_CLASS);
+      }
+      if (!providerForWidget) {
+        widget.removeClass(SEARCHABLE_CLASS);
+      }
+    };
+
+    // Update searchability of the active widget when the registry
+    // changes, in case a provider for the current widget was added
+    // or removed
+    registry.changed.connect(() =>
+      transformWidgetSearchability(labShell.activeWidget)
+    );
+
+    // Apply the searchable class only to the active widget if it is actually
+    // searchable. Remove the searchable class from a widget when it's
+    // no longer active.
     labShell.activeChanged.connect((_, args) => {
       const oldWidget = args.oldValue;
-      const newWidget = args.newValue;
-      if (newWidget && registry.getProviderForWidget(newWidget) !== undefined) {
-        newWidget.addClass(SEARCHABLE_CLASS);
-      }
       if (oldWidget) {
         oldWidget.removeClass(SEARCHABLE_CLASS);
       }
+      transformWidgetSearchability(args.newValue);
     });
   }
 };

+ 14 - 0
packages/documentsearch/src/searchproviderregistry.ts

@@ -7,6 +7,7 @@ import { NotebookSearchProvider } from './providers/notebooksearchprovider';
 import { Token } from '@phosphor/coreutils';
 import { Widget } from '@phosphor/widgets';
 import { IDisposable, DisposableDelegate } from '@phosphor/disposable';
+import { ISignal, Signal } from '@phosphor/signaling';
 
 /* tslint:disable */
 /**
@@ -32,6 +33,12 @@ export interface ISearchProviderRegistry {
    * @returns the search provider, or undefined if none exists.
    */
   getProviderForWidget(widget: any): ISearchProvider | undefined;
+
+  /**
+   * Signal that emits when a new search provider has been registered
+   * or removed.
+   */
+  changed: ISignal<ISearchProviderRegistry, void>;
 }
 
 export class SearchProviderRegistry implements ISearchProviderRegistry {
@@ -53,8 +60,10 @@ export class SearchProviderRegistry implements ISearchProviderRegistry {
    */
   register(key: string, provider: ISearchProviderConstructor): IDisposable {
     this._customProviders.set(key, provider);
+    this._changed.emit();
     return new DisposableDelegate(() => {
       this._customProviders.delete(key);
+      this._changed.emit();
     });
   }
 
@@ -71,6 +80,10 @@ export class SearchProviderRegistry implements ISearchProviderRegistry {
     );
   }
 
+  get changed(): ISignal<this, void> {
+    return this._changed;
+  }
+
   private _registerDefaultProviders(
     key: string,
     provider: ISearchProviderConstructor
@@ -92,6 +105,7 @@ export class SearchProviderRegistry implements ISearchProviderRegistry {
     return undefined;
   }
 
+  private _changed = new Signal<this, void>(this);
   private _defaultProviders: Private.ProviderMap = new Map<
     string,
     ISearchProviderConstructor