Skip to content

New Board Selector UI: show port protocol #1193

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 9 commits into from
Jul 15, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arduino-ide-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"atob": "^2.1.2",
"auth0-js": "^9.14.0",
"btoa": "^1.2.1",
"classnames": "^2.3.1",
"dateformat": "^3.0.3",
"deep-equal": "^2.0.5",
"deepmerge": "2.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,74 @@ export class ArduinoFrontendContribution
hc: 'editor.background',
},
description: 'Background color of the Output view.',
},
{
id: 'arduino.toolbar.dropdown.border',
defaults: {
dark: 'dropdown.border',
light: 'dropdown.border',
hc: 'dropdown.border',
},
description: 'Border color of the Board Selector.',
},

{
id: 'arduino.toolbar.dropdown.borderActive',
defaults: {
dark: 'focusBorder',
light: 'focusBorder',
hc: 'focusBorder',
},
description: "Border color of the Board Selector when it's active",
},

{
id: 'arduino.toolbar.dropdown.background',
defaults: {
dark: 'tab.unfocusedActiveBackground',
light: 'tab.unfocusedActiveBackground',
hc: 'tab.unfocusedActiveBackground',
},
description: 'Background color of the Board Selector.',
},

{
id: 'arduino.toolbar.dropdown.label',
defaults: {
dark: 'foreground',
light: 'foreground',
hc: 'foreground',
},
description: 'Font color of the Board Selector.',
},
{
id: 'arduino.toolbar.dropdown.iconSelected',
defaults: {
dark: 'statusBar.background',
light: 'statusBar.background',
hc: 'statusBar.background',
},
description:
'Color of the selected protocol icon in the Board Selector.',
},
{
id: 'arduino.toolbar.dropdown.option.backgroundHover',
defaults: {
dark: 'editor.background',
light: 'editor.background',
hc: 'editor.background',
},
description: 'Background color on hover of the Board Selector options.',
},
{
id: 'arduino.toolbar.dropdown.option.backgroundSelected',
defaults: {
dark: 'editor.background',
light: 'editor.background',
hc: 'editor.background',
},
description:
'Background color of the selected board in the Board Selector.',
}
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
}

protected setBoardsConfig(config: BoardsConfig.Config): void {
this.logger.info('Board config changed: ', JSON.stringify(config));
this.logger.debug('Board config changed: ', JSON.stringify(config));
this._boardsConfig = config;
this.latestBoardsConfig = this._boardsConfig;
if (this.canUploadTo(this._boardsConfig)) {
Expand Down
158 changes: 112 additions & 46 deletions arduino-ide-extension/src/browser/boards/boards-toolbar-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import * as ReactDOM from '@theia/core/shared/react-dom';
import { CommandRegistry } from '@theia/core/lib/common/command';
import { DisposableCollection } from '@theia/core/lib/common/disposable';
import { Port } from '../../common/protocol';
import { BoardsConfig } from './boards-config';
import { ArduinoCommands } from '../arduino-commands';
import {
BoardsServiceProvider,
AvailableBoard,
} from './boards-service-provider';
import { nls } from '@theia/core/lib/common';
import classNames from 'classnames';

export interface BoardsDropDownListCoords {
readonly top: number;
Expand All @@ -28,10 +28,12 @@ export namespace BoardsDropDown {

export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
protected dropdownElement: HTMLElement;
private listRef: React.RefObject<HTMLDivElement>;

constructor(props: BoardsDropDown.Props) {
super(props);

this.listRef = React.createRef();
let list = document.getElementById('boards-dropdown-container');
if (!list) {
list = document.createElement('div');
Expand All @@ -41,6 +43,12 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
}
}

override componentDidUpdate(prevProps: BoardsDropDown.Props): void {
if (prevProps.coords === 'hidden' && this.listRef.current) {
this.listRef.current.focus();
}
}

override render(): React.ReactNode {
return ReactDOM.createPortal(this.renderNode(), this.dropdownElement);
}
Expand All @@ -61,21 +69,22 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
position: 'absolute',
...coords,
}}
ref={this.listRef}
tabIndex={0}
>
{items
.map(({ name, port, selected, onClick }) => ({
label: nls.localize(
'arduino/board/boardListItem',
'{0} at {1}',
name,
Port.toString(port)
),
selected,
onClick,
}))
.map(this.renderItem)}
<div className="arduino-boards-dropdown-list--items-container">
{items
.map(({ name, port, selected, onClick }) => ({
boardLabel: name,
port,
selected,
onClick,
}))
.map(this.renderItem)}
</div>
<div
key={footerLabel}
tabIndex={0}
className="arduino-boards-dropdown-item arduino-board-dropdown-footer"
onClick={() => this.props.openBoardsConfig()}
>
Expand All @@ -86,22 +95,49 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
}

protected renderItem({
label,
boardLabel,
port,
selected,
onClick,
}: {
label: string;
boardLabel: string;
port: Port;
selected?: boolean;
onClick: () => void;
}): React.ReactNode {
const protocolIcon = iconNameFromProtocol(port.protocol);
const onKeyUp = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
onClick();
}
};

