Skip to content

Commit

Permalink
outline: add 'expand-all' toolbar item
Browse files Browse the repository at this point in the history
The commit adds support for the `expand-all` toolbar item for the
`outline-view` in order to expand rendered nodes. The changes mean that
the toolbar item for `collapse-all` and `expand-all` will be toggleable
based on the state of the view.

Signed-off-by: vince-fugnitto <[email protected]>
  • Loading branch information
vince-fugnitto committed Feb 15, 2023
1 parent 6f53691 commit 9150ff4
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 8 deletions.
39 changes: 33 additions & 6 deletions packages/outline-view/src/browser/outline-view-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,20 @@ export const OUTLINE_WIDGET_FACTORY_ID = 'outline-view';
*/
export namespace OutlineViewCommands {
/**
* Command which collapses all nodes
* from the `outline-view` tree.
* Command which collapses all nodes from the `outline-view` tree.
*/
export const COLLAPSE_ALL: Command = {
id: 'outlineView.collapse.all',
iconClass: codicon('collapse-all')
};

/**
* Command which expands all nodes from the `outline-view` tree.
*/
export const EXPAND_ALL: Command = {
id: 'outlineView.expand.all',
iconClass: codicon('expand-all')
};
}

@injectable()
Expand Down Expand Up @@ -66,18 +73,33 @@ export class OutlineViewContribution extends AbstractViewContribution<OutlineVie
override registerCommands(commands: CommandRegistry): void {
super.registerCommands(commands);
commands.registerCommand(OutlineViewCommands.COLLAPSE_ALL, {
isEnabled: widget => this.withWidget(widget, () => true),
isVisible: widget => this.withWidget(widget, () => true),
isEnabled: w => this.withWidget(w, () => true),
isVisible: w => this.withWidget(w, widget => !widget.model.areNodesCollapsed()),
execute: () => this.collapseAllItems()
});
commands.registerCommand(OutlineViewCommands.EXPAND_ALL, {
isEnabled: w => this.withWidget(w, () => true),
isVisible: w => this.withWidget(w, widget => widget.model.areNodesCollapsed()),
execute: () => this.expandAllItems()
});
}

registerToolbarItems(toolbar: TabBarToolbarRegistry): void {
async registerToolbarItems(toolbar: TabBarToolbarRegistry): Promise<void> {
const widget = await this.widget;
const onDidChange = widget.onDidUpdate;
toolbar.registerItem({
id: OutlineViewCommands.COLLAPSE_ALL.id,
command: OutlineViewCommands.COLLAPSE_ALL.id,
tooltip: nls.localizeByDefault('Collapse All'),
priority: 0
priority: 0,
onDidChange
});
toolbar.registerItem({
id: OutlineViewCommands.EXPAND_ALL.id,
command: OutlineViewCommands.EXPAND_ALL.id,
tooltip: nls.localizeByDefault('Expand All'),
priority: 0,
onDidChange
});
}

Expand All @@ -92,6 +114,11 @@ export class OutlineViewContribution extends AbstractViewContribution<OutlineVie
}
}

protected async expandAllItems(): Promise<void> {
const { model } = await this.widget;
model.expandAll(model.root);
}

/**
* Determine if the current widget is the `outline-view`.
*/
Expand Down
25 changes: 25 additions & 0 deletions packages/outline-view/src/browser/outline-view-tree-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,29 @@ export class OutlineViewTreeModel extends TreeModelImpl {
this.onOpenNodeEmitter.fire(node);
}
}

expandAll(raw?: TreeNode): void {
if (CompositeTreeNode.is(raw)) {
for (const child of raw.children) {
if (ExpandableTreeNode.is(child)) {
this.expandAll(child);
}
}
}
if (ExpandableTreeNode.is(raw)) {
this.expandNode(raw);
}
}

areNodesCollapsed(): boolean {
if (CompositeTreeNode.is(this.root)) {
for (const child of this.root.children) {
if (!ExpandableTreeNode.isCollapsed(child)) {
return false;
}
}
}
return true;
}

}
13 changes: 11 additions & 2 deletions packages/outline-view/src/browser/outline-view-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// *****************************************************************************

import { injectable, inject } from '@theia/core/shared/inversify';
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
import {
TreeWidget,
TreeNode,
Expand All @@ -29,7 +29,7 @@ import {
} from '@theia/core/lib/browser';
import { OutlineViewTreeModel } from './outline-view-tree-model';
import { Message } from '@theia/core/shared/@phosphor/messaging';
import { Emitter, isObject, Mutable, UriSelection } from '@theia/core';
import { Emitter, Event, isObject, Mutable, UriSelection } from '@theia/core';
import * as React from '@theia/core/shared/react';
import { Range } from '@theia/core/shared/vscode-languageserver-protocol';
import URI from '@theia/core/lib/common/uri';
Expand Down Expand Up @@ -78,6 +78,9 @@ export class OutlineViewWidget extends TreeWidget {

readonly onDidChangeOpenStateEmitter = new Emitter<boolean>();

protected readonly onDidUpdateEmitter = new Emitter<void>();
readonly onDidUpdate: Event<void> = this.onDidUpdateEmitter.event;

constructor(
@inject(TreeProps) treeProps: TreeProps,
@inject(OutlineViewTreeModel) override readonly model: OutlineViewTreeModel,
Expand All @@ -93,6 +96,12 @@ export class OutlineViewWidget extends TreeWidget {
this.addClass('theia-outline-view');
}

@postConstruct()
protected override init(): void {
super.init();
this.toDispose.push(this.model.onExpansionChanged(() => this.onDidUpdateEmitter.fire()));
}

/**
* Set the outline tree with the list of `OutlineSymbolInformationNode`.
* @param roots the list of `OutlineSymbolInformationNode`.
Expand Down

0 comments on commit 9150ff4

Please sign in to comment.