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

Open editors widget in navigator #9284

Conversation

kenneth-marut-work
Copy link
Contributor

@kenneth-marut-work kenneth-marut-work commented Mar 30, 2021

What it does

Fixes: #8936
Adds 'Opened Editors' panel into the Navigator's layout, hidden by default

grouping-open

Includes the following functionality:

  • Shows all opened saveable editors
  • Provides SCM, Problem, dirty, and preview state decorators
  • Provides caption affix to indicate file's workspace root, as well as relative path
  • Adds buttons to close individual editors as well as toolbar buttons to Close All/Save All
  • Adds context menu options to tree nodes to perform actions including: Open in Terminal, Copy Path, Save, Compare, Close All, Close Others
  • Tracks active editors and will also activate editors when tree nodes are selected, pins preview widget when doubleclicked
  • Follows VSCode's grouping convention (i.e. GROUP 1, GROUP 2) to main area editor widgets. If widgets are placed in other shell areas, they are grouped by area (main, bottom, left, right)
  • Adds tree node items for "Save All" and "Close All" on group nodes and area nodes
  • Will update ordering of widgets when they are rearranged in a tabbar

Known Issues/Areas for Improvement:

  • Currently this widget is only tracking NavigatableWidgets (editor widgets) to avoid too much noise, in VSCode it seems that any 'main' area widget is tracked, but this system does not align perfectly with Theia's since we can dock widgets anywhere.
  • VSCode provides additional toolbar buttons including 'New Untitled File', and 'Toggle Vertical/Horizontal Layout'
  • VSCode will display a badge decoration in the toolbar when there are any unsaved editors:
    image
  • VSCode auto-sizes its panel layout based on the widget's contents, I'm not quite sure how to achieve this easily with Phosphor's PanelLayout.
  • When widgets are rearranged on the left/right toolbars, the ordering will not update (it seems that the left/right DockPanel's layoutModified listener behaves differently from the main/bottom dock panel

How to test

Set Up:

  • Pull branch and build
  • Open a single-root workspace and open some files
  • Right click the file explorer's tabbar and select "Open Editors" to enable the widget

Widget Tracking:

  • Open some files and observe that editors are tracked and added
  • Click on the nodes and observe the their corresponding widgets are activated
  • Close widgets from the tabbar, are they removed from the tree view?
  • Dock widgets in different panes, split widgets in the main area, observe the grouping strategy. Does this make sense?
  • Try out some of the grouping toolbar items like "Close Group" and "Save All in Group"

Decorations:

  • Start editing a file, observe the the file is marked as dirty
  • If a widget is opened in Preview mode, it should appear in italics (reflecting the Main Area tabbar state) double click on its node to pin the widget, it should be displayed as normal
  • Attempt to close the file using the 'x' icon, does it behave as expected?
  • Try these steps in a multiroot workspace, observe that caption suffixes are added that indicate the workspace root as well as its relative path
  • Introducing invalid syntax in a file should decorate the node using the problem decorator to match its appearance in the file explorer
  • Introducing changes will decorate the node with the SCM decorator

Actions:

  • Use the toolbar icons and verify they behave as expected
  • Use the context menu and verify the items behave as expected

Review checklist

Reminder for reviewers

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch 2 times, most recently from 84f046f to 71be806 Compare April 2, 2021 20:39
@kenneth-marut-work kenneth-marut-work changed the title WIP: Open editors widget in navigator Open editors widget in navigator Apr 2, 2021
Copy link
Contributor

@colin-grant-work colin-grant-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking very nice. I have a few comments on the code

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from 71be806 to c543684 Compare April 5, 2021 19:39
@kenneth-marut-work kenneth-marut-work marked this pull request as ready for review April 5, 2021 19:40
@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from c543684 to e4cc5d3 Compare April 5, 2021 19:42
@vince-fugnitto vince-fugnitto self-requested a review April 6, 2021 14:58
@vince-fugnitto vince-fugnitto added enhancement issues that are enhancements to current functionality - nice to haves navigator issues related to the navigator/explorer labels Apr 6, 2021
@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch 2 times, most recently from 5826303 to c8ca0ba Compare April 22, 2021 15:08
Copy link
Member

@vince-fugnitto vince-fugnitto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a high level pass of the pull-request, the main concern was the new coupling introduced by the changes.

I found an issue with the current styling, for different icon-themes (such as the seti) we encounter some problems:

open-editors-ui.mp4

packages/navigator/package.json Outdated Show resolved Hide resolved
packages/navigator/src/browser/navigator-contribution.ts Outdated Show resolved Hide resolved
packages/navigator/src/browser/navigator-contribution.ts Outdated Show resolved Hide resolved
@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from c8ca0ba to e7828b9 Compare April 23, 2021 16:57
@kenneth-marut-work
Copy link
Contributor Author

I did a high level pass of the pull-request, the main concern was the new coupling introduced by the changes.

I found an issue with the current styling, for different icon-themes (such as the seti) we encounter some problems:

open-editors-ui.mp4

icon-themes

I've updated the styling to satisfy changing the file icon themes. There is a bit of odd behavior when switching to Seti in particular as the indentation is not consistent with other themes (you can see this on the navigator tree as well), but does not cause any overlap with the decorator. Let me know if this is sufficient. Thanks!

Copy link
Contributor

@colin-grant-work colin-grant-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be working well for me, and the dependencies on the editor and editor-preview packages have been removed. One small hiccup is the size of widget - it doesn't seem to be adhering to the weight ratio specified - and the handling of multiple instances of the same editor widget.

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from e7828b9 to 093b36e Compare May 12, 2021 19:57
@kenneth-marut-work
Copy link
Contributor Author

This seems to be working well for me, and the dependencies on the editor and editor-preview packages have been removed. One small hiccup is the size of widget - it doesn't seem to be adhering to the weight ratio specified - and the handling of multiple instances of the same editor widget.

Thanks for taking another look @colin-grant-work. I've addressed your feedback, and also left a comment in the code regarding the quoted issue above.

@kenneth-marut-work
Copy link
Contributor Author

@colin-grant-work I've pushed an update to this PR that adds grouping functionality to the OpenEditors widget based on my best attempt at reconciling VSCode's OpenEditorsWidget behavior with Theia's ability to dock widgets anywhere. I've also added the corresponding toolbar icons to the grouping nodes that allow for "Close Group" and "Save all in group", and added listeners so that the tree is reordered when tabs are rearranged. Please give this a try and let me know if you have any suggestions

@colin-grant-work colin-grant-work self-requested a review July 2, 2021 14:34
Copy link
Contributor

@colin-grant-work colin-grant-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking pretty good. The behavior is pretty much spot on, just some minor comments about small display items and some stuff in the code.

Copy link
Contributor

@colin-grant-work colin-grant-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is working well to me, and the code looks reasonable. My greatest desideratum would be to follow VSCode in resizing the tree to only ever take up the amount of space it needs, but that can be tackled in a follow up PR.

@kenneth-marut-work
Copy link
Contributor Author

Hey @vince-fugnitto, I've made some considerable updates to this MR, would you be able to give it a test whenever you have free time?

My greatest desideratum would be to follow VSCode in resizing the tree to only ever take up the amount of space it needs, but that can be tackled in a follow up PR.

Regarding @colin-grant-work's comment above about the automatic resizing of a ViewContainer part, do you (@vince-fugnitto) have any suggestions on how to do that with Phosphor's built in methods? I couldn't seem to find a convenient way to do this.

Thanks!

@vince-fugnitto
Copy link
Member

@kenneth-marut-work do you mind rebasing, and I'd be happy to take a look 👍 As for the size of the view, it doesn't need to be part of this pull-request, I believe all tree-view parts suffer from the same bug where the size is not controllable.

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from 223eb65 to 07d1412 Compare July 9, 2021 17:35
Comment on lines 7 to 9
"@theia/editor": "1.15.0",
"@theia/navigator": "1.15.0",
"@theia/workspace": "1.15.0"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kenneth-marut-work @colin-grant-work is the new coupling necessary?
@theia/editor only uses core, why does editor-preview need the coupling?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two of us discussed this since the tree decorator (which is responsible for italicizing the filename when in preview mode, and also adding workspace/tail decorations) was decided to be moved from the navigator -> editor preview package. This allows the decorator to have access to the editor-preview's built-in checks for preview state, and emitters for on-preview-pinned.

It has the sideeffect of needing to depend on the navigator package (to access the decorator service) as well as the workspace service. The SCM and markers package have a similar dependency set up.

font-size: var(--theia-ui-font-size0);
}