return (
<div
key={label}
className={`arduino-boards-dropdown-item ${selected ? 'selected' : ''}`}
key={`board-item--${boardLabel}-${port.address}`}
className={classNames('arduino-boards-dropdown-item', {
'arduino-boards-dropdown-item--selected': selected,
})}
onClick={onClick}
onKeyUp={onKeyUp}
tabIndex={0}
>
<div>{label}</div>
{selected ? <span className="fa fa-check" /> : ''}
<div
className={classNames(
'arduino-boards-dropdown-item--protocol',
'fa',
protocolIcon
)}
/>
<div className="arduino-boards-dropdown-item--label">
<div className="arduino-boards-dropdown-item--board-label">
{boardLabel}
</div>
<div className="arduino-boards-dropdown-item--port-label">
{port.address}
</div>
</div>
{selected ? <div className="fa fa-check" /> : ''}
</div>
);
}
Expand Down Expand Up @@ -163,36 +199,43 @@ export class BoardsToolBarItem extends React.Component<

override render(): React.ReactNode {
const { coords, availableBoards } = this.state;
const boardsConfig = this.props.boardsServiceClient.boardsConfig;
const title = BoardsConfig.Config.toString(boardsConfig, {
default: nls.localize(
'arduino/common/noBoardSelected',
'No board selected'
),
});
const decorator = (() => {
const selectedBoard = availableBoards.find(({ selected }) => selected);
if (!selectedBoard || !selectedBoard.port) {
return 'fa fa-times notAttached';
}
if (selectedBoard.state === AvailableBoard.State.guessed) {
return 'fa fa-exclamation-triangle guessed';
}
return '';
})();
const selectedBoard = availableBoards.find(({ selected }) => selected);

const boardLabel =
selectedBoard?.name ||
nls.localize('arduino/board/selectBoard', 'Select Board');
const selectedPortLabel = portLabel(selectedBoard?.port?.address);

const isConnected = Boolean(
selectedBoard && AvailableBoard.hasPort(selectedBoard)
);
const protocolIcon = isConnected
? iconNameFromProtocol(selectedBoard?.port?.protocol || '')
: null;
const procolIconClassNames = classNames(
'arduino-boards-toolbar-item--protocol',
'fa',
protocolIcon
);

return (
<React.Fragment>
<div className="arduino-boards-toolbar-item-container">
<div className="arduino-boards-toolbar-item" title={title}>
<div className="inner-container" onClick={this.show}>
<span className={decorator} />
<div className="label noWrapInfo">
<div className="noWrapInfo noselect">{title}</div>
</div>
<span className="fa fa-caret-down caret" />
</div>
<div
className="arduino-boards-toolbar-item-container"
title={selectedPortLabel}
onClick={this.show}
>
{protocolIcon && <div className={procolIconClassNames} />}
<div
className={classNames(
'arduino-boards-toolbar-item--label',
'noWrapInfo noselect',
{ 'arduino-boards-toolbar-item--label-connected': isConnected }
)}
>
{boardLabel}
</div>
<div className="fa fa-caret-down caret" />
</div>
<BoardsDropDown
coords={coords}
Expand All @@ -212,6 +255,7 @@ export class BoardsToolBarItem extends React.Component<
selectedPort: board.port,
};
}
this.setState({ coords: 'hidden' });
},
}))}
openBoardsConfig={this.openDialog}
Expand All @@ -222,7 +266,6 @@ export class BoardsToolBarItem extends React.Component<

