mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-11-14 04:39:28 +00:00
Select Board Dialog Style and Layout
Signed-off-by: jbicker <jan.bicker@typefox.io>
This commit is contained in:
@@ -1,20 +1,53 @@
|
||||
import * as React from 'react';
|
||||
import { Board } from '../../common/protocol/boards-service';
|
||||
import { BoardsService, Board } from '../../common/protocol/boards-service';
|
||||
import { ContextMenuRenderer } from '@theia/core/lib/browser';
|
||||
import { ArduinoToolbarContextMenu } from '../arduino-file-menu';
|
||||
import { BoardsNotificationService } from '../boards-notification-service';
|
||||
|
||||
export namespace BoardsToolBarItem {
|
||||
export interface Props {
|
||||
readonly onNoBoardsInstalled: () => void;
|
||||
readonly onUnknownBoard: (board: Board) => void;
|
||||
readonly contextMenuRenderer: ContextMenuRenderer;
|
||||
readonly boardsNotificationService: BoardsNotificationService;
|
||||
readonly boardService: BoardsService;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
selectedBoard?: Board;
|
||||
selectedIsAttached: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export class BoardsToolBarItem extends React.Component<BoardsToolBarItem.Props, {}> {
|
||||
export class BoardsToolBarItem extends React.Component<BoardsToolBarItem.Props, BoardsToolBarItem.State> {
|
||||
|
||||
protected attachedBoards: Board[];
|
||||
|
||||
constructor(props: BoardsToolBarItem.Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
selectedBoard: undefined,
|
||||
selectedIsAttached: true
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setAttachedBoards();
|
||||
}
|
||||
|
||||
protected async setAttachedBoards() {
|
||||
const { boards } = await this.props.boardService.getAttachedBoards();
|
||||
this.attachedBoards = boards;
|
||||
if(this.attachedBoards.length){
|
||||
await this.props.boardService.selectBoard(this.attachedBoards[0]);
|
||||
this.setSelectedBoard(this.attachedBoards[0]);
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedBoard(board: Board) {
|
||||
if (this.attachedBoards.length) {
|
||||
this.setState({ selectedIsAttached: !!this.attachedBoards.find(attachedBoard => attachedBoard.name === board.name) });
|
||||
}
|
||||
this.setState({ selectedBoard: board });
|
||||
}
|
||||
|
||||
protected readonly doShowSelectBoardsMenu = (event: React.MouseEvent<HTMLElement>) => this.showSelectBoardsMenu(event);
|
||||
@@ -29,12 +62,13 @@ export class BoardsToolBarItem extends React.Component<BoardsToolBarItem.Props,
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
|
||||
return <React.Fragment>
|
||||
<div className='arduino-boards-toolbar-item-container' onClick={this.doShowSelectBoardsMenu}>
|
||||
<div className='arduino-boards-toolbar-item'>
|
||||
<div className='inner-container'>
|
||||
<div className='label'>Show selected Board here</div>
|
||||
<span className={!this.state.selectedBoard || !this.state.selectedIsAttached ? 'fa fa-times notAttached' : ''}></span>
|
||||
<div className='label'>{this.state.selectedBoard ? this.state.selectedBoard.name : 'no board selected'}</div>
|
||||
<span className='fa fa-caret-down'></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,42 +10,84 @@ export interface BoardAndPortSelection {
|
||||
port?: string;
|
||||
}
|
||||
|
||||
export namespace SelectableBoardsItem {
|
||||
export namespace BoardAndPortSelectableItem {
|
||||
export interface Props {
|
||||
board: Board,
|
||||
item: BoardAndPortSelection,
|
||||
selected: boolean,
|
||||
onClick: (selection: BoardAndPortSelection) => void
|
||||
onSelect: (selection: BoardAndPortSelection) => void
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectableBoardsItem extends React.Component<SelectableBoardsItem.Props> {
|
||||
export class BoardAndPortSelectableItem extends React.Component<BoardAndPortSelectableItem.Props> {
|
||||
|
||||
render(): React.ReactNode {
|
||||
return <div onClick={this.select} className={`item ${this.props.selected ? 'selected' : ''}`}>{this.props.board.name}</div>
|
||||
if (this.props.item.board || this.props.item.port) {
|
||||
return <div onClick={this.select} className={`item ${this.props.selected ? 'selected' : ''}`}>
|
||||
{this.props.item.board ? this.props.item.board.name : this.props.item.port}
|
||||
{this.props.selected ? <i className='fa fa-check'></i> : ''}
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly select = (() => {
|
||||
this.props.onClick({ board: this.props.board })
|
||||
this.props.onSelect({ board: this.props.item.board, port: this.props.item.port })
|
||||
}).bind(this);
|
||||
}
|
||||
|
||||
export namespace SelectablePortsItem {
|
||||
export namespace BoardAndPortSelectionList {
|
||||
export interface Props {
|
||||
port: string,
|
||||
selected: boolean,
|
||||
onClick: (selection: BoardAndPortSelection) => void
|
||||
type: 'boards' | 'ports';
|
||||
list: BoardAndPortSelection[];
|
||||
onSelect: (selection: BoardAndPortSelection) => void;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
selection: BoardAndPortSelection
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectablePortsItem extends React.Component<SelectablePortsItem.Props> {
|
||||
export class BoardAndPortSelectionList extends React.Component<BoardAndPortSelectionList.Props, BoardAndPortSelectionList.State> {
|
||||
|
||||
constructor(props: BoardAndPortSelectionList.Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
selection: {}
|
||||
}
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.setState({ selection: {} });
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return <div onClick={() => this.props.onClick({ port: this.props.port })} className={`item ${this.props.selected ? 'selected' : ''}`}>{this.props.port}</div>
|
||||
return <div className={`${this.props.type} list`}>
|
||||
{this.props.list.map(item => <BoardAndPortSelectableItem
|
||||
key={item.board ? item.board.name : item.port}
|
||||
onSelect={this.doSelect}
|
||||
item={item}
|
||||
selected={this.isSelectedItem(item)}
|
||||
/>)}
|
||||
</div>
|
||||
}
|
||||
|
||||
protected readonly select = (() => {
|
||||
this.props.onClick({ port: this.props.port })
|
||||
}).bind(this);
|
||||
protected readonly doSelect = (boardAndPortSelection: BoardAndPortSelection) => {
|
||||
this.setState({ selection: boardAndPortSelection });
|
||||
this.props.onSelect(boardAndPortSelection);
|
||||
}
|
||||
|
||||
protected readonly isSelectedItem = ((item: BoardAndPortSelection) => {
|
||||
if (this.state.selection.board) {
|
||||
return (this.state.selection.board === item.board);
|
||||
} else if (this.state.selection.port) {
|
||||
return (this.state.selection.port === item.port);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
protected readonly isSelectedPort = ((port: string) => {
|
||||
return (this.state.selection.port && this.state.selection.port === port) || false;
|
||||
});
|
||||
}
|
||||
|
||||
export namespace BoardAndPortSelectionComponent {
|
||||
@@ -64,6 +106,8 @@ export namespace BoardAndPortSelectionComponent {
|
||||
export class BoardAndPortSelectionComponent extends React.Component<BoardAndPortSelectionComponent.Props, BoardAndPortSelectionComponent.State> {
|
||||
|
||||
protected allBoards: Board[] = [];
|
||||
protected boardListComponent: BoardAndPortSelectionList | null;
|
||||
protected portListComponent: BoardAndPortSelectionList | null;
|
||||
|
||||
constructor(props: BoardAndPortSelectionComponent.Props) {
|
||||
super(props);
|
||||
@@ -80,6 +124,16 @@ export class BoardAndPortSelectionComponent extends React.Component<BoardAndPort
|
||||
this.setPorts();
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
if (this.boardListComponent) {
|
||||
this.boardListComponent.reset();
|
||||
}
|
||||
if (this.portListComponent) {
|
||||
this.portListComponent.reset();
|
||||
}
|
||||
this.setState({selection: {}});
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return <React.Fragment>
|
||||
<div className='body'>
|
||||
@@ -87,13 +141,16 @@ export class BoardAndPortSelectionComponent extends React.Component<BoardAndPort
|
||||
<div className='content'>
|
||||
<div className='title'>
|
||||
BOARDS
|
||||
</div>
|
||||
</div>
|
||||
<div className='search'>
|
||||
<input type='search' placeholder='SEARCH BOARD' onChange={this.doFilter} />
|
||||
<i className='fa fa-search'></i>
|
||||
</div>
|
||||
<div className='boards list'>
|
||||
{this.state.boards.map(board => <SelectableBoardsItem key={board.name} onClick={this.doSelect} board={board} selected={this.isSelectedBoard(board)} />)}
|
||||
</div>
|
||||
<BoardAndPortSelectionList
|
||||
ref={ref => { this.boardListComponent = ref }}
|
||||
type='boards'
|
||||
onSelect={this.doSelect}
|
||||
list={this.state.boards.map<BoardAndPortSelection>(board => ({ board }))} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='right container'>
|
||||
@@ -101,35 +158,17 @@ export class BoardAndPortSelectionComponent extends React.Component<BoardAndPort
|
||||
<div className='title'>
|
||||
PORTS
|
||||
</div>
|
||||
<div className='ports list'>
|
||||
{this.state.ports.map(port => <SelectablePortsItem key={port} onClick={this.doSelect} port={port} selected={this.isSelectedPort(port)} />)}
|
||||
</div>
|
||||
<BoardAndPortSelectionList
|
||||
ref={ref => { this.portListComponent = ref }}
|
||||
type='ports'
|
||||
onSelect={this.doSelect}
|
||||
list={this.state.ports.map<BoardAndPortSelection>(port => ({ port }))} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
protected readonly isSelectedBoard = ((board: Board) => {
|
||||
return (this.state.selection.board && this.state.selection.board === board) || false;
|
||||
});
|
||||
|
||||
protected readonly isSelectedPort = ((port: string) => {
|
||||
return (this.state.selection.port && this.state.selection.port === port) || false;
|
||||
});
|
||||
|
||||
protected readonly doSelect = (boardAndPortSelection: BoardAndPortSelection) => {
|
||||
const selection = this.state.selection;
|
||||
if (boardAndPortSelection.board) {
|
||||
selection.board = boardAndPortSelection.board;
|
||||
}
|
||||
if (boardAndPortSelection.port) {
|
||||
selection.port = boardAndPortSelection.port;
|
||||
}
|
||||
this.setState({ selection });
|
||||
this.props.onSelect(this.state.selection);
|
||||
}
|
||||
|
||||
protected sort(items: Board[]): Board[] {
|
||||
return items.sort((a, b) => {
|
||||
if (a.name < b.name) {
|
||||
@@ -142,6 +181,18 @@ export class BoardAndPortSelectionComponent extends React.Component<BoardAndPort
|
||||
});
|
||||
}
|
||||
|
||||
protected readonly doSelect = (boardAndPortSelection: BoardAndPortSelection) => {
|
||||
const selection = this.state.selection;
|
||||
if (boardAndPortSelection.board) {
|
||||
selection.board = boardAndPortSelection.board;
|
||||
}
|
||||
if (boardAndPortSelection.port) {
|
||||
selection.port = boardAndPortSelection.port;
|
||||
}
|
||||
this.setState({ selection });
|
||||
this.props.onSelect(this.state.selection);
|
||||
}
|
||||
|
||||
protected readonly doFilter = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const boards = this.allBoards.filter(board => board.name.toLowerCase().indexOf(event.target.value.toLowerCase()) >= 0);
|
||||
this.setState({ boards })
|
||||
@@ -175,6 +226,7 @@ export class SelectBoardDialogWidget extends ReactWidget {
|
||||
protected readonly boardsNotificationService: BoardsNotificationService;
|
||||
|
||||
protected readonly onChangedEmitter = new Emitter<BoardAndPortSelection>();
|
||||
protected boardAndPortSelectionComponent: BoardAndPortSelectionComponent | null;
|
||||
|
||||
boardAndPort: BoardAndPortSelection = {};
|
||||
|
||||
@@ -189,6 +241,13 @@ export class SelectBoardDialogWidget extends ReactWidget {
|
||||
return this.onChangedEmitter.event;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
if (this.boardAndPortSelectionComponent) {
|
||||
this.boardAndPortSelectionComponent.reset();
|
||||
}
|
||||
this.boardAndPort = {};
|
||||
}
|
||||
|
||||
protected fireChanged(boardAndPort: BoardAndPortSelection): void {
|
||||
this.onChangedEmitter.fire(boardAndPort);
|
||||
}
|
||||
@@ -215,11 +274,12 @@ export class SelectBoardDialogWidget extends ReactWidget {
|
||||
Select Other Board & Port
|
||||
</div>
|
||||
<div className='text'>
|
||||
Select both a BOARD and a PORT if you want to upload a sketch.<br />
|
||||
If you only select a BOARD you will be able just to compile, but not to upload your sketch.
|
||||
<p>Select both a BOARD and a PORT if you want to upload a sketch.</p>
|
||||
<p>If you only select a BOARD you will be able just to compile,</p>
|
||||
<p>but not to upload your sketch.</p>
|
||||
</div>
|
||||
</div>
|
||||
<BoardAndPortSelectionComponent boardsService={boardsService} onSelect={this.onSelect} />
|
||||
<BoardAndPortSelectionComponent ref={ref => this.boardAndPortSelectionComponent = ref} boardsService={boardsService} onSelect={this.onSelect} />
|
||||
</div>
|
||||
</React.Fragment>
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ export class SelectBoardsDialog extends AbstractDialog<BoardAndPortSelection> {
|
||||
|
||||
protected onUpdateRequest(msg: Message) {
|
||||
super.onUpdateRequest(msg);
|
||||
|
||||
this.widget.update();
|
||||
}
|
||||
|
||||
@@ -59,8 +58,8 @@ export class SelectBoardsDialog extends AbstractDialog<BoardAndPortSelection> {
|
||||
}
|
||||
|
||||
protected isValid(value: BoardAndPortSelection): DialogError {
|
||||
if(!value.board) {
|
||||
if(value.port) {
|
||||
if (!value.board) {
|
||||
if (value.port) {
|
||||
return 'Please pick the Board connected to the Port you have selected';
|
||||
}
|
||||
return false;
|
||||
@@ -72,7 +71,13 @@ export class SelectBoardsDialog extends AbstractDialog<BoardAndPortSelection> {
|
||||
return this.widget.boardAndPort;
|
||||
}
|
||||
|
||||
protected async accept(): Promise<void> {
|
||||
super.accept();
|
||||
close(): void {
|
||||
this.widget.reset();
|
||||
super.close();
|
||||
}
|
||||
|
||||
onAfterDetach(msg: Message) {
|
||||
this.widget.reset();
|
||||
super.onAfterDetach(msg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user