.open-editors-node-row .open-editors-prefix-icon-container {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we should prefix the new stylings with theia-open-editors-widget

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

const widgets = openEditorsWidget.getEditorWidgetsByGroup(id);
widgets?.forEach(widget => widget.close());
},
isVisible: () => false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confirm, the following is set to false to hide it from the command palette?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So these two commands I've decided to hide from the command palette since they are essentially toolbar icon commands. Their implementation is slightly different from the way VSCode would implement them as they accept either an ApplicationShell.Area or TabBar<Widget> command as their argument.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought a simpler way would be to not give it a label so it does not show up in the command palette?
Although, I'm fine with you explicitly setting it to false as well.


export namespace OpenEditorsCommands {
export const CLOSE_ALL_TABS_FROM_TOOLBAR: Command = {
id: 'navigator.close.all.editors',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the new commands in the file, should we align their ids with that of vscode so the plugin-system can directly reference them without the mapping?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See note above, I've kept these commands separate from the plugin commands since their implementation is slightly different in both arguments and behavior. I've added added an additional command with VSCode's ID to the plugin-vscode-commands-contribution for workbench.files.saveAllInGroup which uses a very similar implementation as the existing workbench.action.closeEditorsInGroup and ensured that the two now have labels so that they can be accessed from the command palette. It's a bit tricky to figure out exactly where some of these things should live, but this was my best attempt at separating responsibilities. I've also added an appropriate utility in the application shell for saving editors which I am using in the execute of the toolbar commands.

Let me know if you have suggestions, thanks!

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch 3 times, most recently from 62ad33a to 98a21a7 Compare July 14, 2021 21:49
@@ -105,7 +113,8 @@ export namespace FileNavigatorCommands {
label: 'Focus on Files Explorer'
};
export const COPY_RELATIVE_FILE_PATH: Command = {
id: 'navigator.copyRelativeFilePath'
id: 'navigator.copyRelativeFilePath',
label: 'Copy Relative Path'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we align?

Suggested change
label: 'Copy Relative Path'
label: 'Copy Relative Path of Active File'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In VSCode, when I right click on files and look for this command I see "Copy Relative Path". I do see two labels for this command in the VSCode repo, but I'm not sure I understand how VSCode represents their commands to make the call:

https://github.com/microsoft/vscode/blob/2853fd0ffcc4c067bf7b5b31ccfc15ac245fc89c/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts#L163

https://github.com/microsoft/vscode/blob/2853fd0ffcc4c067bf7b5b31ccfc15ac245fc89c/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts#L215

isVisible: widget => this.withOpenEditorsWidget(widget, () => !!this.editorWidgets.length)
});
registry.registerCommand(OpenEditorsCommands.SAVE_ALL_TABS_FROM_TOOLBAR, {
execute: widget => this.withOpenEditorsWidget(widget, () => this.commandService.executeCommand(CommonCommands.SAVE_ALL.id)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the CommandService injection:

Suggested change
execute: widget => this.withOpenEditorsWidget(widget, () => this.commandService.executeCommand(CommonCommands.SAVE_ALL.id)),
execute: widget => this.withOpenEditorsWidget(widget, () => registry.executeCommand(CommonCommands.SAVE_ALL.id)),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know, I've fixed this 👍

const widgets = openEditorsWidget.getEditorWidgetsByGroup(id);
widgets?.forEach(widget => widget.close());
},
isVisible: () => false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought a simpler way would be to not give it a label so it does not show up in the command palette?
Although, I'm fine with you explicitly setting it to false as well.

@@ -412,7 +463,7 @@ export class FileNavigatorContribution extends AbstractViewContribution<FileNavi
});
registry.registerMenuAction(NavigatorContextMenu.CLIPBOARD, {
commandId: FileNavigatorCommands.COPY_RELATIVE_FILE_PATH.id,
label: 'Copy Relative Path',
label: FileNavigatorCommands.COPY_RELATIVE_FILE_PATH.label,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it can be omitted if the label is the same as the command definition.
The same is true for other occurences.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also good to know, I've removed the labels from the menu items

export const OpenEditorsTreeDecorator = Symbol('OpenEditorsTreeDecorator');

@injectable()
export class OpenEditorsTreeDecoratorService extends AbstractTreeDecoratorService {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused as to this file.

  1. why does it live in navigator, navigator should not know about problems.
  2. I believe we want a open-editor decorator service which problems contributes to, like the following in problems/.
bind(NavigatorTreeDecorator).toService(ProblemDecorator);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved the suffix decorations that add the workspace * path/to/file to the problem decorator and added a conditional check if the decorated node belongs to the OpenEditorsWidget. This way the suffix decorations are only applied to open-editor nodes and not the navigator nodes. Moving that logic allows this file to be much less complex :)

Thanks for the suggestions and help with this issue!

The only downside is that I cannot find a way to aggregate the italicization provided by the editor-preview-tree-decorator into the suffix decoration, which causes a preview widget node to not have italicization on its suffix. I don't think this is really a problem and the cleaner code outweighs the minor UI flaw. This could also be addressed in a separate PR

image

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from 98a21a7 to 48593f3 Compare July 16, 2021 21:36
@kenneth-marut-work
Copy link
Contributor Author

@vince-fugnitto thanks for the helpful suggestions. I believe I have addressed your comments except for the minor issue with the visible: () => false check which I've decided to keep as I refer to those commands' labels by their Variable name in the OpenEditorsWidget for convenience.

Moving the suffix-decorations into the problem-decorator seemed to work quite well and greatly simplified the strange logic I was doing in the open-editors-decorator service to retroactively apply coloring, so now that file is much more straightforward.

@kenneth-marut-work
Copy link
Contributor Author

@vince-fugnitto thanks for pointing out the path display issue. I've fixed this and also added a case for when a file is opened outside a workspace (in that case we display the full path). This works for the case of no-workspace-open case as well:

Single root with nested files and file outside workspace
image

Multiroot with nested files, and file outside workspace
image

No-root workspace with file
image

Copy link
Member

@vince-fugnitto vince-fugnitto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes work well for me, and the code is also clean 👍

I attempted to review multiple use-cases:

  • confirmed it works in a single-root workspace
  • confirmed it works in a multi-root workspace
  • confirmed the relative paths are displayed for nested files
  • confirmed the root name and relative paths are displayed for files in a multi-root workspace
  • confirmed the problem decorations work for the open editors
  • confirmed that scm decorations work for the open editors
  • confirmed that dirty decorations work for the open editors
  • confirmed that the close-all and save-all toolbar items work
  • confirmed that the context-menu works for open editors
  • confirmed that switching editors in the view works
  • confirmed that it properly represents editor groups in the layout

The changes are already substantial, if there are improvements we can make them in subsequent pull-requests 👍

@kenneth-marut-work
Copy link
Contributor Author

The changes work well for me, and the code is also clean 👍

I attempted to review multiple use-cases:

  • confirmed it works in a single-root workspace
  • confirmed it works in a multi-root workspace
  • confirmed the relative paths are displayed for nested files
  • confirmed the root name and relative paths are displayed for files in a multi-root workspace
  • confirmed the problem decorations work for the open editors
  • confirmed that scm decorations work for the open editors
  • confirmed that dirty decorations work for the open editors
  • confirmed that the close-all and save-all toolbar items work
  • confirmed that the context-menu works for open editors
  • confirmed that switching editors in the view works
  • confirmed that it properly represents editor groups in the layout

The changes are already substantial, if there are improvements we can make them in subsequent pull-requests 👍

Thanks @vince-fugnitto, I'll go ahead and squash and otherwise will merge tomorrow if there are no objections

@kenneth-marut-work kenneth-marut-work force-pushed the feature/open-editors-widget branch from 9e56780 to a0472f6 Compare July 20, 2021 16:42
@kenneth-marut-work kenneth-marut-work merged commit f7d1a2d into eclipse-theia:master Jul 21, 2021
@vince-fugnitto vince-fugnitto added this to the 1.16.0 milestone Jul 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement issues that are enhancements to current functionality - nice to haves navigator issues related to the navigator/explorer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Tree view for Open Editors in file navigator
3 participants