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

Make preference node rendering customizable and provide file selection #10766

Merged
merged 1 commit into from
Mar 30, 2022
Merged

Make preference node rendering customizable and provide file selection #10766

merged 1 commit into from
Mar 30, 2022

Conversation

martin-fleck-at
Copy link
Contributor

What it does

Fixes #10765

  • Introduce preference node render service to support contributions

    • Convert previous renderer factory content to default contribution
    • Let new renderer factory implementation use service
    • Contributions are ranked similar to open handlers
  • Provide base for leaf node contributions and render hints

  • Implement concrete string renderer for single file selection

How to test

  • Specify rendering hint in preferences
  • Usage Example: Windows terminal (part of the commit but can be removed if unwanted)

browse

Review checklist

Reminder for reviewers

@vince-fugnitto vince-fugnitto added preferences issues related to preferences proposal feature proposals (potential future features) labels Feb 17, 2022
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.

Functionally, this appears to work well. I've made a number of comments, mainly about naming, as I think the names currently used don't make very clear what problem is being addressed. Specifically, I think RenderHint and associated names could be made more generic and accurate if changed to something like TypeDetails, and BrowseNode and associated names would be clearer as FilepathNode etc.

Another detail of the implementation worth considering is whether to use a ContributionProvider - whose members generally have to be registered at build time - or a registry that permits runtime extension.

@@ -87,6 +87,7 @@ export async function getExternalTerminalSchema(externalTerminalService: Externa
properties: {
'terminal.external.windowsExec': {
type: 'string',
renderHint: { rendering: 'browse' },
Copy link
Contributor

Choose a reason for hiding this comment

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

Regarding most of the names including 'browse,' I think it would makes sense to change to something that refers to something in the semantic field of file / path / folder, for example, in this case:

type: 'string'
typeDetails: {
    isFilepath: true,
    selectionProps: ...OpenFileDialogProps
}

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 renamed the fields to better match the file/file path terminology.

@martin-fleck-at
Copy link
Contributor Author

@colin-grant-work Thank you very much for your detailed review! Unfortunately it took me some time to come back to this but I followed your suggestions which were all great in my opinion. The new change looks much cleaner now (even though it touches more 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 just about there. I have only one substantive comment on the Registry implementation. I traced the performance of the handleDisplayChange method on master and with this code, and despite the increase in overhead picking a renderer for each node, there was only a very small increase in the time taken to fully render (0.1 seconds; 0.5sec vs. 0.4sec previously). A small price to pay for a considerable increase in flexibility. 👍

Comment on lines 17 to 25
import {
createPreferenceProxy,
PreferenceSchema,
PreferenceService,
PreferenceProxy
createPreferenceProxy, PreferenceProxy, PreferenceSchema,
PreferenceService
} from '@theia/core/lib/browser';
import { PreferenceSchemaProvider } from '@theia/core/lib/browser/preferences/preference-contribution';
import { isWindows, isOSX } from '@theia/core/lib/common/os';
import { ExternalTerminalService, ExternalTerminalConfiguration } from '../common/external-terminal';
import { nls } from '@theia/core/lib/common/nls';
import { isOSX, isWindows } from '@theia/core/lib/common/os';
import { inject, injectable, interfaces, postConstruct } from '@theia/core/shared/inversify';
import { ExternalTerminalConfiguration, ExternalTerminalService } from '../common/external-terminal';
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like these changes are probably the work of an auto-formatter of some kind? Since there isn't currently a standard for the repo for the organization of imports (perhaps there should be), it's likely better to turn such auto-formatting off for the time being to limit the diff to relevant changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right, sorry for that! I restored the original formatting which I usually do when I check the commit but seems like this slipped through ;-)

Comment on lines 97 to 103
this.setPreference(selection);
}
}

protected setPreference(uri: URI): void {
this.interactable.value = uri.path.toString();
this.setPreferenceImmediately(uri.path.toString());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: since these classes already have two setPreference methods, I think it would be preferable to just call setPreferenceImmediately directly on line 97 rather than introducing a third method with that prefix.

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 adapted the method to override setPreferenceImmediately instead and now call that directly. You are right that having 3 methods with similar functionality is definitely curios.

Comment on lines 24 to 28
export interface PreferenceNodeRendererCreatorRegistry {
registerPreferenceNodeRendererCreator(registry: PreferenceNodeRendererCreator): Disposable;
unregisterPreferenceNodeRendererCreator(registry: PreferenceNodeRendererCreator): void;
getPreferenceNodeRendererCreator(node: Preference.TreeNode): PreferenceNodeRendererCreator;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The registry should have an Emitter/Event to signal that its contents have changed so that users of registry (PreferenceEditorWidget, in this case) can subscribe and react to changes appropriately.

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 added an event to the interface and implementation but just a simple one for change and no further details (e.g., added or removed creators), I hope that is fine. Since the PreferenceEditorWidget does not directly use that I was not sure how to apply it but I think having it is definitely a valuable contribution.

Copy link
Contributor

Choose a reason for hiding this comment

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

@martin-fleck-at, I believe the place to refer to the event would be in the PreferenceEditorWidget class. It should trigger a total repopulation of the renderers field analagous to what happens when the widget starts up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@colin-grant-work Ah yes, I found it! Somehow I missed that the renderers are cached in the widget so thank you for noticing! I now remove all the cached renderers and re-render the widget as expected. I made a small test commit on a separate branch that toggles the file contribution in case you want to test it: https://github.com/martin-fleck-at/theia/commit/2c4e17b69d9d84f0a4fb586e681da2002187b731

@martin-fleck-at
Copy link
Contributor Author

@colin-grant-work Thank you very much for your detailed review and the rendering performance measurement, that is very interesting and good to know! I already squashed the commits now on top of master but if there is anything else, I'll gladly add it.

- Introduce preference node render registry to support contributions
-- Convert previous renderer factory content to default contribution
-- Let new renderer factory implementation use service
-- Contributions are ranked similar to open handlers

- Add 'typeDetails' as generic optional property to preference schema
-- Contributions may use type details for further properties

- Provide base for leaf node contributions and render hints

- Implement concrete string renderer for single file selection
-- Usage Example: Windows terminal (external and internal)
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.

Looks good to me. I tested with the supplied test commit, and the preference was accurately rerendered. 👍

@JonasHelming JonasHelming merged commit 7b8d3b7 into eclipse-theia:master Mar 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
preferences issues related to preferences proposal feature proposals (potential future features)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Provide support for file selection in preferences
4 participants