Skip to content

Commit

Permalink
Fixed #5670: implemented "collapse all" in the Outline widget
Browse files Browse the repository at this point in the history
- Added a "collapse all" toolbar item to the Outline widget.
- Created `OutlineViewTreeModel` class in order to override the default `collapseAll` function and `onExpansionChanged` event handler in the default tree model.

Signed-off-by: fangnx <naxin.fang@ericsson.com>
  • Loading branch information
fangnx committed Jul 25, 2019
1 parent 87a35c1 commit f12d9a2
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Breaking changes:
- `HostedPluginSupport` is refactored to support multiple `PluginManagerExt` properly
- [plugin] added support of `workspaceContains` activation events [#5649](https://github.com/theia-ide/theia/pull/5649)
- [plugin] activate dependencies before activating a plugin [#5661](https://github.com/theia-ide/theia/pull/5661)
- [outline] added `OutlineViewTreeModel` for the outline view tree widget

## v0.8.0

Expand Down
22 changes: 13 additions & 9 deletions packages/core/src/browser/tree/tree-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
********************************************************************************/

import { inject, injectable, postConstruct } from 'inversify';
import { DisposableCollection, Event, Emitter, SelectionProvider, ILogger } from '../../common';
import { DisposableCollection, Disposable, Event, Emitter, SelectionProvider, ILogger } from '../../common';
import { Tree, TreeNode, CompositeTreeNode } from './tree';
import { TreeSelectionService, SelectableTreeNode, TreeSelection } from './tree-selection';
import { TreeExpansionService, ExpandableTreeNode } from './tree-expansion';
Expand Down Expand Up @@ -155,14 +155,7 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
this.toDispose.push(this.selectionService);

this.toDispose.push(this.expansionService);
this.toDispose.push(this.expansionService.onExpansionChanged(node => {
this.fireChanged();
if (!node.expanded && [...this.selectedNodes].some(selectedNode => CompositeTreeNode.isAncestor(node, selectedNode))) {
if (SelectableTreeNode.isVisible(node)) {
this.selectNode(node);
}
}
}));
this.toDispose.push(this.handleExpansionChanged());

this.toDispose.push(this.onOpenNodeEmitter);
this.toDispose.push(this.onChangedEmitter);
Expand All @@ -173,6 +166,17 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
this.toDispose.dispose();
}

handleExpansionChanged(): Disposable {
return this.expansionService.onExpansionChanged(node => {
this.fireChanged();
if (!node.expanded && [...this.selectedNodes].some(selectedNode => CompositeTreeNode.isAncestor(node, selectedNode))) {
if (SelectableTreeNode.isVisible(node)) {
this.selectNode(node);
}
}
});
}

get root() {
return this.tree.root;
}
Expand Down
53 changes: 51 additions & 2 deletions packages/outline-view/src/browser/outline-view-contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,24 @@

import { injectable } from 'inversify';
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
import { OutlineViewWidget } from './outline-view-widget';
import { FrontendApplicationContribution, FrontendApplication } from '@theia/core/lib/browser/frontend-application';
import { Command, CommandRegistry } from '@theia/core/lib/common/command';
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { Widget } from '@theia/core/lib/browser/widgets';
import { OutlineViewWidget } from './outline-view-widget';
import { CompositeTreeNode } from '@theia/core/lib/browser/tree';

export const OUTLINE_WIDGET_FACTORY_ID = 'outline-view';

export namespace OutlineViewCommands {
export const COLLAPSE_ALL: Command = {
id: 'outlineView.collapse.all',
iconClass: 'collapse-all'
};
}

@injectable()
export class OutlineViewContribution extends AbstractViewContribution<OutlineViewWidget> implements FrontendApplicationContribution {
export class OutlineViewContribution extends AbstractViewContribution<OutlineViewWidget> implements FrontendApplicationContribution, TabBarToolbarContribution {

constructor() {
super({
Expand All @@ -40,4 +51,42 @@ export class OutlineViewContribution extends AbstractViewContribution<OutlineVie
async initializeLayout(app: FrontendApplication): Promise<void> {
await this.openView();
}

registerCommands(commands: CommandRegistry): void {
super.registerCommands(commands);
commands.registerCommand(OutlineViewCommands.COLLAPSE_ALL, {
isEnabled: widget => this.withWidget(widget, () => true),
isVisible: widget => this.withWidget(widget, () => true),
execute: () => this.collapseAllItems()
});
}

registerToolbarItems(toolbar: TabBarToolbarRegistry): void {
toolbar.registerItem({
id: OutlineViewCommands.COLLAPSE_ALL.id,
command: OutlineViewCommands.COLLAPSE_ALL.id,
tooltip: 'Collapse All',
priority: 0
});
}

/**
* Collapse all nodes in the outline view tree.
*/
protected async collapseAllItems(): Promise<void> {
const { model } = await this.widget;
const root = model.root as CompositeTreeNode;
root.children.forEach(async childNode => {
if (CompositeTreeNode.is(childNode)) {
await model.collapseAll(childNode);
}
});
}

protected withWidget<T>(widget: Widget | undefined = this.tryGetWidget(), cb: (widget: OutlineViewWidget) => T): T | false {
if (widget instanceof OutlineViewWidget && widget.id === OUTLINE_WIDGET_FACTORY_ID) {
return cb(widget);
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ import {
bindViewContribution,
TreeProps,
defaultTreeProps,
TreeDecoratorService
TreeDecoratorService,
TreeModel,
TreeModelImpl
} from '@theia/core/lib/browser';
import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { OutlineViewWidgetFactory, OutlineViewWidget } from './outline-view-widget';
import '../../src/browser/styles/index.css';
import { bindContributionProvider } from '@theia/core/lib/common/contribution-provider';
import { OutlineDecoratorService, OutlineTreeDecorator } from './outline-decorator-service';
import { OutlineViewTreeModel } from './outline-view-tree';

export default new ContainerModule(bind => {
bind(OutlineViewWidgetFactory).toFactory(ctx =>
Expand All @@ -42,6 +46,7 @@ export default new ContainerModule(bind => {

bindViewContribution(bind, OutlineViewContribution);
bind(FrontendApplicationContribution).toService(OutlineViewContribution);
bind(TabBarToolbarContribution).toService(OutlineViewContribution);
});

function createOutlineViewWidget(parent: interfaces.Container): OutlineViewWidget {
Expand All @@ -52,6 +57,10 @@ function createOutlineViewWidget(parent: interfaces.Container): OutlineViewWidge
child.unbind(TreeWidget);
child.bind(OutlineViewWidget).toSelf();

child.unbind(TreeModelImpl);
child.bind(OutlineViewTreeModel).toSelf();
child.rebind(TreeModel).toService(OutlineViewTreeModel);

child.bind(OutlineDecoratorService).toSelf().inSingletonScope();
child.rebind(TreeDecoratorService).toDynamicValue(ctx => ctx.container.get(OutlineDecoratorService)).inSingletonScope();
bindContributionProvider(child, OutlineTreeDecorator);
Expand Down
40 changes: 40 additions & 0 deletions packages/outline-view/src/browser/outline-view-tree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/********************************************************************************
* Copyright (C) 2019 Ericsson 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 { Disposable } from '@theia/core/src/common';
import { CompositeTreeNode, TreeModelImpl, TreeSelectionService, TreeExpansionService } from '@theia/core/lib/browser';

@injectable()
export class OutlineViewTreeModel extends TreeModelImpl {

@inject(TreeSelectionService) protected readonly selectionService: TreeSelectionService;
@inject(TreeExpansionService) protected readonly expansionService: TreeExpansionService;

handleExpansionChanged(): Disposable {
return this.expansionService.onExpansionChanged(node => {
this.fireChanged();
});
}

async collapseAll(raw?: Readonly<CompositeTreeNode>): Promise<boolean> {
const node = raw || this.selectedNodes[0];
if (CompositeTreeNode.is(node)) {
return this.expansionService.collapseAll(node);
}
return false;
}
}
3 changes: 2 additions & 1 deletion packages/outline-view/src/browser/outline-view-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
TreeModel,
ExpandableTreeNode
} from '@theia/core/lib/browser';
import { OutlineViewTreeModel } from './outline-view-tree';
import { Message } from '@phosphor/messaging';
import { Emitter } from '@theia/core';
import { CompositeTreeNode } from '@theia/core/lib/browser';
Expand All @@ -50,7 +51,7 @@ export class OutlineViewWidget extends TreeWidget {

constructor(
@inject(TreeProps) protected readonly treeProps: TreeProps,
@inject(TreeModel) model: TreeModel,
@inject(OutlineViewTreeModel) model: OutlineViewTreeModel,
@inject(ContextMenuRenderer) protected readonly contextMenuRenderer: ContextMenuRenderer
) {
super(treeProps, model, contextMenuRenderer);
Expand Down

0 comments on commit f12d9a2

Please sign in to comment.