diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ea9467d9b4c9..a3bf971f60ec0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
[Breaking Changes:](#breaking_changes_1.15.0)
- [editor-preview] `EditorPreviewWidget` now extends `EditorWidget` and `EditorPreviewManager` extends and overrides `EditorManager`. `instanceof` checks can no longer distinguish between preview and non-preview editors; use `.isPreview` field instead. [#9518](https://github.com/eclipse-theia/theia/pull/9517)
+- [core] `outline-view-tree.ts` has been renamed to `outline-view-tree-model.ts` to match class name. [#9583](https://github.com/eclipse-theia/theia/pull/9583)
## v1.14.0 - 5/27/2021
diff --git a/packages/core/src/browser/tree/tree-widget.tsx b/packages/core/src/browser/tree/tree-widget.tsx
index 085f2a9f6df73..892d73b5e826a 100644
--- a/packages/core/src/browser/tree/tree-widget.tsx
+++ b/packages/core/src/browser/tree/tree-widget.tsx
@@ -99,6 +99,12 @@ export interface TreeProps {
* `true` if a tree widget contributes to the global selection. Defaults to `false`.
*/
readonly globalSelection?: boolean;
+
+ /**
+ * `true` if the tree widget supports expansion only when clicking the expansion toggle. Defaults to `false`.
+ */
+ readonly expandOnlyOnExpansionToggleClick?: boolean;
+
}
/**
@@ -531,7 +537,13 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
const nodeId = event.currentTarget.getAttribute('data-node-id');
if (nodeId) {
const node = this.model.getNode(nodeId);
- this.handleClickEvent(node, event);
+ if (node && this.props.expandOnlyOnExpansionToggleClick) {
+ if (this.isExpandable(node) && !this.hasShiftMask(event) && !this.hasCtrlCmdMask(event)) {
+ this.model.toggleNodeExpansion(node);
+ }
+ } else {
+ this.handleClickEvent(node, event);
+ }
}
event.stopPropagation();
}
@@ -557,7 +569,8 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
return
+ onClick={this.toggle}
+ onDoubleClick={this.handleExpansionToggleDblClickEvent}>
;
}
@@ -1123,9 +1136,9 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
*/
protected handleClickEvent(node: TreeNode | undefined, event: React.MouseEvent): void {
if (node) {
+ const shiftMask = this.hasShiftMask(event);
+ const ctrlCmdMask = this.hasCtrlCmdMask(event);
if (!!this.props.multiSelect) {
- const shiftMask = this.hasShiftMask(event);
- const ctrlCmdMask = this.hasCtrlCmdMask(event);
if (SelectableTreeNode.is(node)) {
if (shiftMask) {
this.model.selectRange(node);
@@ -1135,14 +1148,13 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
this.model.selectNode(node);
}
}
- if (this.isExpandable(node) && !shiftMask && !ctrlCmdMask) {
- this.model.toggleNodeExpansion(node);
- }
} else {
if (SelectableTreeNode.is(node)) {
this.model.selectNode(node);
}
- if (this.isExpandable(node) && !this.hasCtrlCmdMask(event) && !this.hasShiftMask(event)) {
+ }
+ if (!this.props.expandOnlyOnExpansionToggleClick) {
+ if (this.isExpandable(node) && !shiftMask && !ctrlCmdMask) {
this.model.toggleNodeExpansion(node);
}
}
@@ -1191,6 +1203,17 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
event.preventDefault();
}
+ /**
+ * Handle the double-click mouse event on the expansion toggle.
+ * @param event the double-click mouse event.
+ */
+ protected handleExpansionToggleDblClickEvent(event: React.MouseEvent): void {
+ if (this.props.expandOnlyOnExpansionToggleClick) {
+ // Ignore the double-click event.
+ event.stopPropagation();
+ }
+ }
+
/**
* Convert the tree node to context menu arguments.
* @param node the selectable tree node.
diff --git a/packages/outline-view/src/browser/outline-view-frontend-module.ts b/packages/outline-view/src/browser/outline-view-frontend-module.ts
index a8969c12f753b..a110da6fa61bc 100644
--- a/packages/outline-view/src/browser/outline-view-frontend-module.ts
+++ b/packages/outline-view/src/browser/outline-view-frontend-module.ts
@@ -34,7 +34,7 @@ import { OutlineViewWidgetFactory, OutlineViewWidget } from './outline-view-widg
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';
+import { OutlineViewTreeModel } from './outline-view-tree-model';
export default new ContainerModule(bind => {
bind(OutlineViewWidgetFactory).toFactory(ctx =>
@@ -61,7 +61,7 @@ export default new ContainerModule(bind => {
function createOutlineViewWidget(parent: interfaces.Container): OutlineViewWidget {
const child = createTreeContainer(parent);
- child.rebind(TreeProps).toConstantValue({ ...defaultTreeProps, search: true });
+ child.rebind(TreeProps).toConstantValue({ ...defaultTreeProps, expandOnlyOnExpansionToggleClick: true, search: true });
child.unbind(TreeWidget);
child.bind(OutlineViewWidget).toSelf();
diff --git a/packages/outline-view/src/browser/outline-view-tree.ts b/packages/outline-view/src/browser/outline-view-tree-model.ts
similarity index 77%
rename from packages/outline-view/src/browser/outline-view-tree.ts
rename to packages/outline-view/src/browser/outline-view-tree-model.ts
index d75dd4ad8c2a6..759d92ed5f7f7 100644
--- a/packages/outline-view/src/browser/outline-view-tree.ts
+++ b/packages/outline-view/src/browser/outline-view-tree-model.ts
@@ -15,7 +15,7 @@
********************************************************************************/
import { injectable, inject } from '@theia/core/shared/inversify';
-import { CompositeTreeNode, TreeModelImpl, TreeExpansionService, ExpandableTreeNode } from '@theia/core/lib/browser';
+import { CompositeTreeNode, TreeModelImpl, TreeExpansionService, ExpandableTreeNode, TreeNode } from '@theia/core/lib/browser';
@injectable()
export class OutlineViewTreeModel extends TreeModelImpl {
@@ -39,4 +39,16 @@ export class OutlineViewTreeModel extends TreeModelImpl {
}
return false;
}
+
+ /**
+ * The default behavior of `openNode` calls `doOpenNode` which by default
+ * toggles the expansion of the node. Overriding to prevent expansion, but
+ * allow for the `onOpenNode` event to still fire on a double-click event.
+ */
+ openNode(raw?: TreeNode | undefined): void {
+ const node = raw || this.selectedNodes[0];
+ if (node) {
+ this.onOpenNodeEmitter.fire(node);
+ }
+ }
}
diff --git a/packages/outline-view/src/browser/outline-view-widget.tsx b/packages/outline-view/src/browser/outline-view-widget.tsx
index 12ac92459eb86..b2a897b564759 100644
--- a/packages/outline-view/src/browser/outline-view-widget.tsx
+++ b/packages/outline-view/src/browser/outline-view-widget.tsx
@@ -25,7 +25,7 @@ import {
TreeModel,
ExpandableTreeNode
} from '@theia/core/lib/browser';
-import { OutlineViewTreeModel } from './outline-view-tree';
+import { OutlineViewTreeModel } from './outline-view-tree-model';
import { Message } from '@theia/core/shared/@phosphor/messaging';
import { Emitter } from '@theia/core';
import { CompositeTreeNode } from '@theia/core/lib/browser';