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

focused element and selected elements as arguments for title commands #158916

Merged
merged 3 commits into from Aug 24, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/vs/workbench/api/browser/mainThreadTreeViews.ts
Expand Up @@ -168,6 +168,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
this._register(treeView.onDidExpandItem(item => this._proxy.$setExpanded(treeViewId, item.handle, true)));
this._register(treeView.onDidCollapseItem(item => this._proxy.$setExpanded(treeViewId, item.handle, false)));
this._register(treeView.onDidChangeSelection(items => this._proxy.$setSelection(treeViewId, items.map(({ handle }) => handle))));
this._register(treeView.onDidChangeFocus(item => this._proxy.$setFocus(treeViewId, item.handle)));
this._register(treeView.onDidChangeVisibility(isVisible => this._proxy.$setVisible(treeViewId, isVisible)));
}

Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/common/extHost.protocol.ts
Expand Up @@ -1404,6 +1404,7 @@ export interface ExtHostTreeViewsShape {
$handleDrag(sourceViewId: string, sourceTreeItemHandles: string[], operationUuid: string, token: CancellationToken): Promise<DataTransferDTO | undefined>;
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void;
$setSelection(treeViewId: string, treeItemHandles: string[]): void;
$setFocus(treeViewId: string, treeItemHandle: string): void;
$setVisible(treeViewId: string, visible: boolean): void;
$hasResolve(treeViewId: string): Promise<boolean>;
$resolve(treeViewId: string, treeItemHandle: string, token: CancellationToken): Promise<ITreeItem | undefined>;
Expand Down
21 changes: 18 additions & 3 deletions src/vs/workbench/api/common/extHostTreeViews.ts
Expand Up @@ -59,7 +59,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
) {

function isTreeViewConvertableItem(arg: any): boolean {
return arg && arg.$treeViewId && (arg.$treeItemHandle || arg.$selectedTreeItems);
return arg && arg.$treeViewId && (arg.$treeItemHandle || arg.$selectedTreeItems || arg.$focusedTreeItem);
}
commands.registerArgumentProcessor({
processArgument: arg => {
Expand Down Expand Up @@ -221,6 +221,14 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
treeView.setSelection(treeItemHandles);
}

$setFocus(treeViewId: string, treeItemHandles: string) {
const treeView = this.treeViews.get(treeViewId);
if (!treeView) {
throw new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId));
}
treeView.setFocus(treeItemHandles);
}

$setVisible(treeViewId: string, isVisible: boolean): void {
const treeView = this.treeViews.get(treeViewId);
if (!treeView) {
Expand All @@ -240,8 +248,8 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
if (treeView && '$treeItemHandle' in arg) {
return treeView.getExtensionElement(arg.$treeItemHandle);
}
if (treeView && '$selectedTreeItems' in arg && arg.$selectedTreeItems) {
return { selectedTreeItems: treeView.selectedElements };
if (treeView && '$focusedTreeItem' in arg && arg.$focusedTreeItem) {
return treeView.focusedElement;
}
return null;
}
Expand Down Expand Up @@ -276,6 +284,9 @@ class ExtHostTreeView<T> extends Disposable {
private _selectedHandles: TreeItemHandle[] = [];
get selectedElements(): T[] { return <T[]>this._selectedHandles.map(handle => this.getExtensionElement(handle)).filter(element => !isUndefinedOrNull(element)); }

private _focusedHandle: TreeItemHandle | undefined = undefined;
get focusedElement(): T | undefined { return <T | undefined>(this._focusedHandle ? this.getExtensionElement(this._focusedHandle) : undefined); }

private _onDidExpandElement: Emitter<vscode.TreeViewExpansionEvent<T>> = this._register(new Emitter<vscode.TreeViewExpansionEvent<T>>());
readonly onDidExpandElement: Event<vscode.TreeViewExpansionEvent<T>> = this._onDidExpandElement.event;

Expand Down Expand Up @@ -455,6 +466,10 @@ class ExtHostTreeView<T> extends Disposable {
}
}

setFocus(treeItemHandle: TreeItemHandle) {
this._focusedHandle = treeItemHandle;
}

setVisible(visible: boolean): void {
if (visible !== this._visible) {
this._visible = visible;
Expand Down
28 changes: 22 additions & 6 deletions src/vs/workbench/browser/parts/views/treeView.ts
Expand Up @@ -71,6 +71,7 @@ export class TreeViewPane extends ViewPane {

protected readonly treeView: ITreeView;
private _container: HTMLElement | undefined;
private _actionRunner: MultipleSelectionActionRunner;

constructor(
options: IViewletViewOptions,
Expand All @@ -83,6 +84,7 @@ export class TreeViewPane extends ViewPane {
@IOpenerService openerService: IOpenerService,
@IThemeService themeService: IThemeService,
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService
) {
super({ ...(options as IViewPaneOptions), titleMenuId: MenuId.ViewTitle, donotForwardArgs: false }, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
const { treeView } = (<ITreeViewDescriptor>Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getView(options.id));
Expand All @@ -103,6 +105,7 @@ export class TreeViewPane extends ViewPane {
if (options.titleDescription !== this.treeView.description) {
this.updateTitleDescription(this.treeView.description);
}
this._actionRunner = new MultipleSelectionActionRunner(notificationService, () => this.treeView.getSelection());

this.updateTreeVisibility();
}
Expand Down Expand Up @@ -143,11 +146,12 @@ export class TreeViewPane extends ViewPane {
this.treeView.setVisibility(this.isBodyVisible());
}

override getActionRunner() {
return this._actionRunner;
}

override getActionsContext(): TreeViewPaneHandleArg {
return {
$selectedTreeItems: true,
$treeViewId: this.id
};
return { $treeViewId: this.id, $focusedTreeItem: true, $selectedTreeItems: true };
}

}
Expand Down Expand Up @@ -214,6 +218,9 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
private _onDidChangeSelection: Emitter<ITreeItem[]> = this._register(new Emitter<ITreeItem[]>());
readonly onDidChangeSelection: Event<ITreeItem[]> = this._onDidChangeSelection.event;

private _onDidChangeFocus: Emitter<ITreeItem> = this._register(new Emitter<ITreeItem>());
readonly onDidChangeFocus: Event<ITreeItem> = this._onDidChangeFocus.event;

private readonly _onDidChangeVisibility: Emitter<boolean> = this._register(new Emitter<boolean>());
readonly onDidChangeVisibility: Event<boolean> = this._onDidChangeVisibility.event;

Expand Down Expand Up @@ -617,6 +624,11 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
customTreeKey.set(true);
this._register(this.tree.onContextMenu(e => this.onContextMenu(treeMenus, e, actionRunner)));
this._register(this.tree.onDidChangeSelection(e => this._onDidChangeSelection.fire(e.elements)));
this._register(this.tree.onDidChangeFocus(e => {
if (e.elements.length) {
benibenj marked this conversation as resolved.
Show resolved Hide resolved
this._onDidChangeFocus.fire(e.elements[0]);
}
}));
this._register(this.tree.onDidChangeCollapseState(e => {
if (!e.node.element) {
return;
Expand Down Expand Up @@ -803,6 +815,10 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
this.tree?.setSelection(items);
}

getSelection(): ITreeItem[] {
return this.tree?.getSelection() ?? [];
}

setFocus(item: ITreeItem): void {
if (this.tree) {
this.focus(true, item);
Expand Down Expand Up @@ -1233,13 +1249,13 @@ class MultipleSelectionActionRunner extends ActionRunner {
}));
}

override async runAction(action: IAction, context: TreeViewItemHandleArg): Promise<void> {
override async runAction(action: IAction, context: TreeViewItemHandleArg | TreeViewPaneHandleArg): Promise<void> {
const selection = this.getSelectedResources();
let selectionHandleArgs: TreeViewItemHandleArg[] | undefined = undefined;
let actionInSelected: boolean = false;
if (selection.length > 1) {
selectionHandleArgs = selection.map(selected => {
if (selected.handle === context.$treeItemHandle) {
if ((selected.handle === (context as TreeViewItemHandleArg).$treeItemHandle) || (context as TreeViewPaneHandleArg).$selectedTreeItems) {
actionInSelected = true;
}
return { $treeViewId: context.$treeViewId, $treeItemHandle: selected.handle };
Expand Down
9 changes: 7 additions & 2 deletions src/vs/workbench/browser/parts/views/viewPane.ts
Expand Up @@ -11,7 +11,7 @@ import { attachButtonStyler, attachProgressBarStyler } from 'vs/platform/theme/c
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { after, append, $, trackFocus, EventType, addDisposableListener, createCSSRule, asCSSUrl } from 'vs/base/browser/dom';
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IAction } from 'vs/base/common/actions';
import { IAction, IActionRunner } from 'vs/base/common/actions';
import { ActionsOrientation, IActionViewItem, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
import { Registry } from 'vs/platform/registry/common/platform';
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
Expand Down Expand Up @@ -298,7 +298,8 @@ export abstract class ViewPane extends Pane implements IView {
actionViewItemProvider: action => this.getActionViewItem(action),
ariaLabel: nls.localize('viewToolbarAriaLabel', "{0} actions", this.title),
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
renderDropdownAsChildElement: true
renderDropdownAsChildElement: true,
actionRunner: this.getActionRunner()
});

this._register(this.toolbar);
Expand Down Expand Up @@ -519,6 +520,10 @@ export abstract class ViewPane extends Pane implements IView {
return undefined;
}

getActionRunner(): IActionRunner | undefined {
return undefined;
}

getOptimalWidth(): number {
return 0;
}
Expand Down
7 changes: 6 additions & 1 deletion src/vs/workbench/common/views.ts
Expand Up @@ -663,6 +663,8 @@ export interface ITreeView extends IDisposable {

readonly onDidChangeSelection: Event<ITreeItem[]>;

readonly onDidChangeFocus: Event<ITreeItem>;

readonly onDidChangeVisibility: Event<boolean>;

readonly onDidChangeActions: Event<void>;
Expand Down Expand Up @@ -691,6 +693,8 @@ export interface ITreeView extends IDisposable {

setSelection(items: ITreeItem[]): void;

getSelection(): ITreeItem[];

setFocus(item: ITreeItem): void;

show(container: any): void;
Expand All @@ -712,7 +716,8 @@ export interface ITreeViewDescriptor extends IViewDescriptor {

export type TreeViewPaneHandleArg = {
$treeViewId: string;
$selectedTreeItems: boolean;
$selectedTreeItems?: boolean;
$focusedTreeItem?: boolean;
};

export type TreeViewItemHandleArg = {
Expand Down
Expand Up @@ -36,7 +36,7 @@ import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { FloatingClickWidget } from 'vs/workbench/browser/codeeditor';
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { Severity } from 'vs/platform/notification/common/notification';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { EditorResolution } from 'vs/platform/editor/common/editor';

Expand Down Expand Up @@ -66,8 +66,9 @@ export class UserDataSyncMergesViewPane extends TreeViewPane {
@IOpenerService openerService: IOpenerService,
@IThemeService themeService: IThemeService,
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService
) {
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService, notificationService);
this.userDataSyncPreview = userDataSyncWorkbenchService.userDataSyncPreview;

this._register(this.userDataSyncPreview.onDidChangeResources(() => this.updateSyncButtonEnablement()));
Expand Down