mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-10 02:48:33 +00:00
Rework listing of discovered ports (#614)
* Removed Protocol type * Reworked function that groups ports by protocol * Remove useless protocol check in Port sameAs function * Reworked port selection menu ordering Now ports are shown in this order: 1. Serial with recognized boards 2. Serial with unrecognized boards 3. Network with recognized boards 4. Network with unrecognized boards 5. Other protocols with recognized boards 6. Other protocols with unrecognized boards * Fix ports shown multiple times in menu * Reworked board selection dropdown ordering Ordering is now: 1. Serial with recognized boards 2. Serial with guessed boards 3. Serial with incomplete boards 4. Network with recognized boards 5. Other protocols with recognized boards * Localize some strings * Fix bug selecting board in boards selector dropdown * Reworked board selection dialog ordering * Fix Tools > Port menu not refreshing * Move Select other board button to bottom of Board selector dropdown and change its style * Updated arduino-cli to 0.20.0 and generated protocol files
This commit is contained in:
@@ -10,8 +10,12 @@ import {
|
||||
BoardWithPackage,
|
||||
} from '../../common/protocol/boards-service';
|
||||
import { NotificationCenter } from '../notification-center';
|
||||
import { BoardsServiceProvider } from './boards-service-provider';
|
||||
import {
|
||||
AvailableBoard,
|
||||
BoardsServiceProvider,
|
||||
} from './boards-service-provider';
|
||||
import { nls } from '@theia/core/lib/browser/nls';
|
||||
import { naturalCompare } from '../../common/utils';
|
||||
|
||||
export namespace BoardsConfig {
|
||||
export interface Config {
|
||||
@@ -184,11 +188,50 @@ export class BoardsConfig extends React.Component<
|
||||
.filter(notEmpty);
|
||||
}
|
||||
|
||||
protected get availableBoards(): AvailableBoard[] {
|
||||
return this.props.boardsServiceProvider.availableBoards;
|
||||
}
|
||||
|
||||
protected queryPorts = async (
|
||||
availablePorts: MaybePromise<Port[]> = this.availablePorts
|
||||
) => {
|
||||
const ports = await availablePorts;
|
||||
return { knownPorts: ports.sort(Port.compare) };
|
||||
// Available ports must be sorted in this order:
|
||||
// 1. Serial with recognized boards
|
||||
// 2. Serial with guessed boards
|
||||
// 3. Serial with incomplete boards
|
||||
// 4. Network with recognized boards
|
||||
// 5. Other protocols with recognized boards
|
||||
const ports = (await availablePorts).sort((left: Port, right: Port) => {
|
||||
if (left.protocol === 'serial' && right.protocol !== 'serial') {
|
||||
return -1;
|
||||
} else if (left.protocol !== 'serial' && right.protocol === 'serial') {
|
||||
return 1;
|
||||
} else if (left.protocol === 'network' && right.protocol !== 'network') {
|
||||
return -1;
|
||||
} else if (left.protocol !== 'network' && right.protocol === 'network') {
|
||||
return 1;
|
||||
} else if (left.protocol === right.protocol) {
|
||||
// We show ports, including those that have guessed
|
||||
// or unrecognized boards, so we must sort those too.
|
||||
const leftBoard = this.availableBoards.find((board) =>
|
||||
Port.sameAs(board.port, left)
|
||||
);
|
||||
const rightBoard = this.availableBoards.find((board) =>
|
||||
Port.sameAs(board.port, right)
|
||||
);
|
||||
if (leftBoard && !rightBoard) {
|
||||
return -1;
|
||||
} else if (!leftBoard && rightBoard) {
|
||||
return 1;
|
||||
} else if (leftBoard?.state! < rightBoard?.state!) {
|
||||
return -1;
|
||||
} else if (leftBoard?.state! > rightBoard?.state!) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return naturalCompare(left.address, right.address);
|
||||
});
|
||||
return { knownPorts: ports };
|
||||
};
|
||||
|
||||
protected toggleFilterPorts = () => {
|
||||
@@ -281,8 +324,24 @@ export class BoardsConfig extends React.Component<
|
||||
}
|
||||
|
||||
protected renderPorts(): React.ReactNode {
|
||||
const filter = this.state.showAllPorts ? () => true : Port.isBoardPort;
|
||||
const ports = this.state.knownPorts.filter(filter);
|
||||
let ports = [] as Port[];
|
||||
if (this.state.showAllPorts) {
|
||||
ports = this.state.knownPorts;
|
||||
} else {
|
||||
ports = this.state.knownPorts.filter((port) => {
|
||||
if (port.protocol === 'serial') {
|
||||
return true;
|
||||
}
|
||||
// All other ports with different protocol are
|
||||
// only shown if there is a recognized board
|
||||
// connected
|
||||
for (const board of this.availableBoards) {
|
||||
if (board.port?.address === port.address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return !ports.length ? (
|
||||
<div className="loading noselect">No ports discovered</div>
|
||||
) : (
|
||||
|
||||
@@ -42,6 +42,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
protected readonly onAvailableBoardsChangedEmitter = new Emitter<
|
||||
AvailableBoard[]
|
||||
>();
|
||||
protected readonly onAvailablePortsChangedEmitter = new Emitter<Port[]>();
|
||||
|
||||
/**
|
||||
* Used for the auto-reconnecting. Sometimes, the attached board gets disconnected after uploading something to it.
|
||||
@@ -67,8 +68,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
* This event is also emitted when the board package for the currently selected board was uninstalled.
|
||||
*/
|
||||
readonly onBoardsConfigChanged = this.onBoardsConfigChangedEmitter.event;
|
||||
readonly onAvailableBoardsChanged =
|
||||
this.onAvailableBoardsChangedEmitter.event;
|
||||
readonly onAvailableBoardsChanged = this.onAvailableBoardsChangedEmitter.event;
|
||||
readonly onAvailablePortsChanged = this.onAvailablePortsChangedEmitter.event;
|
||||
|
||||
onStart(): void {
|
||||
this.notificationCenter.onAttachedBoardsChanged(
|
||||
@@ -88,6 +89,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
]).then(([attachedBoards, availablePorts]) => {
|
||||
this._attachedBoards = attachedBoards;
|
||||
this._availablePorts = availablePorts;
|
||||
this.onAvailablePortsChangedEmitter.fire(this._availablePorts);
|
||||
this.reconcileAvailableBoards().then(() => this.tryReconnect());
|
||||
});
|
||||
}
|
||||
@@ -102,6 +104,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
this._attachedBoards = event.newState.boards;
|
||||
this._availablePorts = event.newState.ports;
|
||||
this.onAvailablePortsChangedEmitter.fire(this._availablePorts);
|
||||
this.reconcileAvailableBoards().then(() => this.tryReconnect());
|
||||
}
|
||||
|
||||
@@ -180,8 +183,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const selectedAvailableBoard = AvailableBoard.is(selectedBoard)
|
||||
? selectedBoard
|
||||
: this._availableBoards.find((availableBoard) =>
|
||||
Board.sameAs(availableBoard, selectedBoard)
|
||||
);
|
||||
Board.sameAs(availableBoard, selectedBoard)
|
||||
);
|
||||
if (
|
||||
selectedAvailableBoard &&
|
||||
selectedAvailableBoard.selected &&
|
||||
@@ -358,14 +361,14 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const timeoutTask =
|
||||
!!timeout && timeout > 0
|
||||
? new Promise<void>((_, reject) =>
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${timeout} ms.`)),
|
||||
timeout
|
||||
)
|
||||
setTimeout(
|
||||
() => reject(new Error(`Timeout after ${timeout} ms.`)),
|
||||
timeout
|
||||
)
|
||||
)
|
||||
: new Promise<void>(() => {
|
||||
/* never */
|
||||
});
|
||||
/* never */
|
||||
});
|
||||
const waitUntilTask = new Promise<void>((resolve) => {
|
||||
let candidate = find(what, this.availableBoards);
|
||||
if (candidate) {
|
||||
@@ -384,7 +387,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
}
|
||||
|
||||
protected async reconcileAvailableBoards(): Promise<void> {
|
||||
const attachedBoards = this._attachedBoards;
|
||||
const availablePorts = this._availablePorts;
|
||||
// Unset the port on the user's config, if it is not available anymore.
|
||||
if (
|
||||
@@ -402,51 +404,64 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
const boardsConfig = this.boardsConfig;
|
||||
const currentAvailableBoards = this._availableBoards;
|
||||
const availableBoards: AvailableBoard[] = [];
|
||||
const availableBoardPorts = availablePorts.filter(Port.isBoardPort);
|
||||
const attachedSerialBoards = attachedBoards.filter(({ port }) => !!port);
|
||||
const attachedBoards = this._attachedBoards.filter(({ port }) => !!port);
|
||||
const availableBoardPorts = availablePorts.filter((port) => {
|
||||
if (port.protocol === "serial") {
|
||||
// We always show all serial ports, even if there
|
||||
// is no recognized board connected to it
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const boardPort of availableBoardPorts) {
|
||||
let state = AvailableBoard.State.incomplete; // Initial pessimism.
|
||||
let board = attachedSerialBoards.find(({ port }) =>
|
||||
Port.sameAs(boardPort, port)
|
||||
);
|
||||
if (board) {
|
||||
state = AvailableBoard.State.recognized;
|
||||
} else {
|
||||
// If the selected board is not recognized because it is a 3rd party board: https://github.com/arduino/arduino-cli/issues/623
|
||||
// We still want to show it without the red X in the boards toolbar: https://github.com/arduino/arduino-pro-ide/issues/198#issuecomment-599355836
|
||||
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(
|
||||
boardPort
|
||||
);
|
||||
if (lastSelectedBoard) {
|
||||
board = {
|
||||
...lastSelectedBoard,
|
||||
port: boardPort,
|
||||
};
|
||||
state = AvailableBoard.State.guessed;
|
||||
// All other ports with different protocol are
|
||||
// only shown if there is a recognized board
|
||||
// connected
|
||||
for (const board of attachedBoards) {
|
||||
if (board.port?.address === port.address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!board) {
|
||||
availableBoards.push({
|
||||
return false;
|
||||
});
|
||||
|
||||
for (const boardPort of availableBoardPorts) {
|
||||
let board = attachedBoards.find(({ port }) => Port.sameAs(boardPort, port));
|
||||
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(boardPort);
|
||||
|
||||
let availableBoard = {} as AvailableBoard;
|
||||
if (board) {
|
||||
availableBoard = {
|
||||
...board,
|
||||
state: AvailableBoard.State.recognized,
|
||||
selected: BoardsConfig.Config.sameAs(boardsConfig, board),
|
||||
port: boardPort,
|
||||
};
|
||||
} else if (lastSelectedBoard) {
|
||||
// If the selected board is not recognized because it is a 3rd party board: https://github.com/arduino/arduino-cli/issues/623
|
||||
// We still want to show it without the red X in the boards toolbar: https://github.com/arduino/arduino-pro-ide/issues/198#issuecomment-599355836
|
||||
availableBoard = {
|
||||
...lastSelectedBoard,
|
||||
state: AvailableBoard.State.guessed,
|
||||
selected: BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard),
|
||||
port: boardPort,
|
||||
};
|
||||
} else {
|
||||
availableBoard = {
|
||||
name: nls.localize('arduino/common/unknown', 'Unknown'),
|
||||
port: boardPort,
|
||||
state,
|
||||
});
|
||||
} else {
|
||||
const selected = BoardsConfig.Config.sameAs(boardsConfig, board);
|
||||
availableBoards.push({
|
||||
...board,
|
||||
state,
|
||||
selected,
|
||||
port: boardPort,
|
||||
});
|
||||
state: AvailableBoard.State.incomplete,
|
||||
};
|
||||
}
|
||||
availableBoards.push(availableBoard);
|
||||
}
|
||||
|
||||
if (
|
||||
boardsConfig.selectedBoard &&
|
||||
!availableBoards.some(({ selected }) => selected)
|
||||
) {
|
||||
if (boardsConfig.selectedBoard && !availableBoards.some(({ selected }) => selected)) {
|
||||
// If the selected board has the same port of an unknown board
|
||||
// that is already in availableBoards we might get a duplicate port.
|
||||
// So we remove the one already in the array and add the selected one.
|
||||
const found = availableBoards.findIndex(board => board.port?.address === boardsConfig.selectedPort?.address);
|
||||
if (found >= 0) {
|
||||
availableBoards.splice(found, 1);
|
||||
}
|
||||
availableBoards.push({
|
||||
...boardsConfig.selectedBoard,
|
||||
port: boardsConfig.selectedPort,
|
||||
@@ -455,28 +470,20 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
});
|
||||
}
|
||||
|
||||
const sortedAvailableBoards = availableBoards.sort(AvailableBoard.compare);
|
||||
let hasChanged =
|
||||
sortedAvailableBoards.length !== currentAvailableBoards.length;
|
||||
for (let i = 0; !hasChanged && i < sortedAvailableBoards.length; i++) {
|
||||
hasChanged =
|
||||
AvailableBoard.compare(
|
||||
sortedAvailableBoards[i],
|
||||
currentAvailableBoards[i]
|
||||
) !== 0;
|
||||
availableBoards.sort(AvailableBoard.compare);
|
||||
|
||||
let hasChanged = availableBoards.length !== currentAvailableBoards.length;
|
||||
for (let i = 0; !hasChanged && i < availableBoards.length; i++) {
|
||||
const [left, right] = [availableBoards[i], currentAvailableBoards[i]];
|
||||
hasChanged = !!AvailableBoard.compare(left, right) || left.selected !== right.selected;
|
||||
}
|
||||
if (hasChanged) {
|
||||
this._availableBoards = sortedAvailableBoards;
|
||||
this._availableBoards = availableBoards;
|
||||
this.onAvailableBoardsChangedEmitter.fire(this._availableBoards);
|
||||
}
|
||||
}
|
||||
|
||||
protected async getLastSelectedBoardOnPort(
|
||||
port: Port | string | undefined
|
||||
): Promise<Board | undefined> {
|
||||
if (!port) {
|
||||
return undefined;
|
||||
}
|
||||
protected async getLastSelectedBoardOnPort(port: Port): Promise<Board | undefined> {
|
||||
const key = this.getLastSelectedBoardOnPortKey(port);
|
||||
return this.getData<Board>(key);
|
||||
}
|
||||
@@ -497,11 +504,8 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
|
||||
]);
|
||||
}
|
||||
|
||||
protected getLastSelectedBoardOnPortKey(port: Port | string): string {
|
||||
// TODO: we lose the port's `protocol` info (`serial`, `network`, etc.) here if the `port` is a `string`.
|
||||
return `last-selected-board-on-port:${
|
||||
typeof port === 'string' ? port : Port.toString(port)
|
||||
}`;
|
||||
protected getLastSelectedBoardOnPortKey(port: Port): string {
|
||||
return `last-selected-board-on-port:${Port.toString(port)}`;
|
||||
}
|
||||
|
||||
protected async loadState(): Promise<void> {
|
||||
@@ -585,35 +589,30 @@ export namespace AvailableBoard {
|
||||
return !!board.port;
|
||||
}
|
||||
|
||||
// Available boards must be sorted in this order:
|
||||
// 1. Serial with recognized boards
|
||||
// 2. Serial with guessed boards
|
||||
// 3. Serial with incomplete boards
|
||||
// 4. Network with recognized boards
|
||||
// 5. Other protocols with recognized boards
|
||||
export const compare = (left: AvailableBoard, right: AvailableBoard) => {
|
||||
if (left.selected && !right.selected) {
|
||||
if (left.port?.protocol === "serial" && right.port?.protocol !== "serial") {
|
||||
return -1;
|
||||
}
|
||||
if (right.selected && !left.selected) {
|
||||
} else if (left.port?.protocol !== "serial" && right.port?.protocol === "serial") {
|
||||
return 1;
|
||||
}
|
||||
let result = naturalCompare(left.name, right.name);
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
}
|
||||
if (left.fqbn && right.fqbn) {
|
||||
result = naturalCompare(left.fqbn, right.fqbn);
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
} else if (left.port?.protocol === "network" && right.port?.protocol !== "network") {
|
||||
return -1;
|
||||
} else if (left.port?.protocol !== "network" && right.port?.protocol === "network") {
|
||||
return 1;
|
||||
} else if (left.port?.protocol === right.port?.protocol) {
|
||||
// We show all ports, including those that have guessed
|
||||
// or unrecognized boards, so we must sort those too.
|
||||
if (left.state < right.state) {
|
||||
return -1;
|
||||
} else if (left.state > right.state) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (left.port && right.port) {
|
||||
result = Port.compare(left.port, right.port);
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (!!left.selected && !right.selected) {
|
||||
return -1;
|
||||
}
|
||||
if (!!right.selected && !left.selected) {
|
||||
return 1;
|
||||
}
|
||||
return left.state - right.state;
|
||||
};
|
||||
return naturalCompare(left.port?.address!, right.port?.address!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
if (coords === 'hidden') {
|
||||
return '';
|
||||
}
|
||||
const footerLabel = nls.localize(
|
||||
'arduino/board/openBoardsConfig',
|
||||
'Select other board and port…'
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className="arduino-boards-dropdown-list"
|
||||
@@ -58,17 +62,25 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
|
||||
...coords,
|
||||
}}
|
||||
>
|
||||
{this.renderItem({
|
||||
label: 'Select Other Board & Port',
|
||||
onClick: () => this.props.openBoardsConfig(),
|
||||
})}
|
||||
{items
|
||||
.map(({ name, port, selected, onClick }) => ({
|
||||
label: `${name} at ${Port.toString(port)}`,
|
||||
label: nls.localize(
|
||||
'arduino/board/boardListItem',
|
||||
'{0} at {1}',
|
||||
name,
|
||||
Port.toString(port)
|
||||
),
|
||||
selected,
|
||||
onClick,
|
||||
}))
|
||||
.map(this.renderItem)}
|
||||
<div
|
||||
key={footerLabel}
|
||||
className="arduino-boards-dropdown-item arduino-board-dropdown-footer"
|
||||
onClick={() => this.props.openBoardsConfig()}
|
||||
>
|
||||
<div>{footerLabel}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,6 +110,9 @@ PID: ${PID}`;
|
||||
this.boardsServiceProvider.onAvailableBoardsChanged(
|
||||
this.updateMenus.bind(this)
|
||||
);
|
||||
this.boardsServiceProvider.onAvailablePortsChanged(
|
||||
this.updateMenus.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
protected async updateMenus(): Promise<void> {
|
||||
@@ -247,19 +250,25 @@ PID: ${PID}`;
|
||||
}
|
||||
|
||||
// Installed ports
|
||||
const registerPorts = (ports: AvailablePorts) => {
|
||||
const registerPorts = (
|
||||
protocol: string,
|
||||
protocolOrder: number,
|
||||
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 menuPath = [
|
||||
...portsSubmenuPath,
|
||||
`${protocolOrder.toString()}_${protocol}`,
|
||||
];
|
||||
const placeholder = new PlaceholderMenuNode(
|
||||
menuPath,
|
||||
`${firstToUpperCase(port.protocol)} ports`
|
||||
`${firstToUpperCase(protocol)} ports`,
|
||||
{ order: protocolOrder.toString() }
|
||||
);
|
||||
this.menuModelRegistry.registerMenuNode(menuPath, placeholder);
|
||||
this.toDisposeBeforeMenuRebuild.push(
|
||||
@@ -268,63 +277,76 @@ PID: ${PID}`;
|
||||
)
|
||||
);
|
||||
|
||||
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 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.commandRegistry.unregisterCommand(command)
|
||||
)
|
||||
);
|
||||
this.menuModelRegistry.registerMenuAction(menuPath, menuAction);
|
||||
}
|
||||
// First we show addresses with recognized boards connected,
|
||||
// then all the rest.
|
||||
const sortedAddresses = Object.keys(ports);
|
||||
sortedAddresses.sort((left: string, right: string): number => {
|
||||
const [, leftBoards] = ports[left];
|
||||
const [, rightBoards] = ports[right];
|
||||
return rightBoards.length - leftBoards.length;
|
||||
});
|
||||
|
||||
for (let i = 0; i < sortedAddresses.length; i++) {
|
||||
const address = sortedAddresses[i];
|
||||
const [port, boards] = ports[address];
|
||||
let label = `${address}`;
|
||||
if (boards.length) {
|
||||
const boardsList = boards.map((board) => board.name).join(', ');
|
||||
label = `${label} (${boardsList})`;
|
||||
}
|
||||
const id = `arduino-select-port--${address}`;
|
||||
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,
|
||||
order: `${protocolOrder + i + 1}`,
|
||||
};
|
||||
this.commandRegistry.registerCommand(command, handler);
|
||||
this.toDisposeBeforeMenuRebuild.push(
|
||||
Disposable.create(() =>
|
||||
this.commandRegistry.unregisterCommand(command)
|
||||
)
|
||||
);
|
||||
this.menuModelRegistry.registerMenuAction(menuPath, menuAction);
|
||||
}
|
||||
};
|
||||
|
||||
const { serial, network, unknown } =
|
||||
AvailablePorts.groupByProtocol(availablePorts);
|
||||
registerPorts(serial);
|
||||
registerPorts(network);
|
||||
registerPorts(unknown);
|
||||
const grouped = AvailablePorts.byProtocol(availablePorts);
|
||||
let protocolOrder = 100;
|
||||
// We first show serial and network ports, then all the rest
|
||||
['serial', 'network'].forEach((protocol) => {
|
||||
const ports = grouped.get(protocol);
|
||||
if (ports) {
|
||||
registerPorts(protocol, protocolOrder, ports);
|
||||
grouped.delete(protocol);
|
||||
protocolOrder = protocolOrder + 100;
|
||||
}
|
||||
});
|
||||
grouped.forEach((ports, protocol) => {
|
||||
registerPorts(protocol, protocolOrder, ports);
|
||||
protocolOrder = protocolOrder + 100;
|
||||
});
|
||||
|
||||
this.mainMenuManager.update();
|
||||
}
|
||||
|
||||
@@ -1,224 +1,237 @@
|
||||
div#select-board-dialog {
|
||||
margin: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
div#select-board-dialog .selectBoardContainer .body {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.select-board-dialog .head {
|
||||
margin: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
div.dialogContent.select-board-dialog > div.head .title {
|
||||
font-weight: 400;
|
||||
letter-spacing: .02em;
|
||||
font-size: 1.2em;
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
margin-bottom: 10px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.02em;
|
||||
font-size: 1.2em;
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
div#select-board-dialog .selectBoardContainer .body .list .item.selected {
|
||||
background: var(--theia-secondaryButton-hoverBackground);
|
||||
background: var(--theia-secondaryButton-hoverBackground);
|
||||
}
|
||||
|
||||
div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .search,
|
||||
#select-board-dialog .selectBoardContainer .search input,
|
||||
#select-board-dialog .selectBoardContainer .list,
|
||||
#select-board-dialog .selectBoardContainer .list {
|
||||
background: var(--theia-editor-background);
|
||||
background: var(--theia-editor-background);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .search input {
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 37px;
|
||||
padding: 10px 5px 10px 10px;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
display: flex;
|
||||
color: var(--theia-editor-foreground);
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 37px;
|
||||
padding: 10px 5px 10px 10px;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
display: flex;
|
||||
color: var(--theia-editor-foreground);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .search input:focus {
|
||||
box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .container {
|
||||
flex: 1;
|
||||
padding: 0px 10px 0px 0px;
|
||||
min-width: 240px;
|
||||
max-width: 240px;
|
||||
flex: 1;
|
||||
padding: 0px 10px 0px 0px;
|
||||
min-width: 240px;
|
||||
max-width: 240px;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .left.container .content {
|
||||
margin: 0 5px 0 0;
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .right.container .content {
|
||||
margin: 0 0 0 5px;
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .container .content .title {
|
||||
color: #7f8c8d;
|
||||
padding: 0px 0px 10px 0px;
|
||||
text-transform: uppercase;
|
||||
color: #7f8c8d;
|
||||
padding: 0px 0px 10px 0px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .container .content .footer {
|
||||
padding: 10px 5px 10px 0px;
|
||||
padding: 10px 5px 10px 0px;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .container .content .loading {
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
color: var(--theia-arduino-branding-secondary);
|
||||
padding: 10px 5px 10px 10px;
|
||||
text-transform: uppercase;
|
||||
/* The max, min-height comes from `.body .list` 200px + 47px top padding - 2 * 10px top padding */
|
||||
max-height: 227px;
|
||||
min-height: 227px;
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
color: var(--theia-arduino-branding-secondary);
|
||||
padding: 10px 5px 10px 10px;
|
||||
text-transform: uppercase;
|
||||
/* The max, min-height comes from `.body .list` 200px + 47px top padding - 2 * 10px top padding */
|
||||
max-height: 227px;
|
||||
min-height: 227px;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list .item {
|
||||
padding: 10px 5px 10px 10px;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
padding: 10px 5px 10px 10px;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list .item .selected-icon {
|
||||
margin-left: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list .item .details {
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
opacity: var(--theia-mod-disabled-opacity);
|
||||
width: 155px; /* used heuristics for the calculation */
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
opacity: var(--theia-mod-disabled-opacity);
|
||||
width: 155px; /* used heuristics for the calculation */
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list .item.missing {
|
||||
opacity: var(--theia-mod-disabled-opacity);
|
||||
opacity: var(--theia-mod-disabled-opacity);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list .item:hover {
|
||||
background: var(--theia-secondaryButton-hoverBackground);
|
||||
background: var(--theia-secondaryButton-hoverBackground);
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list .label {
|
||||
max-width: 215px;
|
||||
width: 215px;
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 215px;
|
||||
width: 215px;
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .list {
|
||||
max-height: 200px;
|
||||
min-height: 200px;
|
||||
overflow-y: auto;
|
||||
max-height: 200px;
|
||||
min-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .ports.list {
|
||||
margin: 47px 0px 0px 0px /* 47 is 37 as input height for the `Boards`, plus 10 margin bottom. */
|
||||
margin: 47px 0px 0px 0px; /* 47 is 37 as input height for the `Boards`, plus 10 margin bottom. */
|
||||
}
|
||||
|
||||
#select-board-dialog .selectBoardContainer .body .search {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 5px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.p-Widget.dialogOverlay .dialogContent.select-board-dialog {
|
||||
width: 500px;
|
||||
width: 500px;
|
||||
}
|
||||
.arduino-boards-toolbar-item-container {
|
||||
margin-left: 3px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container .arduino-boards-toolbar-item .inner-container {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
.arduino-boards-toolbar-item-container
|
||||
.arduino-boards-toolbar-item
|
||||
.inner-container {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container .arduino-boards-toolbar-item .inner-container .notAttached {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
color: red;
|
||||
margin: 0 5px;
|
||||
.arduino-boards-toolbar-item-container
|
||||
.arduino-boards-toolbar-item
|
||||
.inner-container
|
||||
.notAttached {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
color: red;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container .arduino-boards-toolbar-item .inner-container .guessed {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
color: var(--theia-warningBackground);
|
||||
margin: 0 5px;
|
||||
.arduino-boards-toolbar-item-container
|
||||
.arduino-boards-toolbar-item
|
||||
.inner-container
|
||||
.guessed {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
color: var(--theia-warningBackground);
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 220px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item .label {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 5px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item .caret {
|
||||
width: 10px;
|
||||
margin-right: 5px;
|
||||
width: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.arduino-boards-toolbar-item {
|
||||
background: var(--theia-tab-unfocusedActiveBackground);
|
||||
color: var(--theia-foreground);
|
||||
height: 22px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0px 3px 0px 3px;
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
background: var(--theia-tab-unfocusedActiveBackground);
|
||||
color: var(--theia-foreground);
|
||||
height: 22px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
margin: 0px 3px 0px 3px;
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-list {
|
||||
border: 3px solid var(--theia-activityBar-background);
|
||||
margin: -1px;
|
||||
z-index: 1;
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
border: 3px solid var(--theia-activityBar-background);
|
||||
margin: -1px;
|
||||
z-index: 1;
|
||||
border: 1px solid var(--theia-dropdown-border);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item {
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
color: var(--theia-foreground);
|
||||
background: var(--theia-tab-unfocusedActiveBackground);
|
||||
border: 1px solid var(--theia-tab-unfocusedActiveBackground);
|
||||
font-size: var(--theia-ui-font-size1);
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
color: var(--theia-foreground);
|
||||
background: var(--theia-tab-unfocusedActiveBackground);
|
||||
border: 1px solid var(--theia-tab-unfocusedActiveBackground);
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item .fa-check {
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
align-self: center;
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item.selected,
|
||||
.arduino-boards-dropdown-item:hover {
|
||||
border: 1px solid var(--theia-focusBorder);
|
||||
border: 1px solid var(--theia-focusBorder);
|
||||
}
|
||||
|
||||
.arduino-board-dropdown-footer {
|
||||
color: var(--theia-arduino-branding-primary);
|
||||
border-top: 1px solid var(--theia-dropdown-border);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user