added sketch control.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2020-07-20 19:28:27 +02:00
parent 271b06d98a
commit 12a13b869c
7 changed files with 198 additions and 19 deletions

View File

@ -1,5 +1,5 @@
import '../../src/browser/style/index.css';
import { ContainerModule, interfaces } from 'inversify';
import { ContainerModule } from 'inversify';
import { WidgetFactory } from '@theia/core/lib/browser/widget-manager';
import { CommandContribution } from '@theia/core/lib/common/command';
import { bindViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
@ -101,6 +101,7 @@ import { OpenSketchExternal } from './contributions/open-sketch-external';
import { PreferencesContribution as TheiaPreferencesContribution } from '@theia/preferences/lib/browser/preference-contribution';
import { PreferencesContribution } from './theia/preferences/preference-contribution';
import { QuitApp } from './contributions/quit-app';
import { SketchControl } from './contributions/sketch-control-contributions';
const ElementQueries = require('css-element-queries/src/ElementQueries');
@ -111,7 +112,7 @@ MonacoThemingService.register({
json: require('../../src/browser/data/arduino.color-theme.json')
});
export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
export default new ContainerModule((bind, unbind, isBound, rebind) => {
ElementQueries.listen();
ElementQueries.init();
@ -329,4 +330,5 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
Contribution.configure(bind, OpenSketchExternal);
Contribution.configure(bind, EditContributions);
Contribution.configure(bind, QuitApp);
Contribution.configure(bind, SketchControl);
});

View File

@ -1,9 +1,8 @@
import { inject, injectable } from 'inversify';
import { remote } from 'electron';
import { Disposable } from '@theia/languages/lib/browser';
import { MaybePromise } from '@theia/core/lib/common/types';
import { DisposableCollection } from '@theia/core/lib/common/disposable';
import { Widget, ContextMenuRenderer } from '@theia/core/lib/browser';
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
import { ArduinoMenus } from '../menu/arduino-menus';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import { SketchContribution, Sketch, URI, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution';
@ -28,39 +27,42 @@ export class OpenSketch extends SketchContribution {
if (!sketches.length) {
this.openSketch();
} else {
if (!(target instanceof HTMLElement)) {
return;
}
const toDisposeOnClose = new DisposableCollection();
const { parentElement } = target;
if (!parentElement) {
return;
}
const toDisposeOnHide = new DisposableCollection();
this.menuRegistry.registerMenuAction(ArduinoMenus.OPEN_SKETCH__CONTEXT__OPEN_GROUP, {
commandId: OpenSketch.Commands.OPEN_SKETCH.id,
label: 'Open...'
});
toDisposeOnClose.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(OpenSketch.Commands.OPEN_SKETCH)));
toDisposeOnHide.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(OpenSketch.Commands.OPEN_SKETCH)));
for (const sketch of sketches) {
const command = { id: `arduino-open-sketch--${sketch.uri}` };
const handler = { execute: () => this.openSketch(sketch) };
toDisposeOnClose.push(registry.registerCommand(command, handler));
toDisposeOnHide.push(registry.registerCommand(command, handler));
this.menuRegistry.registerMenuAction(ArduinoMenus.OPEN_SKETCH__CONTEXT__RECENT_GROUP, {
commandId: command.id,
label: sketch.name
});
toDisposeOnClose.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command)));
toDisposeOnHide.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command)));
}
const { parentElement } = target;
if (parentElement) {
const options = {
menuPath: ArduinoMenus.OPEN_SKETCH__CONTEXT,
anchor: {
x: parentElement.getBoundingClientRect().left,
y: parentElement.getBoundingClientRect().top + parentElement.offsetHeight
},
onHide: () => toDisposeOnClose.dispose()
onHide: () => toDisposeOnHide.dispose()
}
this.contextMenuRenderer.render(options);
}
}
}
});
}

View File

