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 1 commit
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
Prev Previous commit
Next Next commit
implement new Board Selector design
  • Loading branch information
Alberto Iannaccone committed Jul 15, 2022
commit c9e10b968485c2b56a2a3e1fa09af96482ad5380
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 @@ -270,7 +270,6 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
}

protected setBoardsConfig(config: BoardsConfig.Config): void {
this.logger.info('Board config changed: ', JSON.stringify(config));
this._boardsConfig = config;
this.latestBoardsConfig = this._boardsConfig;
if (this.canUploadTo(this._boardsConfig)) {
Expand Down
124 changes: 85 additions & 39 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 Down Expand Up @@ -64,12 +64,8 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
>
{items
.map(({ name, port, selected, onClick }) => ({
label: nls.localize(
'arduino/board/boardListItem',
'{0} at {1}',
name,
Port.toString(port)
),
boardLabel: name,
port,
selected,
onClick,
}))
Expand All @@ -86,22 +82,42 @@ 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);

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}
>
<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 +179,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 Down Expand Up @@ -236,3 +259,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) {
return portName
? nls.localize('arduino/board/portLabel', 'Port: {0}', portName)
: nls.localize('arduino/board/disconnected', 'Disconnected');
}
130 changes: 78 additions & 52 deletions arduino-ide-extension/src/browser/style/boards-config-dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -142,96 +142,122 @@ div#select-board-dialog .selectBoardContainer .body .list .item.selected i {
.p-Widget.dialogOverlay .dialogContent.select-board-dialog {
width: 500px;
}

.arduino-boards-toolbar-item-container {
margin-left: 3px;
align-items: center;
background: var(--theia-tab-unfocusedActiveBackground);
border-radius: 1px;
color: var(--theia-foreground);
display: flex;
gap: 10px;
height: 24px;
margin: 0 6px;
overflow: hidden;
padding: 0 10px;
width: 230px;
}

.arduino-boards-toolbar-item-container
.arduino-boards-toolbar-item
.inner-container {
.arduino-boards-toolbar-item--protocol,
.arduino-boards-dropdown-item--protocol {
align-items: center;
display: flex;
align-items: baseline;
width: 100%;
font-size: 16px;
}

.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--protocol {
color: var(--theia-foreground);
}

.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-dropdown-item--protocol {
color: var(--theia-activityBar-inactiveForeground);
}

.arduino-boards-toolbar-item-container {
.arduino-boards-toolbar-item-container
.arduino-boards-toolbar-item {
display: flex;
align-items: center;
width: 220px;
align-items: baseline;
width: 100%;
}

.arduino-boards-toolbar-item .label {
.arduino-boards-toolbar-item--label {
height: 100%;
display: flex;
align-items: center;
margin: 0 5px;
width: 100%;
}

.arduino-boards-toolbar-item .caret {
width: 10px;
margin-right: 5px;
.arduino-boards-toolbar-item--label-connected {
font-weight: 700;
}

.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);
.arduino-boards-toolbar-item-container .caret {
width: 10px;
margin-right: 5px;
}

.arduino-boards-dropdown-list {
border: 3px solid var(--theia-activityBar-background);
margin: -1px;
z-index: 1;
border: 1px solid var(--theia-dropdown-border);
border: 1px solid var(--theia-menu-selectionBackground);
}

.arduino-boards-dropdown-list--items-container {
overflow: auto;
max-height: 404px;
}

.arduino-boards-dropdown-list--items-container::-webkit-scrollbar {
background: var(--theia-tab-unfocusedActiveBackground);
}

.arduino-boards-dropdown-item {
font-size: var(--theia-ui-font-size1);
background: var(--theia-tab-unfocusedActiveBackground);
color: var(--theia-foreground);
cursor: default;
display: flex;
font-size: var(--theia-ui-font-size1);
gap: 10px;
justify-content: space-between;
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;
.arduino-boards-dropdown-item--label {
flex: 1;
}

.arduino-boards-dropdown-item--board-label {
font-size: 14px;
}

.arduino-boards-dropdown-item--port-label {
color: #95A5A6;
font-size: 12px;
}

.arduino-boards-dropdown-item.selected,
.arduino-boards-dropdown-item:hover {
border: 1px solid var(--theia-focusBorder);
background: var(--theia-list-hoverBackground);
}

.arduino-boards-dropdown-item--selected,
.arduino-boards-dropdown-item--selected:hover {
background: var(--theia-menu-selectionBackground);
border: 1px solid var(--theia-menu-selectionBackground);
}

.arduino-boards-dropdown-item--selected
.arduino-boards-dropdown-item--port-label {
color: var(--theia-foreground);
}

.arduino-boards-dropdown-item--selected .fa {
color: #1DA086;
}

.arduino-boards-dropdown-item .fa-check {
align-self: center;
}

.arduino-board-dropdown-footer {
color: var(--theia-arduino-branding-primary);
border-top: 1px solid var(--theia-dropdown-border);
border-top: 1px solid var(--theia-menu-selectionBackground);
}
4 changes: 2 additions & 2 deletions arduino-ide-extension/src/browser/style/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@
#arduino-toolbar-container {
display: flex;
width: 100%;
justify-content: space-between;
}

.p-TabBar-toolbar.theia-arduino-toolbar {
flex: 1;
z-index: 0;
}

Expand All @@ -119,7 +119,7 @@

#theia-top-panel .p-TabBar-toolbar.theia-arduino-toolbar.right {
justify-content: flex-start;
min-width: 190px;
min-width: 100px;
}

#theia-top-panel .p-TabBar-toolbar.theia-arduino-toolbar.left {
Expand Down
Loading