protected openDialog = () => {
this.props.commands.executeCommand(ArduinoCommands.OPEN_BOARDS_DIALOG.id);
this.setState({ coords: 'hidden' });
};
}
export namespace BoardsToolBarItem {
Expand All @@ -236,3 +279,26 @@ export namespace BoardsToolBarItem {
coords: BoardsDropDownListCoords | 'hidden';
}
}

function iconNameFromProtocol(protocol: string): string {
switch (protocol) {
case 'serial':
return 'fa-arduino-technology-usb';
case 'network':
return 'fa-arduino-technology-connection';
/*
Bluetooth ports are not listed yet from the CLI;
Not sure about the naming ('bluetooth'); make sure it's correct before uncommenting the following lines
*/
// case 'bluetooth':
// return 'fa-arduino-technology-bluetooth';
default:
return 'fa-arduino-technology-3dimensionscube';
}
}

function portLabel(portName?: string): string {
return portName
? nls.localize('arduino/board/portLabel', 'Port: {0}', portName)
: nls.localize('arduino/board/disconnected', 'Disconnected');
}
7 changes: 7 additions & 0 deletions arduino-ide-extension/src/browser/data/dark.color-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
"arduino.output.background": "#000000",
"arduino.toolbar.button.hoverBackground": "#dae3e3",
"arduino.toolbar.button.background": "#0ca1a6",
"arduino.toolbar.dropdown.border": "#7fcbcd",
"arduino.toolbar.dropdown.borderActive": "#0ca1a6",
"arduino.toolbar.dropdown.background": "#2c353a",
"arduino.toolbar.dropdown.label": "#dae3e3",
"arduino.toolbar.dropdown.iconSelected": "#3fae98",
"arduino.toolbar.dropdown.option.backgroundHover": "#374146",
"arduino.toolbar.dropdown.option.backgroundSelected": "#4e5b61",
"arduino.toolbar.toggleBackground": "#f1c40f",
"sideBar.background": "#101618",
"sideBar.foreground": "#dae3e3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"titleBar.activeForeground": "#f7f9f9",
"terminal.background": "#000000",
"terminal.foreground": "#e0e0e0",
"dropdown.border": "#f7f9f9",
"dropdown.border": "#dae3e3",
"dropdown.background": "#ffffff",
"dropdown.foreground": "#4e5b61",
"activityBar.background": "#ecf1f1",
Expand All @@ -47,6 +47,13 @@
"arduino.output.background": "#000000",
"arduino.toolbar.button.hoverBackground": "#f7f9f9",
"arduino.toolbar.button.background": "#7fcbcd",
"arduino.toolbar.dropdown.border": "#dae3e3",
"arduino.toolbar.dropdown.borderActive": "#7fcbcd",
"arduino.toolbar.dropdown.background": "#ffffff",
"arduino.toolbar.dropdown.label": "#4e5b61",
"arduino.toolbar.dropdown.iconSelected": "#1da086",
"arduino.toolbar.dropdown.option.backgroundHover": "#ecf1f1",
"arduino.toolbar.dropdown.option.backgroundSelected": "#dae3e3",
"arduino.toolbar.toggleBackground": "#f1c40f",
"sideBar.background": "#f7f9f9",
"sideBar.foreground": "#4e5b61",
Expand Down
Loading