Skip to content

Commit ff63d2a

Browse files
Merge remote-tracking branch 'origin/select-board-with-protocol' into fspissu/toolbar-update
2 parents bc29215 + 509ba75 commit ff63d2a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+579
-276
lines changed

arduino-ide-extension/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"atob": "^2.1.2",
6262
"auth0-js": "^9.14.0",
6363
"btoa": "^1.2.1",
64+
"classnames": "^2.3.1",
6465
"dateformat": "^3.0.3",
6566
"deep-equal": "^2.0.5",
6667
"deepmerge": "2.0.1",

arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx

+68
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,74 @@ export class ArduinoFrontendContribution
650650
hc: 'editor.background',
651651
},
652652
description: 'Background color of the Output view.',
653+
},
654+
{
655+
id: 'arduino.toolbar.dropdown.border',
656+
defaults: {
657+
dark: 'dropdown.border',
658+
light: 'dropdown.border',
659+
hc: 'dropdown.border',
660+
},
661+
description: 'Border color of the Board Selector.',
662+
},
663+
664+
{
665+
id: 'arduino.toolbar.dropdown.borderActive',
666+
defaults: {
667+
dark: 'focusBorder',
668+
light: 'focusBorder',
669+
hc: 'focusBorder',
670+
},
671+
description: "Border color of the Board Selector when it's active",
672+
},
673+
674+
{
675+
id: 'arduino.toolbar.dropdown.background',
676+
defaults: {
677+
dark: 'tab.unfocusedActiveBackground',
678+
light: 'tab.unfocusedActiveBackground',
679+
hc: 'tab.unfocusedActiveBackground',
680+
},
681+
description: 'Background color of the Board Selector.',
682+
},
683+
684+
{
685+
id: 'arduino.toolbar.dropdown.label',
686+
defaults: {
687+
dark: 'foreground',
688+
light: 'foreground',
689+
hc: 'foreground',
690+
},
691+
description: 'Font color of the Board Selector.',
692+
},
693+
{
694+
id: 'arduino.toolbar.dropdown.iconSelected',
695+
defaults: {
696+
dark: 'statusBar.background',
697+
light: 'statusBar.background',
698+
hc: 'statusBar.background',
699+
},
700+
description:
701+
'Color of the selected protocol icon in the Board Selector.',
702+
},
703+
{
704+
id: 'arduino.toolbar.dropdown.option.backgroundHover',
705+
defaults: {
706+
dark: 'editor.background',
707+
light: 'editor.background',
708+
hc: 'editor.background',
709+
},
710+
description: 'Background color on hover of the Board Selector options.',
711+
},
712+
{
713+
id: 'arduino.toolbar.dropdown.option.backgroundSelected',
714+
defaults: {
715+
dark: 'editor.background',
716+
light: 'editor.background',
717+
hc: 'editor.background',
718+
},
719+
description:
720+
'Background color of the selected board in the Board Selector.',
653721
}
654722
);
655723
}

arduino-ide-extension/src/browser/boards/boards-service-provider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
270270
}
271271

