mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-12 22:06:34 +00:00
🤞 finalized the monitor UI
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
29ebf055e6
commit
8c49c04359
@ -95,12 +95,12 @@ export class MonitorConnection {
|
||||
}
|
||||
});
|
||||
// Handles the `baudRate` changes by reconnecting if required.
|
||||
this.monitorModel.onChange(() => {
|
||||
if (this.autoConnect && this.connected) {
|
||||
this.monitorModel.onChange(({ property }) => {
|
||||
if (property === 'baudRate' && this.autoConnect && this.connected) {
|
||||
const { boardsConfig } = this.boardsServiceClient;
|
||||
this.handleBoardConfigChange(boardsConfig);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
get connected(): boolean {
|
||||
|
@ -15,7 +15,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
@inject(BoardsServiceClientImpl)
|
||||
protected readonly boardsServiceClient: BoardsServiceClientImpl;
|
||||
|
||||
protected readonly onChangeEmitter: Emitter<void>;
|
||||
protected readonly onChangeEmitter: Emitter<MonitorModel.State.Change<keyof MonitorModel.State>>;
|
||||
protected _autoscroll: boolean;
|
||||
protected _timestamp: boolean;
|
||||
protected _baudRate: MonitorConfig.BaudRate;
|
||||
@ -26,7 +26,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
this._timestamp = false;
|
||||
this._baudRate = MonitorConfig.BaudRate.DEFAULT;
|
||||
this._lineEnding = MonitorModel.EOL.DEFAULT;
|
||||
this.onChangeEmitter = new Emitter<void>();
|
||||
this.onChangeEmitter = new Emitter<MonitorModel.State.Change<keyof MonitorModel.State>>();
|
||||
}
|
||||
|
||||
onStart(): void {
|
||||
@ -37,7 +37,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
});
|
||||
}
|
||||
|
||||
get onChange(): Event<void> {
|
||||
get onChange(): Event<MonitorModel.State.Change<keyof MonitorModel.State>> {
|
||||
return this.onChangeEmitter.event;
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
toggleAutoscroll(): void {
|
||||
this._autoscroll = !this._autoscroll;
|
||||
this.storeState();
|
||||
this.storeState().then(() => this.onChangeEmitter.fire({ property: 'autoscroll', value: this._autoscroll }));
|
||||
}
|
||||
|
||||
get timestamp(): boolean {
|
||||
@ -56,7 +57,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
|
||||
toggleTimestamp(): void {
|
||||
this._timestamp = !this._timestamp;
|
||||
this.storeState();
|
||||
this.storeState().then(() => this.onChangeEmitter.fire({ property: 'timestamp', value: this._timestamp }));
|
||||
}
|
||||
|
||||
get baudRate(): MonitorConfig.BaudRate {
|
||||
@ -65,7 +66,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
|
||||
set baudRate(baudRate: MonitorConfig.BaudRate) {
|
||||
this._baudRate = baudRate;
|
||||
this.storeState().then(() => this.onChangeEmitter.fire(undefined));
|
||||
this.storeState().then(() => this.onChangeEmitter.fire({ property: 'baudRate', value: this._baudRate }));
|
||||
}
|
||||
|
||||
get lineEnding(): MonitorModel.EOL {
|
||||
@ -74,7 +75,7 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
|
||||
set lineEnding(lineEnding: MonitorModel.EOL) {
|
||||
this._lineEnding = lineEnding;
|
||||
this.storeState();
|
||||
this.storeState().then(() => this.onChangeEmitter.fire({ property: 'lineEnding', value: this._lineEnding }));
|
||||
}
|
||||
|
||||
protected restoreState(state: MonitorModel.State) {
|
||||
@ -82,7 +83,6 @@ export class MonitorModel implements FrontendApplicationContribution {
|
||||
this._timestamp = state.timestamp;
|
||||
this._baudRate = state.baudRate;
|
||||
this._lineEnding = state.lineEnding;
|
||||
this.onChangeEmitter.fire(undefined);
|
||||
}
|
||||
|
||||
protected async storeState(): Promise<void> {
|
||||
@ -104,6 +104,12 @@ export namespace MonitorModel {
|
||||
baudRate: MonitorConfig.BaudRate;
|
||||
lineEnding: EOL;
|
||||
}
|
||||
export namespace State {
|
||||
export interface Change<K extends keyof State> {
|
||||
readonly property: K;
|
||||
readonly value: State[K];
|
||||
}
|
||||
}
|
||||
|
||||
export type EOL = '' | '\n' | '\r' | '\r\n';
|
||||
export namespace EOL {
|
||||
|
@ -59,13 +59,13 @@ export class MonitorViewContribution extends AbstractViewContribution<MonitorWid
|
||||
id: 'monitor-autoscroll',
|
||||
render: () => this.renderAutoScrollButton(),
|
||||
isVisible: widget => widget instanceof MonitorWidget,
|
||||
onDidChange: this.model.onChange
|
||||
onDidChange: this.model.onChange as any // TODO: https://github.com/eclipse-theia/theia/pull/6696/
|
||||
});
|
||||
registry.registerItem({
|
||||
id: 'monitor-timestamp',
|
||||
render: () => this.renderTimestampButton(),
|
||||
isVisible: widget => widget instanceof MonitorWidget,
|
||||
onDidChange: this.model.onChange
|
||||
onDidChange: this.model.onChange as any // TODO: https://github.com/eclipse-theia/theia/pull/6696/
|
||||
});
|
||||
registry.registerItem({
|
||||
id: SerialMonitor.Commands.CLEAR_OUTPUT.id,
|
||||
|
@ -88,7 +88,7 @@ export class MonitorWidget extends ReactWidget {
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
label: 'Newline',
|
||||
label: 'New Line',
|
||||
value: '\n'
|
||||
},
|
||||
{
|
||||
@ -99,7 +99,7 @@ export class MonitorWidget extends ReactWidget {
|
||||
label: 'Both NL & CR',
|
||||
value: '\r\n'
|
||||
}
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
protected get baudRates(): OptionsType<SelectOption<MonitorConfig.BaudRate>> {
|
||||
@ -111,28 +111,33 @@ export class MonitorWidget extends ReactWidget {
|
||||
const { baudRates, lineEndings } = this;
|
||||
const lineEnding = lineEndings.find(item => item.value === this.monitorModel.lineEnding) || lineEndings[1]; // Defaults to `\n`.
|
||||
const baudRate = baudRates.find(item => item.value === this.monitorModel.baudRate) || baudRates[4]; // Defaults to `9600`.
|
||||
return <div className='serial-monitor-container'>
|
||||
return <div className='serial-monitor'>
|
||||
<div className='head'>
|
||||
<div className='send'>
|
||||
<SerialMonitorSendField
|
||||
<SerialMonitorSendInput
|
||||
monitorConfig={this.monitorConnection.monitorConfig}
|
||||
resolveFocus={this.onFocusResolved}
|
||||
onSend={this.onSend} />
|
||||
</div>
|
||||
<div className='config'>
|
||||
<ArduinoSelect
|
||||
maxMenuHeight={this.widgetHeight - 40}
|
||||
options={lineEndings}
|
||||
defaultValue={lineEnding}
|
||||
onChange={this.onChangeLineEnding} />,
|
||||
<ArduinoSelect
|
||||
maxMenuHeight={this.widgetHeight - 40}
|
||||
options={baudRates}
|
||||
defaultValue={baudRate}
|
||||
onChange={this.onChangeBaudRate} />
|
||||
<div className='select'>
|
||||
<ArduinoSelect
|
||||
maxMenuHeight={this.widgetHeight - 40}
|
||||
options={lineEndings}
|
||||
defaultValue={lineEnding}
|
||||
onChange={this.onChangeLineEnding} />
|
||||
</div>
|
||||
<div className='select'>
|
||||
<ArduinoSelect
|
||||
className='select'
|
||||
maxMenuHeight={this.widgetHeight - 40}
|
||||
options={baudRates}
|
||||
defaultValue={baudRate}
|
||||
onChange={this.onChangeBaudRate} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id='serial-monitor-output-container'>
|
||||
<div className='body'>
|
||||
<SerialMonitorOutput
|
||||
monitorModel={this.monitorModel}
|
||||
monitorServiceClient={this.monitorServiceClient}
|
||||
@ -157,7 +162,7 @@ export class MonitorWidget extends ReactWidget {
|
||||
|
||||
}
|
||||
|
||||
export namespace SerialMonitorSendField {
|
||||
export namespace SerialMonitorSendInput {
|
||||
export interface Props {
|
||||
readonly monitorConfig?: MonitorConfig;
|
||||
readonly onSend: (text: string) => void;
|
||||
@ -168,9 +173,9 @@ export namespace SerialMonitorSendField {
|
||||
}
|
||||
}
|
||||
|
||||
export class SerialMonitorSendField extends React.Component<SerialMonitorSendField.Props, SerialMonitorSendField.State> {
|
||||
export class SerialMonitorSendInput extends React.Component<SerialMonitorSendInput.Props, SerialMonitorSendInput.State> {
|
||||
|
||||
constructor(props: SerialMonitorSendField.Props) {
|
||||
constructor(props: Readonly<SerialMonitorSendInput.Props>) {
|
||||
super(props);
|
||||
this.state = { value: '' };
|
||||
this.onChange = this.onChange.bind(this);
|
||||
@ -235,6 +240,7 @@ export namespace SerialMonitorOutput {
|
||||
}
|
||||
export interface State {
|
||||
content: string;
|
||||
timestamp: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,7 +254,7 @@ export class SerialMonitorOutput extends React.Component<SerialMonitorOutput.Pro
|
||||
|
||||
constructor(props: Readonly<SerialMonitorOutput.Props>) {
|
||||
super(props);
|
||||
this.state = { content: '' };
|
||||
this.state = { content: '', timestamp: this.props.monitorModel.timestamp };
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
@ -270,11 +276,17 @@ export class SerialMonitorOutput extends React.Component<SerialMonitorOutput.Pro
|
||||
if (eolIndex !== -1) {
|
||||
const line = chunk.substring(0, eolIndex + 1);
|
||||
chunk = chunk.slice(eolIndex + 1);
|
||||
const content = `${this.state.content}${false ? `${dateFormat(new Date(), 'H:M:ss.l')} -> ` : ''}${line}`;
|
||||
const content = `${this.state.content}${this.state.timestamp ? `${dateFormat(new Date(), 'H:M:ss.l')} -> ` : ''}${line}`;
|
||||
this.setState({ content });
|
||||
}
|
||||
}),
|
||||
this.props.clearConsoleEvent(() => this.setState({ content: '' }))
|
||||
this.props.clearConsoleEvent(() => this.setState({ content: '' })),
|
||||
this.props.monitorModel.onChange(({ property }) => {
|
||||
if (property === 'timestamp') {
|
||||
const { timestamp } = this.props.monitorModel;
|
||||
this.setState({ timestamp });
|
||||
}
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
||||
@ -283,7 +295,8 @@ export class SerialMonitorOutput extends React.Component<SerialMonitorOutput.Pro
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
this.toDisposeBeforeUnmount.dispose()
|
||||
// TODO: "Your preferred browser's local storage is almost full." Discard `content` before saving layout?
|
||||
this.toDisposeBeforeUnmount.dispose();
|
||||
}
|
||||
|
||||
protected scrollToBottom(): void {
|
||||
|
@ -5,51 +5,49 @@
|
||||
background-position-x: 19px;
|
||||
}
|
||||
|
||||
.serial-monitor-container {
|
||||
.serial-monitor {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head {
|
||||
.serial-monitor .head {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
background: var(--theia-layout-color0);
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send {
|
||||
.serial-monitor .head .send {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send > input {
|
||||
.serial-monitor .head .send > input {
|
||||
line-height: var(--theia-content-line-height);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send > input:focus {
|
||||
.serial-monitor .head .send > input:focus {
|
||||
border-color: var(--theia-accent-color3);
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send > input.not-connected {
|
||||
.serial-monitor .head .send > input.not-connected {
|
||||
background-color: var(--theia-warn-color0);
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send input#serial-monitor-send {
|
||||
color: var(--theia-ui-font-color1);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .config {
|
||||
.serial-monitor .head .config {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#serial-monitor-output-container {
|
||||
.serial-monitor .head .config .select {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.serial-monitor .body {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
padding: 6px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-monitor {
|
||||
|
Loading…
x
Reference in New Issue
Block a user