How to remove some UI elements

Hello.

I’ve search this site for answers, but suggested solutions are not clear for me and I can’t figure it out.
I need to remove some UI elements from Theia (remove marked in orange).
Main top bar,
Git extension and button,
Settings,
Lower left branch change

If the answer is in this thread: Remove some widgets from the IDE like explorer, search etc
could someone please write a step-by-step guide :slight_smile:
I have a really hard time figuring out how Theia works.

Best Regards
Maciej

You need to unbind that widget.

I’m trying to do with an extension. Following the tutorial for “hello world”
This is not working. All the UI elements are still there.

import { injectable, inject } from “inversify”;
import { CommandContribution, CommandRegistry, MenuContribution, MenuModelRegistry, MessageService } from “@theia/core/lib/common”;
import { CommonMenus, CommonCommands } from “@theia/core/lib/browser”;
import { FrontendApplicationContribution, FrontendApplication } from ‘@theia/core/lib/browser’;
// import { FrontendApplicationContribution } from ‘@theia/core/lib/browser’;
import { MaybePromise } from ‘@theia/core/lib/common/types’;
import { Widget } from ‘@theia/core/lib/browser/widgets’;

export const TestCommand = {
id: ‘Test.command’,
label: “Say Hello”
};

@injectable()
export class TestCommandContribution implements CommandContribution {

constructor(
    @inject(MessageService) private readonly messageService: MessageService,
) { }

registerCommands(registry: CommandRegistry): void {
    registry.registerCommand(TestCommand, {
        execute: () => this.messageService.info('Hello World!')
    });
}

}

@injectable()
export class TestMenuContribution implements MenuContribution {

registerMenus(menus: MenuModelRegistry): void {
    menus.registerMenuAction(CommonMenus.EDIT_FIND, {
        commandId: TestCommand.id,
        label: TestCommand.label
    });
    menus.unregisterMenuAction(CommonCommands.ABOUT_COMMAND);
}

}

@injectable()
export class ExampleFrontendContribution implements FrontendApplicationContribution {
/*
* Called after the application shell has been attached in case there is no previous workbench layout state.
* Should return a promise if it runs asynchronously.
*/
onDidInitializeLayout(app: FrontendApplication): MaybePromise {
// Remove unused widgets
app.shell.widgets.forEach((widget: Widget) => {

        widget.dispose();
    });
}

}

@maciejchmura thank you for the discussion and welcome to the community :wave:

In order to provide any customizations to the framework, and modify any default behavior, a custom extension would be required. From the extension you can extend classes which provide functionality, and override any methods as necessary.

For example, the top-panel is contributed by the ApplicationShell. For a simple solution, you can simply extend the ApplicationShell and hide the top-panel if you no longer require it.

I have a working example if you’d like a reference:

Here is where we extend the default ApplicationShell and hide the top-menu:

And here is where we use dependency injection (inversify.js to rebind the old class to the new one:

You’ll end up in a state like the following:

You can use this example to support more advanced use-cases if you want :slight_smile: Please also note that we should have native support for toggling the top-panel soon: https://github.com/eclipse-theia/theia/pull/9830

1 Like

WOW!
Thank you @vince-fugnitto :smiley: it works!
I removed the top bar.
I will follow your guide to make more UI adjustments.
After some feedback with my PO, I also need to remove completely the whole left section and move the debug panel to the bottom space.


Hopefully it can be made in the similar manner in the ApplicationShell .

Thank you :slight_smile:
Thanks for your time and for creating the repo :slight_smile:

Update.
I managed to remove the left panel with navigation buttons and the right panel with outline.

this.topPanel.hide(); // attempt to hide the top-panel.
this.leftPanelHandler.container.close() // closes left panel
this.rightPanelHandler.container.close() // closes outline view

Maybe someone will find it helpful. :slight_smile:

Now I’m trying to move the debugger to the bottom panel.

@maciejchmura for the debug-view, you’ll likely want to extend DebugFrontendApplicationContribution and provide a update to the defaultWidgetOptions when creating the widget (area: 'bottom'):

Note that this will not prevent users from moving the view around but if your use-case is to show the debug view at the bottom then it should be sufficient. Else, you can think about extending openView as to only ever open widgets in areas you want, and not the sidepanels.

@vince-fugnitto hmmm
My code should look something like this?

I have this error: Expected 0 arguments, but got 1.ts(2554)

@maciejchmura It doesn’t seem to be possible to extend the DebugFrontendApplicationContribution constructor, as it accepts no arguments. However, going the other direction (overriding openView) is not possible as well, as AbstractViewContribution is not a component but inherited by different other component, making it impossible to rebind on a global scope.

I assume the best idea would be to change the desired widget area in-place in the application shell. Overriding that should be fairly easy:

@msujew Maybe we are thinking about something similar :slight_smile:
I was trying to add a widget to the bottom panel.
Can it be done like this?

Need to provide a correct ID for the debug widget?

You should be able to use the widget id debug, but I’m not quite sure whether this works as expected (I didn’t test it yet)

I would recommend overriding the addWidget method to have a better grip on the actual panel where widgets are placed.

@msujew Looks like .addWidget() can’t accept a string.

this.bottomPanel.addWidget('debug')

Argument of type 'string' is not assignable to parameter of type 'Widget'.ts(2345)

I’m trying to grab the widgets, but I got an empty array.

@injectable()
export class CustomApplicationShell extends ApplicationShell {

    @postConstruct()
    protected init(): void {
        this.topPanel.hide(); // attempt to hide the top-panel.
        this.leftPanelHandler.container.close() // closes left panel
        this.rightPanelHandler.container.close() // closes outline view

        console.log(this.bottomPanel)
        this.bottomPanel.setHidden(false)
        // this.bottomPanel.addWidget('debug')
        const widgets = this.getWidgets('left');
        console.log(widgets)
    }
}

I’m not sure what do you mean by overriding the addWidget method.

Oh, right, I forgot that the shell doesn’t operate on IDs. Also, at post construct time, widgets aren’t probably loaded yet.

You can override the addWidget method like this:

@injectable()
export class CustomApplicationShell extends ApplicationShell {
    async addWidget(widget: Widget, options: Readonly<ApplicationShell.WidgetOptions> = {}): Promise<void> {
        // your code here
    }
}

@msujew
hmmmm
When I add the code you suggested, my build fails. This is how my code for extension looks like.

I’ve commented out the changes responsible for hiding the top, left and right panel.

@maciejchmura In what way does your build fail? Any logs that you can provide? I can’t see something obviously wrong with that code.

I have this:

@maciejchmura This seems to be unrelated to your changes. For some reason your TypeScript setup wants to recompile the Theia sources. This shouldn’t be necessary. Your tsconfig.json file should usually exclude node_modules directories.

@vince-fugnitto @msujew thank you for all your help :smiley:
As for the tsconfig -> I moved the code to different repo and it started working.

As for the moving of debug window, I still don’t know how to do it, but I will leave it for now on the left.