272272
protected setBoardsConfig(config: BoardsConfig.Config): void {
273-
this.logger.info('Board config changed: ', JSON.stringify(config));
273+
this.logger.debug('Board config changed: ', JSON.stringify(config));
274274
this._boardsConfig = config;
275275
this.latestBoardsConfig = this._boardsConfig;
276276
if (this.canUploadTo(this._boardsConfig)) {

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

+112-46
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import * as ReactDOM from '@theia/core/shared/react-dom';
33
import { CommandRegistry } from '@theia/core/lib/common/command';
44
import { DisposableCollection } from '@theia/core/lib/common/disposable';
55
import { Port } from '../../common/protocol';
6-
import { BoardsConfig } from './boards-config';
76
import { ArduinoCommands } from '../arduino-commands';
87
import {
98
BoardsServiceProvider,
109
AvailableBoard,
1110
} from './boards-service-provider';
1211
import { nls } from '@theia/core/lib/common';
12+
import classNames from 'classnames';
1313

1414
export interface BoardsDropDownListCoords {
1515
readonly top: number;
@@ -28,10 +28,12 @@ export namespace BoardsDropDown {
2828

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

3233
constructor(props: BoardsDropDown.Props) {
3334
super(props);
3435

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

46+
override componentDidUpdate(prevProps: BoardsDropDown.Props): void {
47+
if (prevProps.coords === 'hidden' && this.listRef.current) {
48+
this.listRef.current.focus();
49+
}
50+
}
51+
4452
override render(): React.ReactNode {
4553
return ReactDOM.createPortal(this.renderNode(), this.dropdownElement);
4654
}
@@ -61,21 +69,22 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
6169
position: 'absolute',
6270
...coords,
6371
}}
72+
ref={this.listRef}
73+
tabIndex={0}
6474
>
65-
{items
66-
.map(({ name, port, selected, onClick }) => ({
67-
label: nls.localize(
68-
'arduino/board/boardListItem',
69-
'{0} at {1}',
70-
name,
71-
Port.toString(port)
72-
),
73-
selected,
74-
onClick,
75-
}))
76-
.map(this.renderItem)}
75+
<div className="arduino-boards-dropdown-list--items-container">
76+
{items
77+
.map(({ name, port, selected, onClick }) => ({
78+
boardLabel: name,
79+
port,
80+
selected,
81+
onClick,
82+
}))
83+
.map(this.renderItem)}
84+
</div>
7785
<div
7886
key={footerLabel}
87+
tabIndex={0}
7988
className="arduino-boards-dropdown-item arduino-board-dropdown-footer"
8089
onClick={() => this.props.openBoardsConfig()}
8190
>
@@ -86,22 +95,49 @@ export class BoardsDropDown extends React.Component<BoardsDropDown.Props> {
8695
}
8796

8897
protected renderItem({
89-
label,
98+
boardLabel,
99+
port,
90100
selected,
91101
onClick,
92102
}: {
93-
label: string;
103+
boardLabel: string;
104+
port: Port;
94105
selected?: boolean;
95106
onClick: () => void;
96107
}): React.ReactNode {
108+
const protocolIcon = iconNameFromProtocol(port.protocol);
109+
const onKeyUp = (e: React.KeyboardEvent) => {
110+
if (e.key === 'Enter') {
111+
onClick();
112+
}
113+
};
114+
97115
return (
98116
<div
99-
key={label}
100-
className={`arduino-boards-dropdown-item ${selected ? 'selected' : ''}`}
117+
key={`board-item--${boardLabel}-${port.address}`}
118+
className={classNames('arduino-boards-dropdown-item', {
119+
'arduino-boards-dropdown-item--selected': selected,
120+
})}
101121
onClick={onClick}
122+
onKeyUp={onKeyUp}
123+
tabIndex={0}
102124
>
103-
<div>{label}</div>
104-
{selected ? <span className="fa fa-check" /> : ''}
125+
<div
126+
className={classNames(
127+
'arduino-boards-dropdown-item--protocol',
128+
'fa',
129+
protocolIcon
130+
)}
131+
/>
132+
<div className="arduino-boards-dropdown-item--label">
133+
<div className="arduino-boards-dropdown-item--board-label">
134+
{boardLabel}
135+
</div>
136+
<div className="arduino-boards-dropdown-item--port-label">
137+
{port.address}
138+
</div>
139+
</div>
140+
{selected ? <div className="fa fa-check" /> : ''}
105141
</div>
106142
);
107143
}
@@ -163,36 +199,43 @@ export class BoardsToolBarItem extends React.Component<
163199

164200
override render(): React.ReactNode {
165201
const { coords, availableBoards } = this.state;
166-
const boardsConfig = this.props.boardsServiceClient.boardsConfig;
167-
const title = BoardsConfig.Config.toString(boardsConfig, {
168-
default: nls.localize(
169-
'arduino/common/noBoardSelected',
170-
'No board selected'
171-
),
172-
});
173-
const decorator = (() => {
174-
const selectedBoard = availableBoards.find(({ selected }) => selected);
175-
if (!selectedBoard || !selectedBoard.port) {
176-
return 'fa fa-times notAttached';
177-
}
178-
if (selectedBoard.state === AvailableBoard.State.guessed) {
179-
return 'fa fa-exclamation-triangle guessed';
180-
}
181-
return '';
182-
})();
202+
const selectedBoard = availableBoards.find(({ selected }) => selected);
203+
204+
const boardLabel =
205+
selectedBoard?.name ||
206+
nls.localize('arduino/board/selectBoard', 'Select Board');
207+
const selectedPortLabel = portLabel(selectedBoard?.port?.address);
208+
209+
const isConnected = Boolean(
210+
selectedBoard && AvailableBoard.hasPort(selectedBoard)
211+
);
212+
const protocolIcon = isConnected
213+
? iconNameFromProtocol(selectedBoard?.port?.protocol || '')
214+
: null;
215+
const procolIconClassNames = classNames(
216+
'arduino-boards-toolbar-item--protocol',
217+
'fa',
218+
protocolIcon
219+
);
183220

184221
return (
185222
<React.Fragment>
186-
<div className="arduino-boards-toolbar-item-container">
187-
<div className="arduino-boards-toolbar-item" title={title}>
188-
<div className="inner-container" onClick={this.show}>
189-
<span className={decorator} />
190-
<div className="label noWrapInfo">
191-
<div className="noWrapInfo noselect">{title}</div>
192-
</div>
193-
<span className="fa fa-caret-down caret" />
194-
</div>
223+
<div
224+
className="arduino-boards-toolbar-item-container"
225+
title={selectedPortLabel}
226+
onClick={this.show}
227+
>
228+
{protocolIcon && <div className={procolIconClassNames} />}
229+
<div
230+
className={classNames(
231+
'arduino-boards-toolbar-item--label',
232+
'noWrapInfo noselect',
233+
{ 'arduino-boards-toolbar-item--label-connected': isConnected }
234+
)}
235+
>
236+
{boardLabel}
195237
</div>
238+
<div className="fa fa-caret-down caret" />
196239
</div>
197240
<BoardsDropDown
198241
coords={coords}
@@ -212,6 +255,7 @@ export class BoardsToolBarItem extends React.Component<
212255
selectedPort: board.port,
213256
};
214257
}
258+
this.setState({ coords: 'hidden' });
215259
},
216260
}))}
217261
openBoardsConfig={this.openDialog}
@@ -222,7 +266,6 @@ export class BoardsToolBarItem extends React.Component<
222266

