more refactoring.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
Akos Kitta 2020-07-17 16:10:02 +02:00
parent 5abfc2c1aa
commit 20f44fe072
17 changed files with 254 additions and 368 deletions

View File

@ -4,22 +4,6 @@ export namespace ArduinoCommands {
const category = 'Arduino';
export const VERIFY: Command = {
id: 'arduino-verify',
label: 'Verify Sketch'
};
export const VERIFY_TOOLBAR: Command = {
id: 'arduino-verify-toolbar',
};
export const UPLOAD: Command = {
id: 'arduino-upload',
label: 'Upload Sketch'
};
export const UPLOAD_TOOLBAR: Command = {
id: 'arduino-upload-toolbar',
};
export const TOGGLE_COMPILE_FOR_DEBUG: Command = {
id: 'arduino-toggle-compile-for-debug'
};

View File

@ -1,27 +1,24 @@
import * as React from 'react';
import { injectable, inject, postConstruct } from 'inversify';
import URI from '@theia/core/lib/common/uri';
import { EditorWidget } from '@theia/editor/lib/browser/editor-widget';
import { MessageService } from '@theia/core/lib/common/message-service';
import { CommandContribution, CommandRegistry, Command, CommandHandler } from '@theia/core/lib/common/command';
import { CommandContribution, CommandRegistry } from '@theia/core/lib/common/command';
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { BoardsService, BoardsServiceClient, CoreService, SketchesService, ToolOutputServiceClient } from '../common/protocol';
import { ArduinoCommands } from './arduino-commands';
import { BoardsServiceClientImpl } from './boards/boards-service-client-impl';
import { WorkspaceCommands } from '@theia/workspace/lib/browser/workspace-commands';
import { SelectionService, MenuContribution, MenuModelRegistry, MAIN_MENU_BAR, MenuPath } from '@theia/core';
import { SelectionService, MenuContribution, MenuModelRegistry, MAIN_MENU_BAR } from '@theia/core';
import { ArduinoToolbar } from './toolbar/arduino-toolbar';
import { EditorManager, EditorMainMenu } from '@theia/editor/lib/browser';
import {
ContextMenuRenderer, StatusBar, StatusBarAlignment, FrontendApplicationContribution,
FrontendApplication, KeybindingContribution, KeybindingRegistry, OpenerService, open
} from '@theia/core/lib/browser';
import { OpenFileDialogProps, FileDialogService } from '@theia/filesystem/lib/browser/file-dialog';
import { FileSystem, FileStat } from '@theia/filesystem/lib/common';
import { CommonCommands, CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
import { FileDialogService } from '@theia/filesystem/lib/browser/file-dialog';
import { FileSystem } from '@theia/filesystem/lib/common';
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
import { MonacoMenus } from '@theia/monaco/lib/browser/monaco-menu';
import { TerminalMenus } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
import { MaybePromise } from '@theia/core/lib/common/types';
import { BoardsConfigDialog } from './boards/boards-config-dialog';
import { BoardsToolBarItem } from './boards/boards-toolbar-item';
import { BoardsConfig } from './boards/boards-config';
@ -34,7 +31,6 @@ import { OutlineViewContribution } from '@theia/outline-view/lib/browser/outline
import { ProblemContribution } from '@theia/markers/lib/browser/problem/problem-contribution';
import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution';
import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution';
import { FileNavigatorCommands } from '@theia/navigator/lib/browser/navigator-contribution';
import { EditorMode } from './editor-mode';
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
@ -43,19 +39,7 @@ import { ConfigService } from '../common/protocol/config-service';
import { BoardsConfigStore } from './boards/boards-config-store';
import { MainMenuManager } from './menu/main-menu-manager';
import { FileSystemExt } from '../common/protocol/filesystem-ext';
import { OpenSketch } from './contributions/open-sketch';
export namespace ArduinoMenus {
export const SKETCH = [...MAIN_MENU_BAR, '3_sketch'];
export const TOOLS = [...MAIN_MENU_BAR, '4_tools'];
}
export namespace ArduinoToolbarContextMenu {
export const OPEN_SKETCH_PATH: MenuPath = ['arduino-open-sketch-context-menu'];
export const OPEN_GROUP: MenuPath = [...OPEN_SKETCH_PATH, '1_open'];
export const WS_SKETCHES_GROUP: MenuPath = [...OPEN_SKETCH_PATH, '2_sketches'];
export const EXAMPLE_SKETCHES_GROUP: MenuPath = [...OPEN_SKETCH_PATH, '3_examples'];
}
import { ArduinoMenus } from './menu/arduino-menus';
@injectable()
export class ArduinoFrontendContribution implements FrontendApplicationContribution,
@ -155,9 +139,6 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
@inject(FileSystemExt)
protected readonly fileSystemExt: FileSystemExt;
protected application: FrontendApplication;
protected wsSketchCount: number = 0; // TODO: this does not belong here, does it?
@postConstruct()
protected async init(): Promise<void> {
if (!window.navigator.onLine) {
@ -172,12 +153,9 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
}
this.boardsServiceClientImpl.onBoardsConfigChanged(updateStatusBar);
updateStatusBar(this.boardsServiceClientImpl.boardsConfig);
this.registerSketchesInMenu(this.menuRegistry);
}
onStart(app: FrontendApplication): void {
this.application = app;
// Initialize all `pro-mode` widgets. This is a NOOP if in normal mode.
for (const viewContribution of [
this.fileNavigatorContributions,
@ -186,26 +164,13 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
this.problemContribution,
this.scmContribution,
this.siwContribution] as Array<FrontendApplicationContribution>) {
if (viewContribution.initializeLayout) {
viewContribution.initializeLayout(this.application);
viewContribution.initializeLayout(app);
}
}
}
registerToolbarItems(registry: TabBarToolbarRegistry): void {
registry.registerItem({
id: ArduinoCommands.VERIFY.id,
command: ArduinoCommands.VERIFY_TOOLBAR.id,
tooltip: 'Verify',
priority: 1
});
registry.registerItem({
id: ArduinoCommands.UPLOAD.id,
command: ArduinoCommands.UPLOAD_TOOLBAR.id,
tooltip: 'Upload',
priority: 2
});
registry.registerItem({
id: BoardsToolBarItem.TOOLBAR_ID,
render: () => <BoardsToolBarItem
@ -213,7 +178,7 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
commands={this.commandRegistry}
boardsServiceClient={this.boardsServiceClientImpl} />,
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
priority: 6
priority: 7
});
registry.registerItem({
id: 'toggle-serial-monitor',
@ -223,80 +188,21 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
registry.registerItem({
id: ArduinoCommands.TOGGLE_ADVANCED_MODE.id,
command: ArduinoCommands.TOGGLE_ADVANCED_MODE_TOOLBAR.id,
tooltip: 'Toggle Advanced Mode',
text: (this.editorMode.proMode ? '$(toggle-on)' : '$(toggle-off)')
tooltip: this.editorMode.proMode ? 'Switch to Classic Mode' : 'Switch to Advanced Mode',
text: this.editorMode.proMode ? '$(toggle-on)' : '$(toggle-off)'
});
}
registerCommands(registry: CommandRegistry): void {
// TODO: use proper API https://github.com/eclipse-theia/theia/pull/6599
const allHandlers: { [id: string]: CommandHandler[] } = (registry as any)._handlers;
// Make sure to reveal the `Explorer` before executing `New File` and `New Folder`.
for (const command of [WorkspaceCommands.NEW_FILE, WorkspaceCommands.NEW_FOLDER]) {
const { id } = command;
const handlers = allHandlers[id].slice();
registry.unregisterCommand(id);
registry.registerCommand(command);
for (const handler of handlers) {
const wrapper: CommandHandler = {
execute: (...args: any[]) => {
this.fileNavigatorContributions.openView({ reveal: true }).then(() => handler.execute(args));
},
isVisible: (...args: any[]) => {
return handler.isVisible!(args);
},
isEnabled: (args: any[]) => {
return handler.isEnabled!(args);
},
isToggled: (args: any[]) => {
return handler.isToggled!(args);
}
};
if (!handler.isEnabled) {
delete wrapper.isEnabled;
}
if (!handler.isToggled) {
delete wrapper.isToggled;
}
if (!handler.isVisible) {
delete wrapper.isVisible;
}
registry.registerHandler(id, wrapper);
}
}
registry.registerCommand(ArduinoCommands.VERIFY, {
execute: this.verify.bind(this)
});
registry.registerCommand(ArduinoCommands.VERIFY_TOOLBAR, {
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
execute: this.verify.bind(this)
});
registry.registerCommand(ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG, {
execute: () => this.editorMode.toggleCompileForDebug(),
isToggled: () => this.editorMode.compileForDebug
});
registry.registerCommand(ArduinoCommands.UPLOAD, {
execute: this.upload.bind(this)
});
registry.registerCommand(ArduinoCommands.UPLOAD_TOOLBAR, {
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
execute: this.upload.bind(this)
});
registry.registerCommand(ArduinoCommands.OPEN_FILE_NAVIGATOR, {
execute: () => this.doOpenFile()
});
registry.registerCommand(ArduinoCommands.OPEN_SKETCH_FILES, {
execute: async (uri: string) => {
this.openSketchFiles(uri);
}
});
registry.registerCommand(ArduinoCommands.OPEN_BOARDS_DIALOG, {
execute: async () => {
const boardsConfig = await this.boardsConfigDialog.open();
@ -305,7 +211,6 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
}
}
});
registry.registerCommand(ArduinoCommands.TOGGLE_ADVANCED_MODE, {
isToggled: () => this.editorMode.proMode,
execute: () => this.editorMode.toggleProMode()
@ -315,183 +220,41 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
isToggled: () => this.editorMode.proMode,
execute: () => this.editorMode.toggleProMode()
});
registry.registerCommand(ArduinoCommands.OPEN_CLI_CONFIG, {
execute: () => this.configService.getCliConfigFileUri().then(uri => open(this.openerService, new URI(uri)))
});
}
protected async verify() {
const widget = this.getCurrentWidget();
if (widget instanceof EditorWidget) {
await widget.saveable.save();
}
const uri = this.toUri(widget);
if (!uri) {
return;
}
try {
const { boardsConfig } = this.boardsServiceClientImpl;
if (!boardsConfig || !boardsConfig.selectedBoard) {
throw new Error('No boards selected. Please select a board.');
}
if (!boardsConfig.selectedBoard.fqbn) {
throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`);
}
const fqbn = await this.boardsConfigStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn);
this.outputContribution.openView({ reveal: true });
await this.coreService.compile({
sketchUri: uri.toString(),
fqbn,
optimizeForDebug: this.editorMode.compileForDebug
});
} catch (e) {
await this.messageService.error(e.toString());
}
}
protected async upload() {
const widget = this.getCurrentWidget();
if (widget instanceof EditorWidget) {
await widget.saveable.save();
}
const uri = this.toUri(widget);
if (!uri) {
return;
}
const monitorConfig = this.monitorConnection.monitorConfig;
if (monitorConfig) {
await this.monitorConnection.disconnect();
}
try {
const { boardsConfig } = this.boardsServiceClientImpl;
if (!boardsConfig || !boardsConfig.selectedBoard) {
throw new Error('No boards selected. Please select a board.');
}
const { selectedPort } = boardsConfig;
if (!selectedPort) {
throw new Error('No ports selected. Please select a port.');
}
if (!boardsConfig.selectedBoard.fqbn) {
throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`);
}
this.outputContribution.openView({ reveal: true });
const fqbn = await this.boardsConfigStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn);
await this.coreService.upload({
sketchUri: uri.toString(),
fqbn,
port: selectedPort.address,
optimizeForDebug: this.editorMode.compileForDebug
});
} catch (e) {
await this.messageService.error(e.toString());
} finally {
if (monitorConfig) {
await this.monitorConnection.connect(monitorConfig);
}
}
}
registerMenus(registry: MenuModelRegistry) {
if (!this.editorMode.proMode) {
// If are not in pro-mode, we have to disable the context menu for the tabs.
// Such as `Close`, `Close All`, etc.
for (const command of [
CommonCommands.CLOSE_TAB,
CommonCommands.CLOSE_OTHER_TABS,
CommonCommands.CLOSE_RIGHT_TABS,
CommonCommands.CLOSE_ALL_TABS,
CommonCommands.COLLAPSE_PANEL,
CommonCommands.TOGGLE_MAXIMIZED,
FileNavigatorCommands.REVEAL_IN_NAVIGATOR
]) {
if (command) { }
// registry.unregisterMenuAction(command);
const menuId = (menuPath: string[]): string => {
const index = menuPath.length - 1;
const menuId = menuPath[index];
return menuId;
}
// registry.unregisterMenuAction(FileSystemCommands.UPLOAD);
// registry.unregisterMenuAction(FileDownloadCommands.DOWNLOAD);
// registry.unregisterMenuAction(WorkspaceCommands.OPEN_FOLDER);
// registry.unregisterMenuAction(WorkspaceCommands.OPEN_WORKSPACE);
// registry.unregisterMenuAction(WorkspaceCommands.OPEN_RECENT_WORKSPACE);
// registry.unregisterMenuAction(WorkspaceCommands.SAVE_WORKSPACE_AS);
// registry.unregisterMenuAction(WorkspaceCommands.CLOSE);
registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(MonacoMenus.SELECTION));
registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(EditorMainMenu.GO));
registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(TerminalMenus.TERMINAL));
registry.getMenu(MAIN_MENU_BAR).removeNode(this.getMenuId(CommonMenus.VIEW));
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(MonacoMenus.SELECTION));
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(EditorMainMenu.GO));
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(TerminalMenus.TERMINAL));
registry.getMenu(MAIN_MENU_BAR).removeNode(menuId(CommonMenus.VIEW));
}
registry.registerSubmenu(ArduinoMenus.SKETCH, 'Sketch');
registry.registerSubmenu(ArduinoMenus.TOOLS, 'Tools');
registry.registerMenuAction(ArduinoMenus.SKETCH, {
commandId: ArduinoCommands.TOGGLE_COMPILE_FOR_DEBUG.id,
label: 'Optimize for Debugging',
order: '1'
});
registry.registerMenuAction(ArduinoMenus.SKETCH, {
commandId: ArduinoCommands.VERIFY.id,
label: 'Verify/Compile',
order: '2'
});
registry.registerMenuAction(ArduinoMenus.SKETCH, {
commandId: ArduinoCommands.UPLOAD.id,
label: 'Upload',
order: '3'
});
registry.registerSubmenu(ArduinoMenus.TOOLS, 'Tools');
registry.registerMenuAction(CommonMenus.HELP, {
commandId: ArduinoCommands.TOGGLE_ADVANCED_MODE.id,
label: 'Advanced Mode'
});
registry.registerMenuAction([...CommonMenus.FILE_SETTINGS_SUBMENU, '3_settings_cli'], {
commandId: ArduinoCommands.OPEN_CLI_CONFIG.id
});
}
protected getMenuId(menuPath: string[]): string {
const index = menuPath.length - 1;
const menuId = menuPath[index];
return menuId;
}
registerKeybindings(keybindings: KeybindingRegistry): void {
keybindings.unregisterKeybinding('ctrlcmd+n'); // Unregister the keybinding for `New File`, will be used by `New Sketch`. (eclipse-theia/theia#8170)
keybindings.registerKeybinding({
command: ArduinoCommands.VERIFY.id,
keybinding: 'CtrlCmd+Alt+V'
});
keybindings.registerKeybinding({
command: ArduinoCommands.UPLOAD.id,
keybinding: 'CtrlCmd+Alt+U'
});
}
protected async registerSketchesInMenu(registry: MenuModelRegistry): Promise<void> {
const sketches = await this.sketchService.getSketches();
this.wsSketchCount = sketches.length;
sketches.forEach(sketch => {
const command: Command = {
id: 'openSketch' + sketch.name
}
this.commandRegistry.registerCommand(command, {
execute: () => this.commandRegistry.executeCommand(OpenSketch.Commands.OPEN_SKETCH.id, sketch)
});
registry.registerMenuAction(ArduinoToolbarContextMenu.WS_SKETCHES_GROUP, {
commandId: command.id,
label: sketch.name
});
});
}
protected async openSketchFiles(uri: string): Promise<void> {
@ -501,82 +264,6 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
}
}
/**
* Opens a file after prompting the `Open File` dialog. Shows a warning message if
* - the file to open does not exist,
* - it was not a file, but a directory, or
* - the file does not pass validation.
*
* Otherwise, resolves to the URI of the file.
*/
protected async doOpenFile(): Promise<void> {
const props: OpenFileDialogProps = {
title: WorkspaceCommands.OPEN_FILE.dialogLabel,
canSelectFolders: false,
canSelectFiles: true
};
const [rootStat] = await this.workspaceService.roots;
const destinationFileUri = await this.fileDialogService.showOpenDialog(props, rootStat);
if (!destinationFileUri) {
return;
}
const destinationFile = await this.fileSystem.getFileStat(destinationFileUri.toString());
if (!destinationFile) {
this.messageService.warn(`File does not exist: ${this.fileSystem.getFsPath(destinationFileUri.toString())}`)
return;
}
if (destinationFile.isDirectory) {
this.messageService.warn('Please select a sketch file, not a directory.')
return;
}
const message = await this.validate(destinationFile);
if (message) {
this.messageService.warn(message);
return;
}
this.workspaceService.open(destinationFileUri.parent);
}
protected getCurrentWidget(): EditorWidget | undefined {
let widget = this.editorManager.currentEditor;
if (!widget) {
const visibleWidgets = this.editorManager.all.filter(w => w.isVisible);
if (visibleWidgets.length > 0) {
widget = visibleWidgets[0];
}
}
return widget;
}
/**
* Returns `undefined` if the `file` is valid. Otherwise, returns with the validation error message.
*/
protected validate(file: FileStat): MaybePromise<string | undefined> {
const uri = new URI(file.uri);
const path = uri.path;
const { name, ext, dir } = path;
if (ext !== '.ino') {
return "Only sketches with '.ino' extension can be opened.";
}
if (name !== dir.name) {
return `The file "${name}${ext}" needs to be inside a sketch folder named "${name}".`;
}
return undefined;
}
private toUri(arg: any): URI | undefined {
if (arg instanceof URI) {
return arg;
}
if (typeof arg === 'string') {
return new URI(arg);
}
if (arg instanceof EditorWidget) {
return arg.editor.uri;
}
return undefined;
}
registerColors(colors: ColorRegistry): void {
colors.register(
{

View File

@ -85,6 +85,8 @@ import { OpenSketch } from './contributions/open-sketch';
import { CloseSketch } from './contributions/close-sketch';
import { SaveAsSketch } from './contributions/save-as-sketch';
import { SaveSketch } from './contributions/save-sketch';
import { VerifySketch } from './contributions/verify-sketch';
import { UploadSketch } from './contributions/upload-sketch';
const ElementQueries = require('css-element-queries/src/ElementQueries');
@ -310,4 +312,6 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
Contribution.configure(bind, CloseSketch);
Contribution.configure(bind, SaveSketch);
Contribution.configure(bind, SaveAsSketch);
Contribution.configure(bind, VerifySketch);
Contribution.configure(bind, UploadSketch);
});

View File

@ -7,7 +7,6 @@ import { BoardsListWidgetFrontendContribution } from './boards-widget-frontend-c
import { InstallationProgressDialog } from '../components/progress-dialog';
import { BoardsConfig } from './boards-config';
/**
* Listens on `BoardsConfig.Config` changes, if a board is selected which does not
* have the corresponding core installed, it proposes the user to install the core.

View File

@ -5,9 +5,9 @@ import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposa
import { BoardsServiceClientImpl } from './boards-service-client-impl';
import { Board, ConfigOption } from '../../common/protocol';
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
import { ArduinoMenus } from '../arduino-frontend-contribution';
import { BoardsConfigStore } from './boards-config-store';
import { MainMenuManager } from '../menu/main-menu-manager';
import { ArduinoMenus } from '../menu/arduino-menus';
@injectable()
export class BoardsDetailsMenuUpdater implements FrontendApplicationContribution {

View File

@ -1,9 +1,9 @@
import { injectable } from 'inversify';
import { MenuModelRegistry } from '@theia/core';
import { BoardsListWidget } from './boards-list-widget';
import { ArduinoMenus } from '../arduino-frontend-contribution';
import { BoardsPackage } from '../../common/protocol/boards-service';
import { ListWidgetFrontendContribution } from '../components/component-list/list-widget-frontend-contribution';
import { ArduinoMenus } from '../menu/arduino-menus';
@injectable()
export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution<BoardsPackage> {

View File

@ -10,6 +10,7 @@ import { KeybindingRegistry, KeybindingContribution } from '@theia/core/lib/brow
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { Command, CommandRegistry, CommandContribution, CommandService } from '@theia/core/lib/common/command';
import { SketchesService, ConfigService, FileSystemExt, Sketch } from '../../common/protocol';
import { EditorMode } from '../editor-mode';
export { Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry, URI, Sketch };
@ -28,6 +29,9 @@ export abstract class Contribution implements CommandContribution, MenuContribut
@inject(WorkspaceService)
protected readonly workspaceService: WorkspaceService;
@inject(EditorMode)
protected readonly editorMode: EditorMode;
registerCommands(registry: CommandRegistry): void {
}

View File

@ -36,7 +36,7 @@ export class NewSketch extends SketchContribution {
id: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id,
command: NewSketch.Commands.NEW_SKETCH__TOOLBAR.id,
tooltip: 'New',
priority: 4
priority: 3
});
}

View File

@ -84,7 +84,7 @@ export class OpenSketch extends SketchContribution {
id: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id,
command: OpenSketch.Commands.OPEN_SKETCH__TOOLBAR.id,
tooltip: 'Open',
priority: 5
priority: 4
});
}

View File

@ -37,7 +37,7 @@ export class SaveSketch extends SketchContribution {
id: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id,
command: SaveSketch.Commands.SAVE_SKETCH__TOOLBAR.id,
tooltip: 'Save',
priority: 6
priority: 5
});
}

View File

@ -0,0 +1,107 @@
import { inject, injectable } from 'inversify';
import { CoreService } from '../../common/protocol';
import { MonitorConnection } from '../monitor/monitor-connection';
import { BoardsConfigStore } from '../boards/boards-config-store';
import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl';
import { ArduinoMenus } from '../menu/arduino-menus';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution';
@injectable()
export class UploadSketch extends SketchContribution {
@inject(CoreService)
protected readonly coreService: CoreService;
@inject(MonitorConnection)
protected readonly monitorConnection: MonitorConnection;
@inject(BoardsConfigStore)
protected readonly boardsConfigStore: BoardsConfigStore;
@inject(BoardsServiceClientImpl)
protected readonly boardsServiceClientImpl: BoardsServiceClientImpl;
registerCommands(registry: CommandRegistry): void {
registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH, {
execute: () => this.uploadSketch()
});
registry.registerCommand(UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR, {
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
execute: () => registry.executeCommand(UploadSketch.Commands.UPLOAD_SKETCH.id)
});
}
registerMenus(registry: MenuModelRegistry): void {
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
commandId: UploadSketch.Commands.UPLOAD_SKETCH.id,
label: 'Verify',
order: '0'
});
}
registerKeybindings(registry: KeybindingRegistry): void {
registry.registerKeybinding({
command: UploadSketch.Commands.UPLOAD_SKETCH.id,
keybinding: 'CtrlCmd+U'
});
}
registerToolbarItems(registry: TabBarToolbarRegistry): void {
registry.registerItem({
id: UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR.id,
command: UploadSketch.Commands.UPLOAD_SKETCH_TOOLBAR.id,
tooltip: 'Upload',
priority: 1
});
}
async uploadSketch(): Promise<void> {
const sketch = await this.getCurrentSketch();
if (!sketch) {
return;
}
const monitorConfig = this.monitorConnection.monitorConfig;
if (monitorConfig) {
await this.monitorConnection.disconnect();
}
try {
const { boardsConfig } = this.boardsServiceClientImpl;
if (!boardsConfig || !boardsConfig.selectedBoard) {
throw new Error('No boards selected. Please select a board.');
}
const { selectedPort } = boardsConfig;
if (!selectedPort) {
throw new Error('No ports selected. Please select a port.');
}
if (!boardsConfig.selectedBoard.fqbn) {
throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`);
}
const fqbn = await this.boardsConfigStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn);
await this.coreService.upload({
sketchUri: sketch.uri,
fqbn,
port: selectedPort.address,
optimizeForDebug: this.editorMode.compileForDebug
});
} catch (e) {
await this.messageService.error(e.toString());
} finally {
if (monitorConfig) {
await this.monitorConnection.connect(monitorConfig);
}
}
}
}
export namespace UploadSketch {
export namespace Commands {
export const UPLOAD_SKETCH: Command = {
id: 'arduino-upload-sketch'
};
export const UPLOAD_SKETCH_TOOLBAR: Command = {
id: 'arduino-upload-sketch--toolbar'
};
}
}

View File

@ -0,0 +1,90 @@
import { inject, injectable } from 'inversify';
import { ArduinoMenus } from '../menu/arduino-menus';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import { BoardsConfigStore } from '../boards/boards-config-store';
import { BoardsServiceClientImpl } from '../boards/boards-service-client-impl';
import { SketchContribution, Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry } from './contribution';
import { CoreService } from '../../common/protocol';
@injectable()
export class VerifySketch extends SketchContribution {
@inject(CoreService)
protected readonly coreService: CoreService;
@inject(BoardsConfigStore)
protected readonly boardsConfigStore: BoardsConfigStore;
@inject(BoardsServiceClientImpl)
protected readonly boardsServiceClientImpl: BoardsServiceClientImpl;
registerCommands(registry: CommandRegistry): void {
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH, {
execute: () => this.verifySketch()
});
registry.registerCommand(VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR, {
isVisible: widget => ArduinoToolbar.is(widget) && widget.side === 'left',
execute: () => registry.executeCommand(VerifySketch.Commands.VERIFY_SKETCH.id)
});
}
registerMenus(registry: MenuModelRegistry): void {
registry.registerMenuAction(ArduinoMenus.SKETCH__MAIN_GROUP, {
commandId: VerifySketch.Commands.VERIFY_SKETCH.id,
label: 'Verify/Compile',
order: '0'
});
}
registerKeybindings(registry: KeybindingRegistry): void {
registry.registerKeybinding({
command: VerifySketch.Commands.VERIFY_SKETCH.id,
keybinding: 'CtrlCmd+R'
});
}
registerToolbarItems(registry: TabBarToolbarRegistry): void {
registry.registerItem({
id: VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR.id,
command: VerifySketch.Commands.VERIFY_SKETCH_TOOLBAR.id,
tooltip: 'Verify',
priority: 0
});
}
async verifySketch(): Promise<void> {
const sketch = await this.getCurrentSketch();
if (!sketch) {
return;
}
try {
const { boardsConfig } = this.boardsServiceClientImpl;
if (!boardsConfig || !boardsConfig.selectedBoard) {
throw new Error('No boards selected. Please select a board.');
}
if (!boardsConfig.selectedBoard.fqbn) {
throw new Error(`No core is installed for the '${boardsConfig.selectedBoard.name}' board. Please install the core.`);
}
const fqbn = await this.boardsConfigStore.appendConfigToFqbn(boardsConfig.selectedBoard.fqbn);
await this.coreService.compile({
sketchUri: sketch.uri,
fqbn,
optimizeForDebug: this.editorMode.compileForDebug
});
} catch (e) {
await this.messageService.error(e.toString());
}
}
}
export namespace VerifySketch {
export namespace Commands {
export const VERIFY_SKETCH: Command = {
id: 'arduino-verify-sketch'
};
export const VERIFY_SKETCH_TOOLBAR: Command = {
id: 'arduino-verify-sketch--toolbar'
};
}
}

View File

@ -3,7 +3,7 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser/fronten
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
import { MenuModelRegistry } from '@theia/core';
import { LibraryListWidget } from './library-list-widget';
import { ArduinoMenus } from '../arduino-frontend-contribution';
import { ArduinoMenus } from '../menu/arduino-menus';
@injectable()
export class LibraryListWidgetFrontendContribution extends AbstractViewContribution<LibraryListWidget> implements FrontendApplicationContribution {

View File

@ -1,12 +1,24 @@
import { MAIN_MENU_BAR } from '@theia/core/lib/common/menu';
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
export namespace ArduinoMenus {
// Main menu
// File
export const FILE__SKETCH_GROUP = [...CommonMenus.FILE, '0_sketch'];
export const FILE__PRINT_GROUP = [...CommonMenus.FILE, '1_print'];
// `Open...` context menu
// Sketch
export const SKETCH = [...MAIN_MENU_BAR, '3_sketch'];
export const SKETCH__MAIN_GROUP = [...SKETCH, '0_main'];
export const SKETCH__UTILS_GROUP = [...SKETCH, '1_utils'];
// Tools
export const TOOLS = [...MAIN_MENU_BAR, '4_tools'];
export const TOOLS__MAIN_GROUP = [...TOOLS, '0_main'];
// Context menu
// Open
export const OPEN_SKETCH__CONTEXT = ['arduino-open-sketch--context'];
export const OPEN_SKETCH__CONTEXT__OPEN_GROUP = [...OPEN_SKETCH__CONTEXT, '0_open'];
export const OPEN_SKETCH__CONTEXT__RECENT_GROUP = [...OPEN_SKETCH__CONTEXT, '1_recent'];

View File

@ -5,7 +5,6 @@ import { MainMenuManager } from './main-menu-manager';
import { ArduinoMenuContribution } from './arduino-menu-contribution';
import { ArduinoBrowserMainMenuFactory } from './arduino-browser-main-menu-factory';
export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ArduinoBrowserMainMenuFactory).toSelf().inSingletonScope();
bind(MainMenuManager).toService(ArduinoBrowserMainMenuFactory);

View File

@ -1,12 +1,12 @@
import * as React from 'react';
import { injectable, inject } from "inversify";
import { AbstractViewContribution } from "@theia/core/lib/browser";
import { MonitorWidget } from "./monitor-widget";
import { MenuModelRegistry, Command, CommandRegistry } from "@theia/core";
import { ArduinoMenus } from "../arduino-frontend-contribution";
import { TabBarToolbarContribution, TabBarToolbarRegistry } from "@theia/core/lib/browser/shell/tab-bar-toolbar";
import { injectable, inject } from 'inversify';
import { AbstractViewContribution } from '@theia/core/lib/browser';
import { MonitorWidget } from './monitor-widget';
import { MenuModelRegistry, Command, CommandRegistry } from '@theia/core';
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
import { ArduinoToolbar } from '../toolbar/arduino-toolbar';
import { MonitorModel } from './monitor-model';
import { ArduinoMenus } from '../menu/arduino-menus';
export namespace SerialMonitor {
export namespace Commands {

View File

@ -28,8 +28,8 @@
background: var(--theia-button-hoverBackground);
}
.arduino-verify,
.arduino-upload {
.arduino-verify-sketch--toolbar,
.arduino-upload-sketch--toolbar {
border-radius: 12px;
}
@ -43,17 +43,17 @@
mask-size: 800%;
}
.arduino-save-sketch-icon {
.arduino-save-sketch--toolbar-icon {
-webkit-mask-position: 59px -4px;
mask-position: 59px -4px;
}
.arduino-verify-icon {
.arduino-verify-sketch--toolbar-icon {
-webkit-mask-position: 188px -4px;
mask-position: 188px -4px;
}
.arduino-upload-icon {
.arduino-upload-sketch--toolbar-icon {
-webkit-mask-position: 156px -4px;
mask-position: 156px -4px;
}