Skip to content

Commit d54a699

Browse files
author
Akos Kitta
committed
[experimental]: Introduced the Boards Control.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
1 parent 12f2aa3 commit d54a699

File tree

10 files changed

+375
-69
lines changed

10 files changed

+375
-69
lines changed

arduino-ide-extension/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@
3636
"@theia/workspace": "next",
3737
"@types/dateformat": "^3.0.1",
3838
"@types/deepmerge": "^2.2.0",
39-
"@types/js-yaml": "^3.12.2",
4039
"@types/glob": "^5.0.35",
4140
"@types/google-protobuf": "^3.7.1",
41+
"@types/js-yaml": "^3.12.2",
4242
"@types/lodash.debounce": "^4.0.6",
4343
"@types/ps-tree": "^1.1.0",
4444
"@types/react-select": "^3.0.0",
@@ -47,6 +47,7 @@
4747
"css-element-queries": "^1.2.0",
4848
"dateformat": "^3.0.3",
4949
"deepmerge": "^4.2.2",
50+
"fuzzy": "^0.1.3",
5051
"glob": "^7.1.6",
5152
"google-protobuf": "^3.11.0",
5253
"lodash.debounce": "^4.0.8",
@@ -105,6 +106,9 @@
105106
{
106107
"frontend": "lib/browser/menu/browser-arduino-menu-module",
107108
"frontendElectron": "lib/electron-browser/menu/electron-arduino-menu-module"
109+
},
110+
{
111+
"frontend": "lib/browser/boards/quick-open/boards-quick-open-module"
108112
}
109113
]
110114
}

arduino-ide-extension/src/browser/boards/boards-config-quick-open-service.ts

Lines changed: 0 additions & 43 deletions
This file was deleted.

arduino-ide-extension/src/browser/boards/boards-details-menu-updater.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,25 @@ export class BoardsDetailsMenuUpdater implements FrontendApplicationContribution
4545
const boardsConfigMenuPath = [...ArduinoMenus.TOOLS, 'z_boardsConfig']; // `z_` is for ordering.
4646
for (const { label, option, values } of configOptions.sort(ConfigOption.LABEL_COMPARATOR)) {
4747
const menuPath = [...boardsConfigMenuPath, `${option}`];
48-
const commands = new Map<string, Disposable>()
48+
const commands = new Map<string, Disposable & { label: string }>()
4949
for (const value of values) {
5050
const id = `${fqbn}-${option}--${value.value}`;
51-
const command = { id, label: value.label };
51+
const command = { id };
5252
const selectedValue = value.value;
5353
const handler = {
5454
execute: () => this.boardsConfigStore.setSelected({ fqbn, option, selectedValue }),
5555
isToggled: () => value.selected
5656
};
57-
commands.set(id, this.commandRegistry.registerCommand(command, handler));
57+
commands.set(id, Object.assign(this.commandRegistry.registerCommand(command, handler), { label: value.label }));
5858
}
5959
this.menuRegistry.registerSubmenu(menuPath, label);
6060
this.toDisposeOnBoardChange.pushAll([
6161
...commands.values(),
6262
Disposable.create(() => this.unregisterSubmenu(menuPath)), // We cannot dispose submenu entries: https://github.com/eclipse-theia/theia/issues/7299
6363
...Array.from(commands.keys()).map((commandId, index) => {
64-
this.menuRegistry.registerMenuAction(menuPath, { commandId, order: String(index) })
65-
return Disposable.create(() => this.menuRegistry.unregisterMenuAction(commandId))
64+
const { label } = commands.get(commandId)!;
65+
this.menuRegistry.registerMenuAction(menuPath, { commandId, order: String(index), label });
66+
return Disposable.create(() => this.menuRegistry.unregisterMenuAction(commandId));
6667
})
6768
]);
6869
}

arduino-ide-extension/src/browser/boards/boards-service-client-impl.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { FrontendApplicationContribution } from '@theia/core/lib/browser/fronten
77
import { RecursiveRequired } from '../../common/types';
88
import { BoardsServiceClient, AttachedBoardsChangeEvent, BoardInstalledEvent, Board, Port, BoardUninstalledEvent } from '../../common/protocol';
99
import { BoardsConfig } from './boards-config';
10+
import { naturalCompare } from '../../common/utils';
1011

1112
@injectable()
1213
export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApplicationContribution {
@@ -262,10 +263,10 @@ export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApp
262263
});
263264
}
264265

