8000 Renamed the application to Arduino IDE by kittaakos · Pull Request #1 · arduino/arduino-ide · GitHub
[go: up one dir, main page]

Skip to content

Renamed the application to Arduino IDE #1

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

Merged
merged 11 commits into from
Feb 11, 2021
Prev Previous commit
ATL-938: Added menu group categories.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
  • Loading branch information
Akos Kitta committed Feb 10, 2021
commit fb584b2f8378cac17c7eca4f772da1cc749cca73
81 changes: 52 additions & 29 deletions arduino-ide-extension/src/browser/contributions/board-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { inject, injectable } from 'inversify';
import { remote } from 'electron';
import { MenuModelRegistry } from '@theia/core/lib/common/menu';
import { DisposableCollection, Disposable } from '@theia/core/lib/common/disposable';
import { firstToUpperCase } from '../../common/utils';
import { BoardsConfig } from '../boards/boards-config';
import { MainMenuManager } from '../../common/main-menu-manager';
import { BoardsListWidget } from '../boards/boards-list-widget';
import { NotificationCenter } from '../notification-center';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import { ArduinoMenus, unregisterSubmenu } from '../menu/arduino-menus';
import { ArduinoMenus, PlaceholderMenuNode, unregisterSubmenu } from '../menu/arduino-menus';
import { BoardsService, InstalledBoardWithPackage, AvailablePorts, Port } from '../../common/protocol';
import { SketchContribution, Command, CommandRegistry } from './contribution';

