Skip to content

Commit

Permalink
feat: refine platform submenu label with vendor ID
Browse files Browse the repository at this point in the history
if there is a name collision

Signed-off-by: Akos Kitta <[email protected]>
  • Loading branch information
Akos Kitta committed Aug 1, 2023
1 parent f24aed6 commit a463091
Showing 1 changed file with 97 additions and 45 deletions.
142 changes: 97 additions & 45 deletions arduino-ide-extension/src/browser/contributions/board-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import {
DisposableCollection,
} from '@theia/core/lib/common/disposable';
import { MenuModelRegistry } from '@theia/core/lib/common/menu/menu-model-registry';
import type { MenuPath } from '@theia/core/lib/common/menu/menu-types';
import { nls } from '@theia/core/lib/common/nls';
import { Deferred } from '@theia/core/lib/common/promise-util';
import { inject, injectable } from '@theia/core/shared/inversify';
import { MainMenuManager } from '../../common/main-menu-manager';
import {
BoardsService,
BoardWithPackage,
createPlatformIdentifier,
getBoardInfo,
InstalledBoardWithPackage,
Expand Down Expand Up @@ -176,54 +178,104 @@ SN: ${SN}
? createPlatformIdentifier(selectedBoard)
: undefined;

// Installed boards
installedBoards.forEach((board, index) => {
const { packageId, packageName, fqbn, name, manuallyInstalled } = board;

let packageLabel =
packageName +
`${
manuallyInstalled
? nls.localize('arduino/board/inSketchbook', ' (in Sketchbook)')
: ''
}`;
if (
selectedBoardPlatformId &&
platformIdentifierEquals(packageId, selectedBoardPlatformId)
) {
packageLabel = `✓ ${packageLabel}`;
// Keys are the vendor IDs
type BoardsPerVendor = Record<string, BoardWithPackage[]>;
// Group boards by their platform names. The keys are the platform names as menu labels.
// If there is a platform name (menu label) collision, refine the menu label with the vendor ID.
const groupedBoards = new Map<string, BoardsPerVendor>();
for (const board of installedBoards) {
const { packageId, packageName } = board;
const { vendorId } = packageId;
let boardsPerPackageName = groupedBoards.get(packageName);
if (!boardsPerPackageName) {
boardsPerPackageName = {} as BoardsPerVendor;
groupedBoards.set(packageName, boardsPerPackageName);
}
// Platform submenu
const platformMenuPath = [
...boardsPackagesGroup,
serializePlatformIdentifier(packageId),
];
// Note: Registering the same submenu twice is a noop. No need to group the boards per platform.
this.menuModelRegistry.registerSubmenu(platformMenuPath, packageLabel, {
order: packageName.toLowerCase(),
});
let boardPerVendor: BoardWithPackage[] | undefined =
boardsPerPackageName[vendorId];
if (!boardPerVendor) {
boardPerVendor = [];
boardsPerPackageName[vendorId] = boardPerVendor;
}
boardPerVendor.push(board);
}

const id = `arduino-select-board--${fqbn}`;
const command = { id };
const handler = {
execute: () =>
this.boardsServiceProvider.updateBoard({ name: name, fqbn: fqbn }),
isToggled: () => fqbn === selectedBoard?.fqbn,
};
// Installed boards
Array.from(groupedBoards.entries()).forEach(
([packageName, boardsPerPackage]) => {
const useVendorSuffix = Object.keys(boardsPerPackage).length > 1;
Object.entries(boardsPerPackage).forEach(([vendorId, boards]) => {
let platformMenuPath: MenuPath | undefined = undefined;
boards.forEach((board, index) => {
const { packageId, fqbn, name, manuallyInstalled } = board;
// create the platform submenu once.
// creating and registering the same submenu twice in Theia is a noop, though.
if (!platformMenuPath) {
let packageLabel =
packageName +
`${
manuallyInstalled
? nls.localize(
'arduino/board/inSketchbook',
' (in Sketchbook)'
)
: ''
}`;
if (
selectedBoardPlatformId &&
platformIdentifierEquals(packageId, selectedBoardPlatformId)
) {
packageLabel = `✓ ${packageLabel}`;
}
if (useVendorSuffix) {
packageLabel += ` (${vendorId})`;
}
// Platform submenu
platformMenuPath = [
...boardsPackagesGroup,
serializePlatformIdentifier(packageId),
];
this.menuModelRegistry.registerSubmenu(
platformMenuPath,
packageLabel,
{
order: packageName.toLowerCase(),
}
);
}

// Board menu
const menuAction = {
commandId: id,
label: name,
order: String(index).padStart(4), // pads with leading zeros for alphanumeric sort where order is 1, 2, 11, and NOT 1, 11, 2
};
this.commandRegistry.registerCommand(command, handler);
this.toDisposeBeforeMenuRebuild.push(
Disposable.create(() => this.commandRegistry.unregisterCommand(command))
);
this.menuModelRegistry.registerMenuAction(platformMenuPath, menuAction);
// Note: we do not dispose the menu actions individually. Calling `unregisterSubmenu` on the parent will wipe the children menu nodes recursively.
});
const id = `arduino-select-board--${fqbn}`;
const command = { id };
const handler = {
execute: () =>
this.boardsServiceProvider.updateBoard({
name: name,
fqbn: fqbn,
}),
isToggled: () => fqbn === selectedBoard?.fqbn,
};

// Board menu
const menuAction = {
commandId: id,
label: name,
order: String(index).padStart(4), // pads with leading zeros for alphanumeric sort where order is 1, 2, 11, and NOT 1, 11, 2
};
this.commandRegistry.registerCommand(command, handler);
this.toDisposeBeforeMenuRebuild.push(
Disposable.create(() =>
this.commandRegistry.unregisterCommand(command)
)
);
this.menuModelRegistry.registerMenuAction(
platformMenuPath,
menuAction
);
// Note: we do not dispose the menu actions individually. Calling `unregisterSubmenu` on the parent will wipe the children menu nodes recursively.
});
});
}
);

// Detected ports
const registerPorts = (
Expand Down

0 comments on commit a463091

Please sign in to comment.