@ -0,0 +1,138 @@
import { inject, injectable } from 'inversify';
import { EditorManager } from '@theia/editor/lib/browser/editor-manager';
import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribution';
import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
import { WorkspaceCommands } from '@theia/workspace/lib/browser';
import { ContextMenuRenderer } from '@theia/core/lib/browser/context-menu-renderer';
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
import { URI, SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution';
import { ArduinoMenus } from '../menu/arduino-menus';
@injectable()
export class SketchControl extends SketchContribution {
@inject(ApplicationShell)
protected readonly shell: ApplicationShell;
@inject(EditorManager)
protected readonly editorManager: EditorManager;
@inject(MenuModelRegistry)
protected readonly menuRegistry: MenuModelRegistry;
@inject(ContextMenuRenderer)
protected readonly contextMenuRenderer: ContextMenuRenderer;
registerCommands(registry: CommandRegistry): void {
registry.registerCommand(SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR, {
isVisible: widget => this.shell.getWidgets('main').indexOf(widget) !== -1,
execute: async () => {
const toDisposeOnHide = new DisposableCollection();
const sketch = await this.currentSketch();
if (!sketch) {
return;
}
const target = document.getElementById(SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id);
if (!(target instanceof HTMLElement)) {
return;
}
const { parentElement } = target;
if (!parentElement) {
return;
}
const uris = await this.sketchService.getSketchFiles(sketch.uri);
// TODO: order them! The Java IDE orders them by tab index. Use the shell and the editor manager to achieve it.
for (let i = 0; i < uris.length; i++) {
const uri = new URI(uris[i]);
const command = { id: `arduino-focus-file--${uri.toString()}` };
const handler = {
execute: () => {
console.log('bar');
this.editorManager.open(uri, { mode: 'activate' });
console.log('foo');
}
};
toDisposeOnHide.push(registry.registerCommand(command, handler));
this.menuRegistry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__RESOURCES_GROUP, {
commandId: command.id,
label: uri.path.base,
order: `${i}`
});
toDisposeOnHide.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command)));
}
const options = {
menuPath: ArduinoMenus.SKETCH_CONTROL__CONTEXT,
anchor: {
x: parentElement.getBoundingClientRect().left,
y: parentElement.getBoundingClientRect().top + parentElement.offsetHeight
},
onHide: () => toDisposeOnHide.dispose()
}
this.contextMenuRenderer.render(options);
}
});
}
registerMenus(registry: MenuModelRegistry): void {
registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, {
commandId: WorkspaceCommands.NEW_FILE.id,
label: 'New Tab',
order: '0'
});
registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, {
commandId: WorkspaceCommands.FILE_RENAME.id,
label: 'Rename',
order: '1'
});
registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__MAIN_GROUP, {
commandId: WorkspaceCommands.FILE_DELETE.id,
label: 'Delete',
order: '2'
});
registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__NAVIGATION_GROUP, {
commandId: CommonCommands.PREVIOUS_TAB.id,
label: 'Previous Tab',
order: '0'
});
registry.registerMenuAction(ArduinoMenus.SKETCH_CONTROL__CONTEXT__NAVIGATION_GROUP, {
commandId: CommonCommands.NEXT_TAB.id,
label: 'Next Tab',
order: '0'
});
}
registerKeybindings(registry: KeybindingRegistry): void {
registry.registerKeybinding({
command: WorkspaceCommands.NEW_FILE.id,
keybinding: 'CtrlCmd+Shift+N'
});
registry.registerKeybinding({
command: CommonCommands.PREVIOUS_TAB.id,
keybinding: 'CtrlCmd+Alt+Left' // TODO: check why electron does not show the keybindings in the UI.
});
registry.registerKeybinding({
command: CommonCommands.NEXT_TAB.id,
keybinding: 'CtrlCmd+Alt+Right'
});
}
registerToolbarItems(registry: TabBarToolbarRegistry): void {
registry.registerItem({
id: SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id,
command: SketchControl.Commands.OPEN_SKETCH_CONTROL__TOOLBAR.id
});
}
}
export namespace SketchControl {
export namespace Commands {
export const OPEN_SKETCH_CONTROL__TOOLBAR: Command = {
id: 'arduino-open-sketch-control--toolbar',
iconClass: 'fa fa-caret-down'
};
}
}

