Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-7521: Enabled Select All in the Output #7523

Merged
merged 2 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
********************************************************************************/

import { ContainerModule } from 'inversify';
import { bindDynamicLabelProvider } from './label/sample-dymanic-label-provider-command-contribution';
import { bindDynamicLabelProvider } from './label/sample-dynamic-label-provider-command-contribution';
import { bindSampleUnclosableView } from './view/sample-unclosable-view-contribution';

export default new ContainerModule(bind => {
Expand Down
49 changes: 47 additions & 2 deletions packages/output/src/browser/output-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,56 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { injectable } from 'inversify';
import { injectable, inject } from 'inversify';
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
import { Widget } from '@theia/core/lib/browser';
import { Widget, KeybindingRegistry, KeybindingContext, ApplicationShell } from '@theia/core/lib/browser';
import { OUTPUT_WIDGET_KIND, OutputWidget } from './output-widget';
import { Command, CommandRegistry } from '@theia/core/lib/common';

export namespace OutputCommands {

const OUTPUT_CATEGORY = 'Output';

export const CLEAR_OUTPUT_TOOLBAR: Command = {
id: 'output:clear',
category: OUTPUT_CATEGORY,
label: 'Clear Output',
iconClass: 'clear-all'
};

export const SELECT_ALL: Command = {
id: 'output:selectAll',
category: OUTPUT_CATEGORY,
label: 'Select All'
};

}

/**
* Enabled when the `Output` widget is the `activeWidget` in the shell.
*/
@injectable()
export class OutputWidgetIsActiveContext implements KeybindingContext {

static readonly ID = 'output:isActive';

@inject(ApplicationShell)
protected readonly shell: ApplicationShell;

readonly id = OutputWidgetIsActiveContext.ID;

isEnabled(): boolean {
return this.shell.activeWidget instanceof OutputWidget;
}

}

@injectable()
export class OutputContribution extends AbstractViewContribution<OutputWidget> {

@inject(OutputWidgetIsActiveContext)
protected readonly outputIsActiveContext: OutputWidgetIsActiveContext;

constructor() {
super({
widgetId: OUTPUT_WIDGET_KIND,
Expand All @@ -52,6 +83,20 @@ export class OutputContribution extends AbstractViewContribution<OutputWidget> {
isVisible: widget => this.withWidget(widget, () => true),
execute: widget => this.withWidget(widget, outputWidget => this.clear(outputWidget))
});
commands.registerCommand(OutputCommands.SELECT_ALL, {
isEnabled: () => this.outputIsActiveContext.isEnabled(),
isVisible: () => this.outputIsActiveContext.isEnabled(),
execute: widget => this.withWidget(widget, outputWidget => outputWidget.selectAll())
});
}

registerKeybindings(registry: KeybindingRegistry): void {
super.registerKeybindings(registry);
registry.registerKeybindings({
command: OutputCommands.SELECT_ALL.id,
keybinding: 'CtrlCmd+A',
context: OutputWidgetIsActiveContext.ID
});
}

protected async clear(widget: OutputWidget): Promise<void> {
Expand Down
10 changes: 6 additions & 4 deletions packages/output/src/browser/output-frontend-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import { ContainerModule, interfaces } from 'inversify';
import { ContainerModule } from 'inversify';
import { OutputWidget, OUTPUT_WIDGET_KIND } from './output-widget';
import { WidgetFactory, bindViewContribution } from '@theia/core/lib/browser';
import { OutputContribution } from './output-contribution';
import { WidgetFactory, bindViewContribution, KeybindingContext } from '@theia/core/lib/browser';
import { OutputContribution, OutputWidgetIsActiveContext } from './output-contribution';
import { OutputToolbarContribution } from './output-toolbar-contribution';
import { OutputChannelManager } from '../common/output-channel';
import { bindOutputPreferences } from '../common/output-preferences';
import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';

export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
export default new ContainerModule((bind, unbind, isBound, rebind) => {
bindOutputPreferences(bind);
bind(OutputWidget).toSelf();
bind(OutputChannelManager).toSelf().inSingletonScope();
Expand All @@ -34,6 +34,8 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
}));

bindViewContribution(bind, OutputContribution);
bind(OutputWidgetIsActiveContext).toSelf().inSingletonScope();
bind(KeybindingContext).toService(OutputWidgetIsActiveContext);
bind(OutputToolbarContribution).toSelf().inSingletonScope();
bind(TabBarToolbarContribution).toService(OutputToolbarContribution);
});
21 changes: 20 additions & 1 deletion packages/output/src/browser/output-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,31 @@ export class OutputWidget extends ReactWidget {
</React.Fragment>;
}

public clear(): void {
clear(): void {
if (this.outputChannelManager.selectedChannel) {
this.outputChannelManager.selectedChannel.clear();
}
}

selectAll(): void {
if (this.outputChannelManager.selectedChannel) {
const element = document.getElementById(OutputWidget.IDs.CONTENTS);
if (element) {
const selectElementContent = (htmlElement: HTMLElement) => {
const selection = window.getSelection();
const range = document.createRange();
if (selection && range) {
range.selectNodeContents(htmlElement);
selection.removeAllRanges();
selection.addRange(range);
}
};
element.focus();
selectElementContent(element);
}
}
}

protected renderChannelContents(): React.ReactNode {
return <div id={OutputWidget.IDs.CONTENTS}>{this.renderLines()}</div>;
}
Expand Down