From 5a262d42c18559dd87ae1357677acd7b91996301 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Thu, 11 Mar 2021 14:40:48 +0100 Subject: [PATCH] ATL-1063: Integrated search in workspace into IDE - Reordered the sidebar views. - Increased the default sidebar width. Signed-off-by: Akos Kitta --- .../browser/arduino-ide-frontend-module.ts | 17 +++++- .../boards-widget-frontend-contribution.ts | 2 +- .../library-widget-frontend-contribution.ts | 2 +- .../src/browser/style/index.css | 7 ++- ...debug-frontend-application-contribution.ts | 5 ++ .../theia/navigator/navigator-contribution.ts | 18 ++++++- ...arch-in-workspace-frontend-contribution.ts | 6 +-- .../search-in-workspace-result-tree-widget.ts | 34 ++++++++++++ .../search-in-workspace-widget.tsx | 54 +++++++++++++++++++ 9 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts create mode 100644 arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index d7216ac6..8152d79d 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -35,7 +35,9 @@ import { CommonFrontendContribution as TheiaCommonFrontendContribution, KeybindingRegistry as TheiaKeybindingRegistry, TabBarRendererFactory, - ContextMenuRenderer + ContextMenuRenderer, + createTreeContainer, + TreeWidget } from '@theia/core/lib/browser'; import { MenuContribution } from '@theia/core/lib/common/menu'; import { ApplicationShell } from './theia/core/application-shell'; @@ -147,6 +149,10 @@ import { WorkspaceVariableContribution as TheiaWorkspaceVariableContribution } f import { WorkspaceVariableContribution } from './theia/workspace/workspace-variable-contribution'; import { DebugConfigurationManager } from './theia/debug/debug-configuration-manager'; import { DebugConfigurationManager as TheiaDebugConfigurationManager } from '@theia/debug/lib/browser/debug-configuration-manager'; +import { SearchInWorkspaceWidget as TheiaSearchInWorkspaceWidget } from '@theia/search-in-workspace/lib/browser/search-in-workspace-widget'; +import { SearchInWorkspaceWidget } from './theia/search-in-workspace/search-in-workspace-widget'; +import { SearchInWorkspaceResultTreeWidget as TheiaSearchInWorkspaceResultTreeWidget } from '@theia/search-in-workspace/lib/browser/search-in-workspace-result-tree-widget'; +import { SearchInWorkspaceResultTreeWidget } from './theia/search-in-workspace/search-in-workspace-result-tree-widget'; const ElementQueries = require('css-element-queries/src/ElementQueries'); @@ -300,6 +306,15 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(MonacoTextModelService).toSelf().inSingletonScope(); rebind(TheiaMonacoTextModelService).toService(MonacoTextModelService); + bind(SearchInWorkspaceWidget).toSelf(); + rebind(TheiaSearchInWorkspaceWidget).toService(SearchInWorkspaceWidget); + rebind(TheiaSearchInWorkspaceResultTreeWidget).toDynamicValue(({ container }) => { + const childContainer = createTreeContainer(container); + childContainer.bind(SearchInWorkspaceResultTreeWidget).toSelf() + childContainer.rebind(TreeWidget).toService(SearchInWorkspaceResultTreeWidget); + return childContainer.get(SearchInWorkspaceResultTreeWidget); + }); + // Show a disconnected status bar, when the daemon is not available bind(ApplicationConnectionStatusContribution).toSelf().inSingletonScope(); rebind(TheiaApplicationConnectionStatusContribution).toService(ApplicationConnectionStatusContribution); diff --git a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts index fdbb290d..47403845 100644 --- a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts @@ -12,7 +12,7 @@ export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendCont widgetName: BoardsListWidget.WIDGET_LABEL, defaultWidgetOptions: { area: 'left', - rank: 600 + rank: 2 }, toggleCommandId: `${BoardsListWidget.WIDGET_ID}:toggle`, toggleKeybinding: 'CtrlCmd+Shift+B' diff --git a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts index eb87dd19..5dbace9a 100644 --- a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts @@ -14,7 +14,7 @@ export class LibraryListWidgetFrontendContribution extends AbstractViewContribut widgetName: LibraryListWidget.WIDGET_LABEL, defaultWidgetOptions: { area: 'left', - rank: 700 + rank: 3 }, toggleCommandId: `${LibraryListWidget.WIDGET_ID}:toggle`, toggleKeybinding: 'CtrlCmd+Shift+I' diff --git a/arduino-ide-extension/src/browser/style/index.css b/arduino-ide-extension/src/browser/style/index.css index 051eac11..0d8fd79c 100644 --- a/arduino-ide-extension/src/browser/style/index.css +++ b/arduino-ide-extension/src/browser/style/index.css @@ -37,8 +37,13 @@ background-color: var(--theia-warningBackground); } -/* Overrule the default Theia CSS button styles. */ +/* Makes the sidepanel a bit wider when opening the widget */ +.p-DockPanel-widget { + min-width: 200px; + min-height: 200px; +} +/* Overrule the default Theia CSS button styles. */ button.theia-button, .theia-button { border: 1px solid var(--theia-dropdown-border); diff --git a/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts b/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts index 94e960a4..083254c4 100644 --- a/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/debug/debug-frontend-application-contribution.ts @@ -6,6 +6,11 @@ import { unregisterSubmenu } from '../../menu/arduino-menus'; @injectable() export class DebugFrontendApplicationContribution extends TheiaDebugFrontendApplicationContribution { + constructor() { + super() + this.options.defaultWidgetOptions.rank = 4; + } + registerMenus(registry: MenuModelRegistry): void { super.registerMenus(registry); unregisterSubmenu(DebugMenus.DEBUG, registry); diff --git a/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts b/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts index 169b2500..4ec70415 100644 --- a/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/navigator/navigator-contribution.ts @@ -1,12 +1,28 @@ -import { injectable } from 'inversify'; +import { inject, injectable } from 'inversify'; import { WorkspaceCommands } from '@theia/workspace/lib/browser/workspace-commands'; import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; import { FileNavigatorContribution as TheiaFileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution'; +import { FileNavigatorPreferences } from '@theia/navigator/lib/browser/navigator-preferences'; +import { OpenerService } from '@theia/core/lib/browser/opener-service'; +import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; +import { FileNavigatorFilter } from '@theia/navigator/lib/browser/navigator-filter'; +import { WorkspacePreferences } from '@theia/workspace/lib/browser/workspace-preferences'; @injectable() export class FileNavigatorContribution extends TheiaFileNavigatorContribution { + constructor( + @inject(FileNavigatorPreferences) protected readonly fileNavigatorPreferences: FileNavigatorPreferences, + @inject(OpenerService) protected readonly openerService: OpenerService, + @inject(FileNavigatorFilter) protected readonly fileNavigatorFilter: FileNavigatorFilter, + @inject(WorkspaceService) protected readonly workspaceService: WorkspaceService, + @inject(WorkspacePreferences) protected readonly workspacePreferences: WorkspacePreferences + ) { + super(fileNavigatorPreferences, openerService, fileNavigatorFilter, workspaceService, workspacePreferences); + this.options.defaultWidgetOptions.rank = 1; + } + async initializeLayout(app: FrontendApplication): Promise { // NOOP } diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts index 76251281..b1a2fa5e 100644 --- a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-frontend-contribution.ts @@ -1,14 +1,14 @@ import { injectable } from 'inversify'; import { MenuModelRegistry } from '@theia/core/lib/common/menu'; import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding'; -import { FrontendApplication } from '@theia/core/lib/browser/frontend-application'; import { SearchInWorkspaceFrontendContribution as TheiaSearchInWorkspaceFrontendContribution, SearchInWorkspaceCommands } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution'; @injectable() export class SearchInWorkspaceFrontendContribution extends TheiaSearchInWorkspaceFrontendContribution { - async initializeLayout(app: FrontendApplication): Promise { - // NOOP + constructor() { + super(); + this.options.defaultWidgetOptions.rank = 5; } registerMenus(registry: MenuModelRegistry): void { diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts new file mode 100644 index 00000000..d5f09acf --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-result-tree-widget.ts @@ -0,0 +1,34 @@ +import { injectable } from 'inversify'; +import URI from '@theia/core/lib/common/uri'; +import { MEMORY_TEXT } from '@theia/search-in-workspace/lib/browser/in-memory-text-resource'; +import { SearchInWorkspaceFileNode, SearchInWorkspaceResultTreeWidget as TheiaSearchInWorkspaceResultTreeWidget } from '@theia/search-in-workspace/lib/browser/search-in-workspace-result-tree-widget'; + +/** + * Workaround for https://github.com/eclipse-theia/theia/pull/9192/. + */ +@injectable() +export class SearchInWorkspaceResultTreeWidget extends TheiaSearchInWorkspaceResultTreeWidget { + + protected async createReplacePreview(node: SearchInWorkspaceFileNode): Promise { + const fileUri = new URI(node.fileUri).withScheme('file'); + const openedEditor = this.editorManager.all.find(({ editor }) => editor.uri.toString() === fileUri.toString()); + let content: string; + if (openedEditor) { + content = openedEditor.editor.document.getText(); + } else { + const resource = await this.fileResourceResolver.resolve(fileUri); + content = await resource.readContents(); + } + + const lines = content.split('\n'); + node.children.map(l => { + const leftPositionedNodes = node.children.filter(rl => rl.line === l.line && rl.character < l.character); + const diff = (this._replaceTerm.length - this.searchTerm.length) * leftPositionedNodes.length; + const start = lines[l.line - 1].substr(0, l.character - 1 + diff); + const end = lines[l.line - 1].substr(l.character - 1 + diff + l.length); + lines[l.line - 1] = start + this._replaceTerm + end; + }); + + return fileUri.withScheme(MEMORY_TEXT).withQuery(lines.join('\n')); + } +} diff --git a/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx new file mode 100644 index 00000000..d826e450 --- /dev/null +++ b/arduino-ide-extension/src/browser/theia/search-in-workspace/search-in-workspace-widget.tsx @@ -0,0 +1,54 @@ +import { injectable } from 'inversify'; +import * as React from 'react'; +import { Key, KeyCode } from '@theia/core/lib/browser'; +import { SearchInWorkspaceWidget as TheiaSearchInWorkspaceWidget } from '@theia/search-in-workspace/lib/browser/search-in-workspace-widget'; + +/** + * Workaround for https://github.com/eclipse-theia/theia/pull/9183. + */ +@injectable() +export class SearchInWorkspaceWidget extends TheiaSearchInWorkspaceWidget { + + protected renderGlobField(kind: 'include' | 'exclude'): React.ReactNode { + const currentValue = this.searchInWorkspaceOptions[kind]; + const value = currentValue && currentValue.join(', ') || ''; + return
+
{'files to ' + kind}
+ { + if (e.target) { + const targetValue = (e.target as HTMLInputElement).value || ''; + let shouldSearch = Key.ENTER.keyCode === KeyCode.createKeyCode(e.nativeEvent).key?.keyCode; + const currentOptions = (this.searchInWorkspaceOptions[kind] || []).slice().map(s => s.trim()).sort(); + const candidateOptions = this.splitOnComma(targetValue).map(s => s.trim()).sort(); + const sameAs = (left: string[], right: string[]) => { + if (left.length !== right.length) { + return false; + } + for (let i = 0; i < left.length; i++) { + if (left[i] !== right[i]) { + return false; + } + } + return true; + }; + if (!sameAs(currentOptions, candidateOptions)) { + this.searchInWorkspaceOptions[kind] = this.splitOnComma(targetValue); + shouldSearch = true; + } + if (shouldSearch) { + this.resultTreeWidget.search(this.searchTerm, this.searchInWorkspaceOptions); + } + } + }} + onFocus={kind === 'include' ? this.handleFocusIncludesInputBox : this.handleFocusExcludesInputBox} + onBlur={kind === 'include' ? this.handleBlurIncludesInputBox : this.handleBlurExcludesInputBox}> +
; + } + +}