View File

@ -32,4 +32,10 @@ export namespace ArduinoMenus {
export const OPEN_SKETCH__CONTEXT__RECENT_GROUP = [...OPEN_SKETCH__CONTEXT, '1_recent'];
export const OPEN_SKETCH__CONTEXT__EXAMPLES_GROUP = [...OPEN_SKETCH__CONTEXT, '2_examples'];
// Sketch control (such as `New Tab`, `Rename`, `Delete`, etc.)
export const SKETCH_CONTROL__CONTEXT = ['arduino-sketch-control--context'];
export const SKETCH_CONTROL__CONTEXT__MAIN_GROUP = [...SKETCH_CONTROL__CONTEXT, '0_main'];
export const SKETCH_CONTROL__CONTEXT__NAVIGATION_GROUP = [...SKETCH_CONTROL__CONTEXT, '1_navigation'];
export const SKETCH_CONTROL__CONTEXT__RESOURCES_GROUP = [...SKETCH_CONTROL__CONTEXT, '2_resources'];
}

View File

@ -1,6 +1,7 @@
import { injectable } from 'inversify';
import { CommandRegistry } from '@theia/core/lib/common/command';
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
import { KeybindingRegistry } from '@theia/core/lib/browser/keybinding';
import { WorkspaceCommands, FileMenuContribution } from '@theia/workspace/lib/browser/workspace-commands';
import { WorkspaceFrontendContribution as TheiaWorkspaceFrontendContribution } from '@theia/workspace/lib/browser/workspace-frontend-contribution';
@ -26,6 +27,15 @@ export class WorkspaceFrontendContribution extends TheiaWorkspaceFrontendContrib
registerMenus(_: MenuModelRegistry): void {
}
registerKeybindings(registry: KeybindingRegistry): void {
super.registerKeybindings(registry);
[
WorkspaceCommands.NEW_FILE,
WorkspaceCommands.FILE_RENAME,
WorkspaceCommands.FILE_DELETE
].map(({ id }) => id).forEach(registry.unregisterKeybinding.bind(registry));
}
}
@injectable()

View File

@ -0,0 +1,17 @@
import { injectable } from 'inversify'
import { Keybinding } from '@theia/core/lib/common/keybinding';
import { ElectronMainMenuFactory as TheiaElectronMainMenuFactory } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory';
@injectable()
export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
protected acceleratorFor(keybinding: Keybinding): string {
// TODO: https://github.com/eclipse-theia/theia/issues/8207
return this.keybindingRegistry.resolveKeybinding(keybinding)
.map(binding => this.keybindingRegistry.acceleratorForKeyCode(binding, '+'))
.join('')
.replace('←', 'Left')
.replace('→', 'Right');
}
}

View File

@ -2,9 +2,13 @@ import { ContainerModule } from 'inversify';
import { ElectronMenuContribution as TheiaElectronMenuContribution } from '@theia/core/lib/electron-browser/menu/electron-menu-contribution'
import { ElectronMenuContribution } from './electron-menu-contribution';
import { MainMenuManager } from '../../../common/main-menu-manager';
import { ElectronMainMenuFactory as TheiaElectronMainMenuFactory } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory';
import { ElectronMainMenuFactory } from './electron-main-menu-factory';
export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ElectronMenuContribution).toSelf().inSingletonScope();
bind(MainMenuManager).toService(ElectronMenuContribution);
rebind(TheiaElectronMenuContribution).to(ElectronMenuContribution);
bind(ElectronMainMenuFactory).toSelf().inRequestScope();
rebind(TheiaElectronMainMenuFactory).toService(ElectronMainMenuFactory);
});