feat: can dock the monitor widget to the "right"

Added a new preference (`arduino.monitor.dockPanel`) to specify the
location of the application shell where the _Serial Monitor_ widget
resides. The possible values are `"bottom"` and `"right"`. The default\
value is the `"bottom"`.

The dock panel is per application and not per workspace or window.
However, advanced users can create the `./.vscode/settings.json` and
configure per sketch preference.

Signed-off-by: dankeboy36 <dankeboy36@gmail.com>
This commit is contained in:
dankeboy36 2023-06-17 13:03:59 +02:00 committed by Akos Kitta
parent 94d2962985
commit f6a43254f5
6 changed files with 316 additions and 240 deletions

View File

@ -1,12 +1,15 @@
import { interfaces } from '@theia/core/shared/inversify';
import {
createPreferenceProxy,
PreferenceProxy,
PreferenceService,
PreferenceContribution,
PreferenceProxy,
PreferenceSchema,
PreferenceService,
createPreferenceProxy,
} from '@theia/core/lib/browser/preferences';
import { nls } from '@theia/core/lib/common';
import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
import { nls } from '@theia/core/lib/common/nls';
import { PreferenceSchemaProperty } from '@theia/core/lib/common/preferences/preference-schema';
import { interfaces } from '@theia/core/shared/inversify';
import { serialMonitorWidgetLabel } from '../common/nls';
import { CompilerWarningLiterals, CompilerWarnings } from '../common/protocol';
export enum UpdateChannel {
@ -31,7 +34,7 @@ export const ErrorRevealStrategyLiterals = [
*/
'centerIfOutsideViewport',
] as const;
export type ErrorRevealStrategy = typeof ErrorRevealStrategyLiterals[number];
export type ErrorRevealStrategy = (typeof ErrorRevealStrategyLiterals)[number];
export namespace ErrorRevealStrategy {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
export function is(arg: any): arg is ErrorRevealStrategy {
@ -40,9 +43,24 @@ export namespace ErrorRevealStrategy {
export const Default: ErrorRevealStrategy = 'centerIfOutsideViewport';
}
export const ArduinoConfigSchema: PreferenceSchema = {
type: 'object',
properties: {
export type MonitorWidgetDockPanel = Extract<
ApplicationShell.Area,
'bottom' | 'right'
>;
export const defaultMonitorWidgetDockPanel: MonitorWidgetDockPanel = 'bottom';
export function isMonitorWidgetDockPanel(
arg: unknown
): arg is MonitorWidgetDockPanel {
return arg === 'bottom' || arg === 'right';
}
type StrictPreferenceSchemaProperties<T extends object> = {
[p in keyof T]: PreferenceSchemaProperty;
};
type ArduinoPreferenceSchemaProperties =
StrictPreferenceSchemaProperties<ArduinoConfiguration> & { 'arduino.window.zoomLevel': PreferenceSchemaProperty };
const properties: ArduinoPreferenceSchemaProperties = {
'arduino.language.log': {
type: 'boolean',
description: nls.localize(
@ -258,8 +276,22 @@ export const ArduinoConfigSchema: PreferenceSchema = {
),
default: undefined,
},
'arduino.monitor.dockPanel': {
type: 'string',
enum: ['bottom', 'right'],
markdownDescription: nls.localize(
'arduino/preferences/monitor/dockPanel',
'The area of the application shell where the _{0}_ widget will reside. It is either "bottom" or "right". It defaults to "{1}".',
serialMonitorWidgetLabel,
defaultMonitorWidgetDockPanel
),
default: defaultMonitorWidgetDockPanel,
},
};
export const ArduinoConfigSchema: PreferenceSchema = {
type: 'object',
properties,
};
export interface ArduinoConfiguration {
'arduino.language.log': boolean;
@ -288,6 +320,7 @@ export interface ArduinoConfiguration {
'arduino.cli.daemon.debug': boolean;
'arduino.sketch.inoBlueprint': string;
'arduino.checkForUpdates': boolean;
'arduino.monitor.dockPanel': MonitorWidgetDockPanel;
}
export const ArduinoPreferences = Symbol('ArduinoPreferences');

View File

@ -1,6 +1,10 @@
import * as React from '@theia/core/shared/react';
import { injectable, inject } from '@theia/core/shared/inversify';
import { AbstractViewContribution, codicon } from '@theia/core/lib/browser';
import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
import {
AbstractViewContribution,
ApplicationShell,
codicon
} from '@theia/core/lib/browser';
import { MonitorWidget } from './monitor-widget';
import { MenuModelRegistry, Command, CommandRegistry } from '@theia/core';
import {
@ -13,6 +17,12 @@ import { nls } from '@theia/core/lib/common';
import { Event } from '@theia/core/lib/common/event';
import { MonitorModel } from '../../monitor-model';
import { MonitorManagerProxyClient } from '../../../common/protocol';
import {
ArduinoPreferences,
defaultMonitorWidgetDockPanel,
isMonitorWidgetDockPanel
} from '../../arduino-preferences';
import { serialMonitorWidgetLabel } from '../../../common/nls';
export namespace SerialMonitor {
export namespace Commands {
@ -51,30 +61,58 @@ export class MonitorViewContribution
MonitorWidget.ID + ':toggle-toolbar';
static readonly RESET_SERIAL_MONITOR = MonitorWidget.ID + ':reset';
constructor(
@inject(MonitorModel)
protected readonly model: MonitorModel,
private readonly model: MonitorModel;
@inject(MonitorManagerProxyClient)
protected readonly monitorManagerProxy: MonitorManagerProxyClient
) {
private readonly monitorManagerProxy: MonitorManagerProxyClient;
@inject(ArduinoPreferences)
private readonly arduinoPreferences: ArduinoPreferences;
private _panel: ApplicationShell.Area;
constructor() {
super({
widgetId: MonitorWidget.ID,
widgetName: MonitorWidget.LABEL,
widgetName: serialMonitorWidgetLabel,
defaultWidgetOptions: {
area: 'bottom',
area: defaultMonitorWidgetDockPanel,
},
toggleCommandId: MonitorViewContribution.TOGGLE_SERIAL_MONITOR,
toggleKeybinding: 'CtrlCmd+Shift+M',
});
this._panel = defaultMonitorWidgetDockPanel;
}
@postConstruct()
protected init(): void {
this._panel = this.arduinoPreferences['arduino.monitor.dockPanel'] ?? defaultMonitorWidgetDockPanel;
this.monitorManagerProxy.onMonitorShouldReset(() => this.reset());
this.arduinoPreferences.onPreferenceChanged((event) => {
if (event.preferenceName === 'arduino.monitor.dockPanel' && isMonitorWidgetDockPanel(event.newValue) && event.newValue !== this._panel) {
this._panel = event.newValue;
const widget = this.tryGetWidget();
// reopen at the new position if opened
if (widget) {
widget.close();
this.openView({ activate: true, reveal: true });
}
}
})
}
override get defaultViewOptions(): ApplicationShell.WidgetOptions {
const viewOptions = super.defaultViewOptions;
return {
...viewOptions,
area: this._panel
};
}
override registerMenus(menus: MenuModelRegistry): void {
if (this.toggleCommand) {
menus.registerMenuAction(ArduinoMenus.TOOLS__MAIN_GROUP, {
commandId: this.toggleCommand.id,
label: MonitorWidget.LABEL,
label: serialMonitorWidgetLabel,
order: '5',
});
}

View File

@ -27,13 +27,10 @@ import {
} from '../../../common/protocol';
import { MonitorModel } from '../../monitor-model';
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
import { serialMonitorWidgetLabel } from '../../../common/nls';
@injectable()
export class MonitorWidget extends ReactWidget {
static readonly LABEL = nls.localize(
'arduino/common/serialMonitor',
'Serial Monitor'
);
static readonly ID = 'serial-monitor';
protected settings: MonitorSettings = {};
@ -65,7 +62,7 @@ export class MonitorWidget extends ReactWidget {
constructor() {
super();
this.id = MonitorWidget.ID;
this.title.label = MonitorWidget.LABEL;
this.title.label = serialMonitorWidgetLabel;
this.title.iconClass = 'monitor-tab-icon';
this.title.closable = true;
this.scrollOptions = undefined;

View File

@ -20,7 +20,7 @@
.serial-monitor .head {
display: flex;
padding: 0px 5px 5px 0px;
padding: 0px 5px 5px 5px;
height: 27px;
background-color: var(--theia-activityBar-background);
}

View File

@ -19,3 +19,8 @@ export const InstallManually = nls.localize(
'arduino/common/installManually',
'Install Manually'
);
export const serialMonitorWidgetLabel = nls.localize(
'arduino/common/serialMonitor',
'Serial Monitor'
);

View File

@ -381,6 +381,9 @@
"language.log": "True if the Arduino Language Server should generate log files into the sketch folder. Otherwise, false. It's false by default.",
"language.realTimeDiagnostics": "If true, the language server provides real-time diagnostics when typing in the editor. It's false by default.",
"manualProxy": "Manual proxy configuration",
"monitor": {
"dockPanel": "The area of the application shell where the _{0}_ widget will reside. It is either \"bottom\" or \"right\". It defaults to \"{1}\"."
},
"network": "Network",
"newSketchbookLocation": "Select new sketchbook location",
"noCliConfig": "Could not load the CLI configuration",