Expand Down Expand Up @@ -150,39 +151,61 @@ PID: ${PID}`;
}

// Installed ports
for (const address of Object.keys(availablePorts)) {
if (!!availablePorts[address]) {
const [port, boards] = availablePorts[address];
if (!boards.length) {
boards.push({
name: ''
});
}
for (const { name, fqbn } of boards) {
const id = `arduino-select-port--${address}${fqbn ? `--${fqbn}` : ''}`;
const command = { id };
const handler = {
execute: () => {
if (!Port.equals(port, this.boardsServiceProvider.boardsConfig.selectedPort)) {
this.boardsServiceProvider.boardsConfig = {
selectedBoard: this.boardsServiceProvider.boardsConfig.selectedBoard,
selectedPort: port
const registerPorts = (ports: AvailablePorts) => {
const addresses = Object.keys(ports);
if (!addresses.length) {
return;
}

// Register placeholder for protocol
const [port] = ports[addresses[0]];
const protocol = port.protocol;
const menuPath = [...portsSubmenuPath, protocol];
const placeholder = new PlaceholderMenuNode(menuPath, `${firstToUpperCase(port.protocol)} ports`);
this.menuModelRegistry.registerMenuNode(menuPath, placeholder);
this.toDisposeBeforeMenuRebuild.push(Disposable.create(() => this.menuModelRegistry.unregisterMenuNode(placeholder.id)));

for (const address of addresses) {
if (!!ports[address]) {
const [port, boards] = ports[address];
if (!boards.length) {
boards.push({
name: ''
});
}
for (const { name, fqbn } of boards) {
const id = `arduino-select-port--${address}${fqbn ? `--${fqbn}` : ''}`;
const command = { id };
const handler = {
execute: () => {
if (!Port.equals(port, this.boardsServiceProvider.boardsConfig.selectedPort)) {
this.boardsServiceProvider.boardsConfig = {
selectedBoard: this.boardsServiceProvider.boardsConfig.selectedBoard,
selectedPort: port
}
}
}
},
isToggled: () => Port.equals(port, this.boardsServiceProvider.boardsConfig.selectedPort)
};
const menuAction = {
commandId: id,
label: `${address}${name ? ` (${name})` : ''}`
};
this.commandRegistry.registerCommand(command, handler);
this.toDisposeBeforeMenuRebuild.push(Disposable.create(() => this.commandRegistry.unregisterCommand(command)));
this.menuModelRegistry.registerMenuAction(portsSubmenuPath, menuAction);
},
isToggled: () => Port.equals(port, this.boardsServiceProvider.boardsConfig.selectedPort)
};
const label = `${address}${name ? ` (${name})` : ''}`;
const menuAction = {
commandId: id,
label,
order: `1${label}` // `1` comes after the placeholder which has order `0`
};
this.commandRegistry.registerCommand(command, handler);
this.toDisposeBeforeMenuRebuild.push(Disposable.create(() => this.command 10000 Registry.unregisterCommand(command)));
this.menuModelRegistry.registerMenuAction(menuPath, menuAction);
}
}
}
}

const { serial, network, unknown } = AvailablePorts.groupByProtocol(availablePorts);
registerPorts(serial);
registerPorts(network);
registerPorts(unknown);

this.mainMenuManager.update();
}

Expand Down
71 changes: 45 additions & 26 deletions arduino-ide-extension/src/browser/contributions/examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { inject, injectable, postConstruct } from 'inversify';
import { MenuPath, CompositeMenuNode } from '@theia/core/lib/common/menu';
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
import { OpenSketch } from './open-sketch';
import { ArduinoMenus } from '../menu/arduino-menus';
import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus';
import { MainMenuManager } from '../../common/main-menu-manager';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
import { ExamplesService, ExampleContainer } from '../../common/protocol/examples-service';
import { SketchContribution, CommandRegistry, MenuModelRegistry } from './contribution';
import { NotificationCenter } from '../notification-center';
import { Board } from '../../common/protocol';

@injectable()
export abstract class Examples extends SketchContribution {
Expand All @@ -32,10 +33,10 @@ export abstract class Examples extends SketchContribution {

@postConstruct()
init(): void {
this.boardsServiceClient.onBoardsConfigChanged(({ selectedBoard }) => this.handleBoardChanged(selectedBoard?.fqbn));
this.boardsServiceClient.onBoardsConfigChanged(({ selectedBoard }) => this.handleBoardChanged(selectedBoard));
}

protected handleBoardChanged(fqbn: string | undefined): void {
protected handleBoardChanged(board: Board | undefined): void {
// NOOP
}

Expand All @@ -58,27 +59,33 @@ export abstract class Examples extends SketchContribution {
}

registerRecursively(
exampleContainer: ExampleContainer,
exampleContainerOrPlaceholder: ExampleContainer | string,
menuPath: MenuPath,
pushToDispose: DisposableCollection = new DisposableCollection()): void {

const { label, sketches, children } = exampleContainer;
const submenuPath = [...menuPath, label];
this.menuRegistry.registerSubmenu(submenuPath, label);
children.forEach(child => this.registerRecursively(child, submenuPath, pushToDispose));
for (const sketch of sketches) {
const { uri } = sketch;
const commandId = `arduino-open-example-${submenuPath.join(':')}--${uri}`;
const command = { id: commandId };
const handler = {
execute: async () => {
const sketch = await this.sketchService.cloneExample(uri);
this.commandService.executeCommand(OpenSketch.Commands.OPEN_SKETCH.id, sketch);
}
};
pushToDispose.push(this.commandRegistry.registerCommand(command, handler));
this.menuRegistry.registerMenuAction(submenuPath, { commandId, label: sketch.name });
pushToDispose.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command)));
if (typeof exampleContainerOrPlaceholder === 'string') {
const placeholder = new PlaceholderMenuNode(menuPath, exampleContainerOrPlaceholder);
this.menuRegistry.registerMenuNode(menuPath, placeholder);
pushToDispose.push(Disposable.create(() => this.menuRegistry.unregisterMenuNode(placeholder.id)));
} else {
const { label, sketches, children } = exampleContainerOrPlaceholder;
const submenuPath = [...menuPath, label];
this.menuRegistry.registerSubmenu(submenuPath, label);
children.forEach(child => this.registerRecursively(child, submenuPath, pushToDispose));
for (const sketch of sketches) {
const { uri } = sketch;
const commandId = `arduino-open-example-${submenuPath.join(':')}--${uri}`;
const command = { id: commandId };
const handler = {
execute: async () => {
const sketch = await this.sketchService.cloneExample(uri);
this.commandService.executeCommand(OpenSketch.Commands.OPEN_SKETCH.id, sketch);
}
};
pushToDispose.push(this.commandRegistry.registerCommand(command, handler));
this.menuRegistry.registerMenuAction(submenuPath, { commandId, label: sketch.name });
pushToDispose.push(Disposable.create(() => this.menuRegistry.unregisterMenuAction(command)));
}
}
}

Expand All @@ -101,10 +108,12 @@ export class BuiltInExamples extends Examples {
return;
}
this.toDispose.dispose();
for (const container of exampleContainers) {
for (const container of ['Built-in examples', ...exampleContainers]) {
this.registerRecursively(container, ArduinoMenus.EXAMPLES__BUILT_IN_GROUP, this.toDispose);
}
this.menuManager.update();
// TODO: remove
console.log(typeof this.menuRegistry);
}

}
Expand All @@ -123,17 +132,27 @@ export class LibraryExamples extends Examples {
this.notificationCenter.onLibraryUninstalled(() => this.register());
}

protected handleBoardChanged(fqbn: string | undefined): void {
this.register(fqbn);
protected handleBoardChanged(board: Board | undefined): void {
this.register(board);
}

protected async register(fqbn: string | undefined = this.boardsServiceClient.boardsConfig.selectedBoard?.fqbn) {
protected async register(board: Board | undefined = this.boardsServiceClient.boardsConfig.selectedBoard) {
return this.queue.add(async () => {
this.toDispose.dispose();
if (!fqbn) {
if (!board || !board.fqbn) {
return;
}
const { fqbn, name } = board;
const { user, current, any } = await this.examplesService.installed({ fqbn });
if (user.length) {
(user as any).unshift('Examples from Custom Libraries');
}
if (current.length) {
(current as any).unshift(`Examples for ${name}`);
}
if (any.length) {
(any as any).unshift('Examples for any board');
}
for (const container of user) {
this.registerRecursively(container, ArduinoMenus.EXAMPLES__USER_LIBS_GROUP, this.toDispose);
}
Expand Down
32 changes: 24 additions & 8 deletions arduino-ide-extension/src/browser/contributions/include-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
import { EditorManager } from '@theia/editor/lib/browser';
import { MenuModelRegistry, MenuPath } from '@theia/core/lib/common/menu';
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
import { ArduinoMenus } from '../menu/arduino-menus';
import { LibraryPackage, LibraryLocation, LibraryService } from '../../common/protocol';
import { ArduinoMenus, PlaceholderMenuNode } from '../menu/arduino-menus';
import { LibraryPackage, LibraryService } from '../../common/protocol';
import { MainMenuManager } from '../../common/main-menu-manager';
import { LibraryListWidget } from '../library/library-list-widget';
import { BoardsServiceProvider } from '../boards/boards-service-provider';
Expand Down Expand Up @@ -84,19 +84,35 @@ export class IncludeLibrary extends SketchContribution {
// `Arduino libraries`
const packageMenuPath = [...includeLibMenuPath, '2_arduino'];
const userMenuPath = [...includeLibMenuPath, '3_contributed'];
for (const library of libraries) {
this.toDispose.push(this.registerLibrary(library, library.location === LibraryLocation.USER ? userMenuPath : packageMenuPath));
const { user, rest } = LibraryPackage.groupByLocation(libraries);
if (rest.length) {
(rest as any).unshift('Arduino libraries');
}
if (user.length) {
(user as any).unshift('Contributed libraries');
}

for (const library of user) {
this.toDispose.push(this.registerLibrary(library, userMenuPath));
}
for (const library of rest) {
this.toDispose.push(this.registerLibrary(library, packageMenuPath));
}

this.mainMenuManager.update();
});
}

protected registerLibrary(library: LibraryPackage, menuPath: MenuPath): Disposable {
const commandId = `arduino-include-library--${library.name}:${library.author}`;
protected registerLibrary(libraryOrPlaceholder: LibraryPackage | string, menuPath: MenuPath): Disposable {
if (typeof libraryOrPlaceholder === 'string') {
const placeholder = new PlaceholderMenuNode(menuPath, libraryOrPlaceholder);
this.menuRegistry.registerMenuNode(menuPath, placeholder);
return Disposable.create(() => this.menuRegistry.unregisterMenuNode(placeholder.id));
}
const commandId = `arduino-include-library--${libraryOrPlaceholder.name}:${libraryOrPlaceholder.author}`;
const command = { id: commandId };
const handler = { execute: () => this.commandRegistry.executeCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY.id, library) };
const menuAction = { commandId, label: library.name };
const handler = { execute: () => this.commandRegistry.executeCommand(IncludeLibrary.Commands.INCLUDE_LIBRARY.id, libraryOrPlaceholder) };
const menuAction = { commandId, label: libraryOrPlaceholder.name };
this.menuRegistry.registerMenuAction(menuPath, menuAction);
return new DisposableCollection(
this.commandRegistry.registerCommand(command, handler),
Expand Down
23 changes: 22 additions & 1 deletion arduino-ide-extension/src/browser/menu/arduino-menus.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isOSX } from '@theia/core/lib/common/os';
import { CommonMenus } from '@theia/core/lib/browser/common-frontend-contribution';
import { MAIN_MENU_BAR, MenuModelRegistry, MenuNode } from '@theia/core/lib/common/menu';
import { MAIN_MENU_BAR, MenuModelRegistry, MenuNode, MenuPath, SubMenuOptions } from '@theia/core/lib/common/menu';

export namespace ArduinoMenus {

Expand Down Expand Up @@ -99,3 +99,24 @@ export function unregisterSubmenu(menuPath: string[], menuRegistry: MenuModelReg
}
(parent.children as Array<MenuNode>).splice(index, 1);
}

/**
* Special menu node that is not backed by any commands and is always disabled.
*/
export class PlaceholderMenuNode implements MenuNode {

constructor(protected readonly menuPath: MenuPath, readonly label: string, protected options: SubMenuOptions = { order: '0' }) { }

get icon(): string | undefined {
return this.options?.iconClass;
}

get sortString(): string {
return this.options?.order || this.label;
}

get id(): string {
return [...this.menuPath, 'placeholder'].join('-');
}

}
19 changes: 19 additions & 0 deletions arduino-ide-extension/src/common/protocol/boards-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@ import { Installable } from './installable';
import { ArduinoComponent } from './arduino-component';

export type AvailablePorts = Record<string, [Port, Array<Board>]>;
export namespace AvailablePorts {
export function groupByProtocol(availablePorts: AvailablePorts): { serial: AvailablePorts, network: AvailablePorts, unknown: AvailablePorts } {
const serial: AvailablePorts = {};
const network: AvailablePorts = {};
const unknown: AvailablePorts = {};
for (const key of Object.keys(availablePorts)) {
const [port, boards] = availablePorts[key];
const { protocol } = port;
if (protocol === 'serial') {
serial[key] = [port, boards];
} else if (protocol === 'network') {
network[key] = [port, boards];
} else {
unknown[key] = [port, boards];
}
}
return { serial, network, unknown };
}
}

export interface AttachedBoardsChangeEvent {
readonly oldState: Readonly<{ boards: Board[], ports: Port[] }>;
Expand Down
13 changes: 13 additions & 0 deletions arduino-ide-extension/src/common/protocol/library-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,17 @@ export namespace LibraryPackage {
return left.name === right.name && left.author === right.author;
}

export function groupByLocation(packages: LibraryPackage[]): { user: LibraryPackage[], rest: LibraryPackage[] } {
const user: LibraryPackage[] = [];
const rest: LibraryPackage[] = [];
for (const pkg of packages) {
if (pkg.location === LibraryLocation.USER) {
user.push(pkg);
} else {
rest.push(pkg);
}
}
return { user, rest };
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { injectable } from 'inversify'
import { remote } from 'electron';
import { Keybinding } from '@theia/core/lib/common/keybinding';
import { ElectronMainMenuFactory as TheiaElectronMainMenuFactory } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory';
import { ArduinoMenus } from '../../../browser/menu/arduino-menus';
import { CompositeMenuNode } from '@theia/core/lib/common/menu';
import { ElectronMainMenuFactory as TheiaElectronMainMenuFactory, ElectronMenuOptions } from '@theia/core/lib/electron-browser/menu/electron-main-menu-factory';
import { ArduinoMenus, PlaceholderMenuNode } from '../../../browser/menu/arduino-menus';

@injectable()
export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
Expand Down Expand Up @@ -42,4 +43,15 @@ export class ElectronMainMenuFactory extends TheiaElectronMainMenuFactory {
return { label, submenu };
}

protected handleDefault(menuNode: CompositeMenuNode, args: any[] = [], options?: ElectronMenuOptions): Electron.MenuItemConstructorOptions[] {
if (menuNode instanceof PlaceholderMenuNode) {
return [{
label: menuNode.label,
enabled: false,
visible: true
}];
}
return [];
}

}
0