265-
const sortedAvailableBoards = availableBoards.sort(AvailableBoard.COMPARATOR);
266+
const sortedAvailableBoards = availableBoards.sort(AvailableBoard.compare);
266267
let hasChanged = sortedAvailableBoards.length !== currentAvailableBoards.length;
267268
for (let i = 0; !hasChanged && i < sortedAvailableBoards.length; i++) {
268-
hasChanged = AvailableBoard.COMPARATOR(sortedAvailableBoards[i], currentAvailableBoards[i]) !== 0;
269+
hasChanged = AvailableBoard.compare(sortedAvailableBoards[i], currentAvailableBoards[i]) !== 0;
269270
}
270271
if (hasChanged) {
271272
this._availableBoards = sortedAvailableBoards;
@@ -312,9 +313,10 @@ export class BoardsServiceClientImpl implements BoardsServiceClient, FrontendApp
312313
}
313314

314315
/**
315-
* Representation of a ready-to-use board, configured by the user. Not all of the available boards are
316-
* necessarily recognized by the CLI (e.g.: it is a 3rd party board) or correctly configured but ready for `verify`.
317-
* If it has the selected board and a associated port, it can be used for `upload`.
316+
* Representation of a ready-to-use board, either the user has configured it or was automatically recognized by the CLI.
317+
* An available board was not necessarily recognized by the CLI (e.g.: it is a 3rd party board) or correctly configured but ready for `verify`.
318+
* If it has the selected board and a associated port, it can be used for `upload`. We render an available board for the user
319+
* when it has the `port` set.
318320
*/
319321
export interface AvailableBoard extends Board {
320322
readonly state: AvailableBoard.State;
@@ -339,17 +341,27 @@ export namespace AvailableBoard {
339341
'incomplete'
340342
}
341343

342-
export function isWithPort(board: AvailableBoard): board is AvailableBoard & { port: Port } {
344+
export function is(board: any): board is AvailableBoard {
345+
return Board.is(board) && 'state' in board;
346+
}
347+
348+
export function hasPort(board: AvailableBoard): board is AvailableBoard & { port: Port } {
343349
return !!board.port;
344350
}
345351

346-
export const COMPARATOR = (left: AvailableBoard, right: AvailableBoard) => {
347-
let result = left.name.localeCompare(right.name);
352+
export const compare = (left: AvailableBoard, right: AvailableBoard) => {
353+
if (left.selected && !right.selected) {
354+
return -1;
355+
}
356+
if (right.selected && !left.selected) {
357+
return 1;
358+
}
359+
let result = naturalCompare(left.name, right.name);
348360
if (result !== 0) {
349361
return result;
350362
}
351363
if (left.fqbn && right.fqbn) {
352-
result = left.name.localeCompare(right.name);
364+
result = naturalCompare(left.fqbn, right.fqbn);
353365
if (result !== 0) {
354366
return result;
355367
}

arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ export class BoardsToolBarItem extends React.Component<BoardsToolBarItem.Props,
151151
</div>
152152
<BoardsDropDown
153153
coords={coords}
154-
items={availableBoards.filter(AvailableBoard.isWithPort).map(board => ({
154+
items={availableBoards.filter(AvailableBoard.hasPort).map(board => ({
155155
...board,
156156
onClick: () => {
157157
if (board.state === AvailableBoard.State.incomplete) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { ContainerModule } from 'inversify';
2+
import { ILogger } from '@theia/core/lib/common/logger';
3+
import { CommandContribution } from '@theia/core/lib/common/command';
4+
import { QuickOpenContribution } from '@theia/core/lib/browser/quick-open';
5+
import { KeybindingContribution } from '@theia/core/lib/browser/keybinding';
6+
import { BoardsQuickOpenService } from './boards-quick-open-service';
7+
8+
export default new ContainerModule(bind => {
9+
bind(BoardsQuickOpenService).toSelf().inSingletonScope();
10+
bind(CommandContribution).toService(BoardsQuickOpenService);
11+
bind(KeybindingContribution).toService(BoardsQuickOpenService);
12+
bind(QuickOpenContribution).toService(BoardsQuickOpenService);
13+
bind(ILogger).toDynamicValue(({ container }) => container.get<ILogger>(ILogger).child('boards-quick-open'))
14+
.inSingletonScope()
15+
.whenTargetNamed('boards-quick-open');
16+
});

0 commit comments

Comments
 (0)