From 20f44fe0728178bc2bb933e220a7a5b91c5d4500 Mon Sep 17 00:00:00 2001 From: Akos Kitta Date: Fri, 17 Jul 2020 16:10:02 +0200 Subject: [PATCH] more refactoring. Signed-off-by: Akos Kitta --- .../src/browser/arduino-commands.ts | 16 - .../browser/arduino-frontend-contribution.tsx | 351 +----------------- .../browser/arduino-ide-frontend-module.ts | 4 + .../browser/boards/boards-auto-installer.ts | 1 - .../boards/boards-details-menu-updater.ts | 2 +- .../boards-widget-frontend-contribution.ts | 2 +- .../src/browser/contributions/contribution.ts | 4 + .../src/browser/contributions/new-sketch.ts | 2 +- .../src/browser/contributions/open-sketch.ts | 2 +- .../src/browser/contributions/save-sketch.ts | 2 +- .../browser/contributions/upload-sketch.ts | 107 ++++++ .../browser/contributions/verify-sketch.ts | 90 +++++ .../library-widget-frontend-contribution.ts | 2 +- .../src/browser/menu/arduino-menus.ts | 14 +- .../menu/browser-arduino-menu-module.ts | 1 - .../monitor/monitor-view-contribution.tsx | 12 +- .../src/browser/style/main.css | 10 +- 17 files changed, 254 insertions(+), 368 deletions(-) create mode 100644 arduino-ide-extension/src/browser/contributions/upload-sketch.ts create mode 100644 arduino-ide-extension/src/browser/contributions/verify-sketch.ts diff --git a/arduino-ide-extension/src/browser/arduino-commands.ts b/arduino-ide-extension/src/browser/arduino-commands.ts index f4f2e671..85181ff0 100644 --- a/arduino-ide-extension/src/browser/arduino-commands.ts +++ b/arduino-ide-extension/src/browser/arduino-commands.ts @@ -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' }; diff --git a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx index 5805df8c..78b01f9a 100644 --- a/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx +++ b/arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx @@ -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 { 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) { - 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: () => , 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 { - 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 { @@ -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 { - 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 { - 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( { diff --git a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts index 0988fae2..255c9a4b 100644 --- a/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts +++ b/arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts @@ -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); }); diff --git a/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts b/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts index cb0c340d..3fd8b2ce 100644 --- a/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts +++ b/arduino-ide-extension/src/browser/boards/boards-auto-installer.ts @@ -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. diff --git a/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts b/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts index c9df896c..663f090a 100644 --- a/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts +++ b/arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts @@ -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 { diff --git a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts index 5d1815ba..623f5cd2 100644 --- a/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts @@ -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 { diff --git a/arduino-ide-extension/src/browser/contributions/contribution.ts b/arduino-ide-extension/src/browser/contributions/contribution.ts index 73c693b0..4b2cc2bf 100644 --- a/arduino-ide-extension/src/browser/contributions/contribution.ts +++ b/arduino-ide-extension/src/browser/contributions/contribution.ts @@ -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 { } diff --git a/arduino-ide-extension/src/browser/contributions/new-sketch.ts b/arduino-ide-extension/src/browser/contributions/new-sketch.ts index 694e950f..d788d2db 100644 --- a/arduino-ide-extension/src/browser/contributions/new-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/new-sketch.ts @@ -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 }); } diff --git a/arduino-ide-extension/src/browser/contributions/open-sketch.ts b/arduino-ide-extension/src/browser/contributions/open-sketch.ts index ced0fbd1..644b0bd9 100644 --- a/arduino-ide-extension/src/browser/contributions/open-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/open-sketch.ts @@ -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 }); } diff --git a/arduino-ide-extension/src/browser/contributions/save-sketch.ts b/arduino-ide-extension/src/browser/contributions/save-sketch.ts index ed4f56d1..a047d5ca 100644 --- a/arduino-ide-extension/src/browser/contributions/save-sketch.ts +++ b/arduino-ide-extension/src/browser/contributions/save-sketch.ts @@ -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 }); } diff --git a/arduino-ide-extension/src/browser/contributions/upload-sketch.ts b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts new file mode 100644 index 00000000..ceac4bdb --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/upload-sketch.ts @@ -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 { + 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' + }; + } +} diff --git a/arduino-ide-extension/src/browser/contributions/verify-sketch.ts b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts new file mode 100644 index 00000000..2cf3643c --- /dev/null +++ b/arduino-ide-extension/src/browser/contributions/verify-sketch.ts @@ -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 { + 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' + }; + } +} diff --git a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts index ed165c7a..17f430ee 100644 --- a/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts +++ b/arduino-ide-extension/src/browser/library/library-widget-frontend-contribution.ts @@ -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 implements FrontendApplicationContribution { diff --git a/arduino-ide-extension/src/browser/menu/arduino-menus.ts b/arduino-ide-extension/src/browser/menu/arduino-menus.ts index d703c0f6..da97f093 100644 --- a/arduino-ide-extension/src/browser/menu/arduino-menus.ts +++ b/arduino-ide-extension/src/browser/menu/arduino-menus.ts @@ -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']; diff --git a/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts b/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts index 11fe0589..48ab2425 100644 --- a/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts +++ b/arduino-ide-extension/src/browser/menu/browser-arduino-menu-module.ts @@ -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); diff --git a/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx b/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx index 343cb796..b911a32f 100644 --- a/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx +++ b/arduino-ide-extension/src/browser/monitor/monitor-view-contribution.tsx @@ -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 { diff --git a/arduino-ide-extension/src/browser/style/main.css b/arduino-ide-extension/src/browser/style/main.css index 702baf7e..8ebb074d 100644 --- a/arduino-ide-extension/src/browser/style/main.css +++ b/arduino-ide-extension/src/browser/style/main.css @@ -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; }