diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts index c020f63682288..bdff121311e0c 100644 --- a/packages/core/src/browser/common-frontend-contribution.ts +++ b/packages/core/src/browser/common-frontend-contribution.ts @@ -30,6 +30,8 @@ import * as browser from './browser'; import URI from '../common/uri'; import { ContextKeyService } from './context-key-service'; import { OS } from '../common/os'; +import { ResourceContextKey } from './resource-context-key'; +import { UriSelection } from '../common/selection'; export namespace CommonMenus { @@ -203,11 +205,25 @@ export class CommonFrontendContribution implements FrontendApplicationContributi @inject(ContextKeyService) protected readonly contextKeyService: ContextKeyService; + @inject(ResourceContextKey) + protected readonly resourceContextKey: ResourceContextKey; + @postConstruct() protected init(): void { this.contextKeyService.createKey('isLinux', OS.type() === OS.Type.Linux); this.contextKeyService.createKey('isMac', OS.type() === OS.Type.OSX); this.contextKeyService.createKey('isWindows', OS.type() === OS.Type.Windows); + + this.initResourceContextKeys(); + } + + protected initResourceContextKeys(): void { + const updateContextKeys = () => { + const resourceUri = UriSelection.getUri(this.selectionService.selection); + this.resourceContextKey.set(resourceUri); + }; + updateContextKeys(); + this.selectionService.onSelectionChanged(updateContextKeys); } registerMenus(registry: MenuModelRegistry): void { diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 4edb14bf7517f..052e5f74e7e91 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -68,6 +68,7 @@ import { bindCorePreferences } from './core-preferences'; import { QuickPickServiceImpl } from './quick-open/quick-pick-service-impl'; import { QuickPickService, quickPickServicePath } from '../common/quick-pick-service'; import { ContextKeyService } from './context-key-service'; +import { ResourceContextKey } from './resource-context-key'; export const frontendApplicationModule = new ContainerModule((bind, unbind, isBound, rebind) => { const themeService = ThemeService.get(); @@ -152,6 +153,7 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo return messages; }); + bind(ResourceContextKey).toSelf().inSingletonScope(); bind(CommonFrontendContribution).toSelf().inSingletonScope(); [FrontendApplicationContribution, CommandContribution, KeybindingContribution, MenuContribution].forEach(serviceIdentifier => bind(serviceIdentifier).toService(CommonFrontendContribution) diff --git a/packages/core/src/browser/resource-context-key.ts b/packages/core/src/browser/resource-context-key.ts new file mode 100644 index 0000000000000..9440eff0edb7e --- /dev/null +++ b/packages/core/src/browser/resource-context-key.ts @@ -0,0 +1,52 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { injectable, inject, postConstruct } from 'inversify'; +import URI from '../common/uri'; +import { ContextKeyService, ContextKey } from './context-key-service'; + +@injectable() +export class ResourceContextKey { + + @inject(ContextKeyService) + protected readonly contextKeyService: ContextKeyService; + + protected resourceSchemeKey: ContextKey; + protected resourceFileName: ContextKey; + protected resourceExtname: ContextKey; + protected resourceLangId: ContextKey; + + @postConstruct() + protected init(): void { + this.resourceSchemeKey = this.contextKeyService.createKey('resourceScheme', undefined); + this.resourceFileName = this.contextKeyService.createKey('resourceFilename', undefined); + this.resourceExtname = this.contextKeyService.createKey('resourceExtname', undefined); + this.resourceLangId = this.contextKeyService.createKey('resourceLangId', undefined); + } + + set(resourceUri: URI | undefined): void { + this.resourceSchemeKey.set(resourceUri && resourceUri.scheme); + this.resourceFileName.set(resourceUri && resourceUri.path.base); + this.resourceExtname.set(resourceUri && resourceUri.path.ext); + this.resourceLangId.set(resourceUri && this.getLanguageId(resourceUri)); + } + + /** should be implemented by subclasses */ + protected getLanguageId(uri: URI | undefined): string | undefined { + return undefined; + } + +} diff --git a/packages/editor/src/browser/editor-contribution.ts b/packages/editor/src/browser/editor-contribution.ts index 0bfdf17b9e26a..d1156e1e92f6b 100644 --- a/packages/editor/src/browser/editor-contribution.ts +++ b/packages/editor/src/browser/editor-contribution.ts @@ -36,29 +36,16 @@ export class EditorContribution implements FrontendApplicationContribution { protected readonly contextKeyService: ContextKeyService; onStart(): void { - this.initResourceContextKeys(); this.initEditorContextKeys(); this.updateStatusBar(); this.editorManager.onCurrentEditorChanged(() => this.updateStatusBar()); } + /** @default since 0.5.0 - will be removed in farther releases */ protected initResourceContextKeys(): void { - const resourceSchemeKey = this.contextKeyService.createKey('resourceScheme', undefined); - const resourceFileName = this.contextKeyService.createKey('resourceFilename', undefined); - const resourceExtname = this.contextKeyService.createKey('resourceExtname', undefined); - const resourceLangId = this.contextKeyService.createKey('resourceLangId', undefined); - const updateContextKeys = () => { - const editor = this.editorManager.currentEditor; - const resourceUri = editor && editor.getResourceUri(); - resourceSchemeKey.set(resourceUri && resourceUri.scheme); - resourceFileName.set(resourceUri && resourceUri.path.base); - resourceExtname.set(resourceUri && resourceUri.path.ext); - resourceLangId.set(this.getLanguageId(resourceUri)); - }; - updateContextKeys(); - this.editorManager.onCurrentEditorChanged(updateContextKeys); } + /** @default since 0.5.0 - will be removed in farther releases */ protected getLanguageId(uri: URI | undefined): string | undefined { const { languages } = this.languages; if (uri && languages) { diff --git a/packages/editor/src/browser/editor-widget.ts b/packages/editor/src/browser/editor-widget.ts index 4981ad4778685..9bb2d7385ae78 100644 --- a/packages/editor/src/browser/editor-widget.ts +++ b/packages/editor/src/browser/editor-widget.ts @@ -14,7 +14,7 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { SelectionService } from '@theia/core/lib/common'; +import { Disposable, SelectionService } from '@theia/core/lib/common'; import { Widget, BaseWidget, Message, Saveable, SaveableSource, Navigatable, StatefulWidget, DiffUris } from '@theia/core/lib/browser'; import URI from '@theia/core/lib/common/uri'; import { TextEditor } from './editor'; @@ -32,6 +32,11 @@ export class EditorWidget extends BaseWidget implements SaveableSource, Navigata this.selectionService.selection = this.editor; } })); + this.toDispose.push(Disposable.create(() => { + if (this.selectionService.selection === this.editor) { + this.selectionService.selection = undefined; + } + })); } get saveable(): Saveable { diff --git a/packages/languages/src/browser/language-resource-context-key.ts b/packages/languages/src/browser/language-resource-context-key.ts new file mode 100644 index 0000000000000..826f851d8a141 --- /dev/null +++ b/packages/languages/src/browser/language-resource-context-key.ts @@ -0,0 +1,40 @@ +/******************************************************************************** + * Copyright (C) 2019 TypeFox and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { injectable, inject } from 'inversify'; +import URI from '@theia/core/lib/common/uri'; +import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key'; +import { Languages } from './language-client-services'; + +@injectable() +export class LanguageResourceContextKey extends ResourceContextKey { + + @inject(Languages) + protected readonly languages: Languages; + + protected getLanguageId(uri: URI | undefined): string | undefined { + const { languages } = this.languages; + if (uri && languages) { + for (const language of languages) { + if (language.extensions.has(uri.path.ext)) { + return language.id; + } + } + } + return undefined; + } + +} diff --git a/packages/languages/src/browser/languages-frontend-module.ts b/packages/languages/src/browser/languages-frontend-module.ts index 0409a73d9afa2..d1ea33fec38fa 100644 --- a/packages/languages/src/browser/languages-frontend-module.ts +++ b/packages/languages/src/browser/languages-frontend-module.ts @@ -16,6 +16,7 @@ import { ContainerModule } from 'inversify'; import { bindContributionProvider, CommandContribution } from '@theia/core/lib/common'; +import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key'; import { FrontendApplicationContribution, KeybindingContribution, QuickOpenContribution, WebSocketConnectionProvider } from '@theia/core/lib/browser'; import { Window } from './language-client-services'; import { WindowImpl } from './window-impl'; @@ -26,8 +27,9 @@ import { WorkspaceSymbolCommand } from './workspace-symbols'; import { LanguageClientProvider } from './language-client-provider'; import { LanguageClientProviderImpl } from './language-client-provider-impl'; import { LanguageContribution } from '../common'; +import { LanguageResourceContextKey } from './language-resource-context-key'; -export default new ContainerModule(bind => { +export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(Window).to(WindowImpl).inSingletonScope(); bind(LanguageClientFactory).toSelf().inSingletonScope(); @@ -47,4 +49,7 @@ export default new ContainerModule(bind => { bind(LanguageClientProviderImpl).toSelf().inSingletonScope(); bind(LanguageClientProvider).toService(LanguageClientProviderImpl); + + bind(LanguageResourceContextKey).toSelf().inSingletonScope(); + rebind(ResourceContextKey).to(LanguageResourceContextKey).inSingletonScope(); }); diff --git a/packages/navigator/src/browser/navigator-widget.tsx b/packages/navigator/src/browser/navigator-widget.tsx index 52dc894b69008..4f3f8f824c230 100644 --- a/packages/navigator/src/browser/navigator-widget.tsx +++ b/packages/navigator/src/browser/navigator-widget.tsx @@ -17,7 +17,7 @@ import { injectable, inject, postConstruct } from 'inversify'; import { Message } from '@phosphor/messaging'; import URI from '@theia/core/lib/common/uri'; -import { CommandService, SelectionService } from '@theia/core/lib/common'; +import { CommandService, SelectionService, Disposable } from '@theia/core/lib/common'; import { CommonCommands, CorePreferences } from '@theia/core/lib/browser'; import { ContextMenuRenderer, ExpandableTreeNode, @@ -83,6 +83,11 @@ export class FileNavigatorWidget extends FileTreeWidget { this.model.expandNode(child); } } + }), + Disposable.create(() => { + if (this.selectionService.selection === this) { + this.selectionService.selection = undefined; + } }) ]); }