223267
protected openDialog = () => {
224268
this.props.commands.executeCommand(ArduinoCommands.OPEN_BOARDS_DIALOG.id);
225-
this.setState({ coords: 'hidden' });
226269
};
227270
}
228271
export namespace BoardsToolBarItem {
@@ -236,3 +279,26 @@ export namespace BoardsToolBarItem {
236279
coords: BoardsDropDownListCoords | 'hidden';
237280
}
238281
}
282+
283+
function iconNameFromProtocol(protocol: string): string {
284+
switch (protocol) {
285+
case 'serial':
286+
return 'fa-arduino-technology-usb';
287+
case 'network':
288+
return 'fa-arduino-technology-connection';
289+
/*
290+
Bluetooth ports are not listed yet from the CLI;
291+
Not sure about the naming ('bluetooth'); make sure it's correct before uncommenting the following lines
292+
*/
293+
// case 'bluetooth':
294+
// return 'fa-arduino-technology-bluetooth';
295+
default:
296+
return 'fa-arduino-technology-3dimensionscube';
297+
}
298+
}
299+
300+
function portLabel(portName?: string): string {
301+
return portName
302+
? nls.localize('arduino/board/portLabel', 'Port: {0}', portName)
303+
: nls.localize('arduino/board/disconnected', 'Disconnected');
304+
}

arduino-ide-extension/src/browser/data/dark.color-theme.json

+8
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@
4747
"arduino.output.background": "#000000",
4848
"arduino.toolbar.button.hoverBackground": "#dae3e3",
4949
"arduino.toolbar.button.background": "#0ca1a6",
50+
"arduino.toolbar.dropdown.border": "#7fcbcd",
51+
"arduino.toolbar.dropdown.borderActive": "#0ca1a6",
52+
"arduino.toolbar.dropdown.background": "#2c353a",
53+
"arduino.toolbar.dropdown.label": "#dae3e3",
54+
"arduino.toolbar.dropdown.iconSelected": "#3fae98",
55+
"arduino.toolbar.dropdown.option.backgroundHover": "#374146",
56+
"arduino.toolbar.dropdown.option.backgroundSelected": "#4e5b61",
57+
"arduino.toolbar.toggleBackground": "#f1c40f",
5058
"sideBar.background": "#101618",
5159
"sideBar.foreground": "#dae3e3",
5260
"input.background": "#000000",

arduino-ide-extension/src/browser/data/default.color-theme.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"titleBar.activeForeground": "#f7f9f9",
3030
"terminal.background": "#000000",
3131
"terminal.foreground": "#e0e0e0",
32-
"dropdown.border": "#f7f9f9",
32+
"dropdown.border": "#dae3e3",
3333
"dropdown.background": "#ffffff",
3434
"dropdown.foreground": "#4e5b61",
3535
"activityBar.background": "#ecf1f1",
@@ -47,6 +47,14 @@
4747
"arduino.output.background": "#000000",
4848
"arduino.toolbar.button.hoverBackground": "#f7f9f9",
4949
"arduino.toolbar.button.background": "#7fcbcd",
50+
"arduino.toolbar.dropdown.border": "#dae3e3",
51+
"arduino.toolbar.dropdown.borderActive": "#7fcbcd",
52+
"arduino.toolbar.dropdown.background": "#ffffff",
53+
"arduino.toolbar.dropdown.label": "#4e5b61",
54+
"arduino.toolbar.dropdown.iconSelected": "#1da086",
55+
"arduino.toolbar.dropdown.option.backgroundHover": "#ecf1f1",
56+
"arduino.toolbar.dropdown.option.backgroundSelected": "#dae3e3",
57+
"arduino.toolbar.toggleBackground": "#f1c40f",
5058
"sideBar.background": "#f7f9f9",
5159
"sideBar.foreground": "#4e5b61",
5260
"input.background": "#ffffff",

0 commit comments

Comments
 (0)