Skip to content

Commit 1f544b2

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommitted
ATL-546: Added UI for settings.
Signed-off-by: Akos Kitta <[email protected]>
1 parent 1742c53 commit 1f544b2

24 files changed

+1374
-159
lines changed

Diff for: arduino-ide-extension/src/browser/arduino-frontend-contribution.tsx

+35-20
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const debounce = require('lodash.debounce');
12
import { MAIN_MENU_BAR, MenuContribution, MenuModelRegistry, SelectionService, ILogger } from '@theia/core';
23
import {
34
ContextMenuRenderer,
@@ -23,6 +24,7 @@ import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspac
2324
import { TerminalMenus } from '@theia/terminal/lib/browser/terminal-frontend-contribution';
2425
import { inject, injectable, postConstruct } from 'inversify';
2526
import * as React from 'react';
27+
import { remote } from 'electron';
2628
import { MainMenuManager } from '../common/main-menu-manager';
2729
import { BoardsService, CoreService, Port, SketchesService, ExecutableService } from '../common/protocol';
2830
import { ArduinoDaemon } from '../common/protocol/arduino-daemon';
@@ -42,11 +44,9 @@ import { WorkspaceService } from './theia/workspace/workspace-service';
4244
import { ArduinoToolbar } from './toolbar/arduino-toolbar';
4345
import { HostedPluginSupport } from '@theia/plugin-ext/lib/hosted/browser/hosted-plugin';
4446
import { FileService } from '@theia/filesystem/lib/browser/file-service';
45-
46-
const debounce = require('lodash.debounce');
4747
import { OutputService } from '../common/protocol/output-service';
48-
import { NotificationCenter } from './notification-center';
49-
import { Settings } from './contributions/settings';
48+
import { ArduinoPreferences } from './arduino-preferences';
49+
import { SketchesServiceClientImpl } from '../common/protocol/sketches-service-client-impl';
5050

5151
@injectable()
5252
export class ArduinoFrontendContribution implements FrontendApplicationContribution,
@@ -147,11 +147,15 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
147147

148148
@inject(ExecutableService)
149149
protected executableService: ExecutableService;
150+
150151
@inject(OutputService)
151152
protected readonly outputService: OutputService;
152153

153-
@inject(NotificationCenter)
154-
protected readonly notificationCenter: NotificationCenter;
154+
@inject(ArduinoPreferences)
155+
protected readonly arduinoPreferences: ArduinoPreferences;
156+
157+
@inject(SketchesServiceClientImpl)
158+
protected readonly sketchServiceClient: SketchesServiceClientImpl;
155159

156160
protected invalidConfigPopup: Promise<void | 'No' | 'Yes' | undefined> | undefined;
157161

@@ -192,35 +196,45 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
192196
viewContribution.initializeLayout(app);
193197
}
194198
}
195-
this.boardsServiceClientImpl.onBoardsConfigChanged(async ({ selectedBoard }) => {
199+
const start = async ({ selectedBoard }: BoardsConfig.Config) => {
196200
if (selectedBoard) {
197201
const { name, fqbn } = selectedBoard;
198202
if (fqbn) {
199203
await this.hostedPluginSupport.didStart;
200204
this.startLanguageServer(fqbn, name);
201205
}
202206
}
207+
};
208+
this.boardsServiceClientImpl.onBoardsConfigChanged(start);
209+
this.arduinoPreferences.onPreferenceChanged(event => {
210+
if (event.preferenceName === 'arduino.language.log' && event.newValue !== event.oldValue) {
211+
start(this.boardsServiceClientImpl.boardsConfig);
212+
}
203213
});
204-
this.notificationCenter.onConfigChanged(({ config }) => {
205-
if (config) {
206-
this.invalidConfigPopup = undefined;
207-
} else {
208-
if (!this.invalidConfigPopup) {
209-
this.invalidConfigPopup = this.messageService.error(`Your CLI configuration is invalid. Do you want to correct it now?`, 'No', 'Yes')
210-
.then(answer => {
211-
if (answer === 'Yes') {
212-
this.commandRegistry.executeCommand(Settings.Commands.OPEN_CLI_CONFIG.id)
213-
}
214-
this.invalidConfigPopup = undefined;
215-
});
216-
}
214+
this.arduinoPreferences.ready.then(() => {
215+
const webContents = remote.getCurrentWebContents();
216+
const zoomLevel = this.arduinoPreferences.get('arduino.window.zoomLevel');
217+
webContents.setZoomLevel(zoomLevel);
218+
});
219+
this.arduinoPreferences.onPreferenceChanged(event => {
220+
if (event.preferenceName === 'arduino.window.zoomLevel' && typeof event.newValue === 'number' && event.newValue !== event.oldValue) {
221+
const webContents = remote.getCurrentWebContents();
222+
webContents.setZoomLevel(event.newValue || 0);
217223
}
218224
});
219225
}
220226

221227
protected startLanguageServer = debounce((fqbn: string, name: string | undefined) => this.doStartLanguageServer(fqbn, name));
222228
protected async doStartLanguageServer(fqbn: string, name: string | undefined): Promise<void> {
223229
this.logger.info(`Starting language server: ${fqbn}`);
230+
const log = this.arduinoPreferences.get('arduino.language.log');
231+
let currentSketchPath: string | undefined = undefined;
232+
if (log) {
233+
const currentSketch = await this.sketchServiceClient.currentSketch();
234+
if (currentSketch) {
235+
currentSketchPath = await this.fileSystem.fsPath(new URI(currentSketch.uri));
236+
}
237+
}
224238
const { clangdUri, cliUri, lsUri } = await this.executableService.list();
225239
const [clangdPath, cliPath, lsPath] = await Promise.all([
226240
this.fileSystem.fsPath(new URI(clangdUri)),
@@ -231,6 +245,7 @@ export class ArduinoFrontendContribution implements FrontendApplicationContribut
231245
lsPath,
232246
cliPath,
233247
clangdPath,
248+
log: currentSketchPath ? currentSketchPath : log,
234249
board: {
235250
fqbn,
236251
name: name ? `"${name}"` : undefined

Diff for: arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts

+14
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ import { DebugFrontendApplicationContribution as TheiaDebugFrontendApplicationCo
136136
import { BoardSelection } from './contributions/board-selection';
137137
import { OpenRecentSketch } from './contributions/open-recent-sketch';
138138
import { Help } from './contributions/help';
139+
import { bindArduinoPreferences } from './arduino-preferences'
140+
import { SettingsService, SettingsDialog, SettingsWidget, SettingsDialogProps } from './settings';
139141

140142
const ElementQueries = require('css-element-queries/src/ElementQueries');
141143

@@ -375,4 +377,16 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
375377
// To remove the `Run` menu item from the application menu.
376378
bind(DebugFrontendApplicationContribution).toSelf().inSingletonScope();
377379
rebind(TheiaDebugFrontendApplicationContribution).toService(DebugFrontendApplicationContribution);
380+
381+
// Preferences
382+
bindArduinoPreferences(bind);
383+
384+
// Settings wrapper for the preferences and the CLI config.
385+
bind(SettingsService).toSelf().inSingletonScope();
386+
// Settings dialog and widget
387+
bind(SettingsWidget).toSelf().inSingletonScope();
388+
bind(SettingsDialog).toSelf().inSingletonScope();
389+
bind(SettingsDialogProps).toConstantValue({
390+
title: 'Preferences'
391+
});
378392
});
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { interfaces } from 'inversify';
2+
import {
3+
createPreferenceProxy,
4+
PreferenceProxy,
5+
PreferenceService,
6+
PreferenceContribution,
7+
PreferenceSchema
8+
} from '@theia/core/lib/browser/preferences';
9+
10+
export const ArduinoConfigSchema: PreferenceSchema = {
11+
'type': 'object',
12+
'properties': {
13+
'arduino.language.log': {
14+
'type': 'boolean',
15+
'description': "True if the Arduino Language Server should generate log files into the sketch folder. Otherwise, false. It's false by default.",
16+
'default': false
17+
},
18+
'arduino.compile.verbose': {
19+
'type': 'boolean',
20+
'description': 'True for verbose compile output.',
21+
'default': true
22+
},
23+
'arduino.upload.verbose': {
24+
'type': 'boolean',
25+
'description': 'True for verbose upload output.',
26+
'default': true
27+
},
28+
'arduino.upload.verify': {
29+
'type': 'boolean',
30+
'default': false
31+
},
32+
'arduino.window.autoScale': {
33+
'type': 'boolean',
34+
'description': 'True if the user interface automatically scales with the font size.',
35+
'default': true
36+
},
37+
'arduino.window.zoomLevel': {
38+
'type': 'number',
39+
'description': 'Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.',
40+
'default': 0
41+
},
42+
'arduino.ide.autoUpdate': {
43+
'type': 'boolean',
44+
'description': 'True to enable automatic update checks. The IDE will check for updates automatically and periodically.',
45+
'default': true
46+
}
47+
}
48+
};
49+
50+
export interface ArduinoConfiguration {
51+
'arduino.language.log': boolean;
52+
'arduino.compile.verbose': boolean;
53+
'arduino.upload.verbose': boolean;
54+
'arduino.upload.verify': boolean;
55+
'arduino.window.autoScale': boolean;
56+
'arduino.window.zoomLevel': number;
57+
'arduino.ide.autoUpdate': boolean;
58+
}
59+
60+
export const ArduinoPreferences = Symbol('ArduinoPreferences');
61+
export type ArduinoPreferences = PreferenceProxy<ArduinoConfiguration>;
62+
63+
export function createArduinoPreferences(preferences: PreferenceService): ArduinoPreferences {
64+
return createPreferenceProxy(preferences, ArduinoConfigSchema);
65+
}
66+
67+
export function bindArduinoPreferences(bind: interfaces.Bind): void {
68+
bind(ArduinoPreferences).toDynamicValue(ctx => {
69+
const preferences = ctx.container.get<PreferenceService>(PreferenceService);
70+
return createArduinoPreferences(preferences);
71+
});
72+
bind(PreferenceContribution).toConstantValue({ schema: ArduinoConfigSchema });
73+
}

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

+16-5
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
5757
* See: https://arduino.slack.com/archives/CJJHJCJSJ/p1568645417013000?thread_ts=1568640504.009400&cid=CJJHJCJSJ
5858
*/
5959
protected latestValidBoardsConfig: RecursiveRequired<BoardsConfig.Config> | undefined = undefined;
60+
protected latestBoardsConfig: BoardsConfig.Config | undefined = undefined;
6061
protected _boardsConfig: BoardsConfig.Config = {};
6162
protected _attachedBoards: Board[] = []; // This does not contain the `Unknown` boards. They're visible from the available ports only.
6263
protected _availablePorts: Port[] = [];
@@ -187,6 +188,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
187188
protected doSetBoardsConfig(config: BoardsConfig.Config): void {
188189
this.logger.info('Board config changed: ', JSON.stringify(config));
189190
this._boardsConfig = config;
191+
this.latestBoardsConfig = this._boardsConfig;
190192
if (this.canUploadTo(this._boardsConfig)) {
191193
this.latestValidBoardsConfig = this._boardsConfig;
192194
}
@@ -384,7 +386,10 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
384386
const key = this.getLastSelectedBoardOnPortKey(selectedPort);
385387
await this.storageService.setData(key, selectedBoard);
386388
}
387-
await this.storageService.setData('latest-valid-boards-config', this.latestValidBoardsConfig);
389+
await Promise.all([
390+
this.storageService.setData('latest-valid-boards-config', this.latestValidBoardsConfig),
391+
this.storageService.setData('latest-boards-config', this.latestBoardsConfig)
392+
]);
388393
}
389394

390395
protected getLastSelectedBoardOnPortKey(port: Port | string): string {
@@ -393,15 +398,21 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
393398
}
394399

395400
protected async loadState(): Promise<void> {
396-
const storedValidBoardsConfig = await this.storageService.getData<RecursiveRequired<BoardsConfig.Config>>('latest-valid-boards-config');
397-
if (storedValidBoardsConfig) {
398-
this.latestValidBoardsConfig = storedValidBoardsConfig;
401+
const storedLatestValidBoardsConfig = await this.storageService.getData<RecursiveRequired<BoardsConfig.Config>>('latest-valid-boards-config');
402+
if (storedLatestValidBoardsConfig) {
403+
this.latestValidBoardsConfig = storedLatestValidBoardsConfig;
399404
if (this.canUploadTo(this.latestValidBoardsConfig)) {
400405
this.boardsConfig = this.latestValidBoardsConfig;
401406
}
407+
} else {
408+
// If we could not restore the latest valid config, try to restore something, the board at least.
409+
const storedLatestBoardsConfig = await this.storageService.getData<BoardsConfig.Config | undefined>('latest-boards-config');
410+
if (storedLatestBoardsConfig) {
411+
this.latestBoardsConfig = storedLatestBoardsConfig;
412+
this.boardsConfig = this.latestBoardsConfig;
413+
}
402414
}
403415
}
404-
405416
}
406417

407418
/**

Diff for: arduino-ide-extension/src/browser/contributions/burn-bootloader.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,19 @@ export class BurnBootloader extends SketchContribution {
4747
try {
4848
const { boardsConfig } = this.boardsServiceClientImpl;
4949
const port = boardsConfig.selectedPort?.address;
50-
const [fqbn, { selectedProgrammer: programmer }] = await Promise.all([
50+
const [fqbn, { selectedProgrammer: programmer }, verify, verbose] = await Promise.all([
5151
this.boardsDataStore.appendConfigToFqbn(boardsConfig.selectedBoard?.fqbn),
52-
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn)
52+
this.boardsDataStore.getData(boardsConfig.selectedBoard?.fqbn),
53+
this.preferences.get('arduino.upload.verify'),
54+
this.preferences.get('arduino.upload.verbose')
5355
]);
5456
this.outputChannelManager.getChannel('Arduino: bootloader').clear();
5557
await this.coreService.burnBootloader({
5658
fqbn,
5759
programmer,
58-
port
60+
port,
61+
verify,
62+
verbose
5963
});
6064
this.messageService.info('Done burning bootloader.', { timeout: 1000 });
6165
} catch (e) {

Diff for: arduino-ide-extension/src/browser/contributions/contribution.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ import { open, OpenerService } from '@theia/core/lib/browser/opener-service';
1010
import { MenuModelRegistry, MenuContribution } from '@theia/core/lib/common/menu';
1111
import { KeybindingRegistry, KeybindingContribution } from '@theia/core/lib/browser/keybinding';
1212
import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
13+
import { FrontendApplicationContribution, FrontendApplication } from '@theia/core/lib/browser/frontend-application';
1314
import { Command, CommandRegistry, CommandContribution, CommandService } from '@theia/core/lib/common/command';
1415
import { EditorMode } from '../editor-mode';
16+
import { SettingsService } from '../settings';
1517
import { SketchesServiceClientImpl } from '../../common/protocol/sketches-service-client-impl';
1618
import { SketchesService, ConfigService, FileSystemExt, Sketch } from '../../common/protocol';
17-
import { FrontendApplicationContribution, FrontendApplication } from '@theia/core/lib/browser';
19+
import { ArduinoPreferences } from '../arduino-preferences';
1820

1921
export { Command, CommandRegistry, MenuModelRegistry, KeybindingRegistry, TabBarToolbarRegistry, URI, Sketch, open };
2022

@@ -39,6 +41,9 @@ export abstract class Contribution implements CommandContribution, MenuContribut
3941
@inject(LabelProvider)
4042
protected readonly labelProvider: LabelProvider;
4143

44+
@inject(SettingsService)
45+
protected readonly settingsService: SettingsService;
46+
4247
onStart(app: FrontendApplication): MaybePromise<void> {
4348
}
4449

@@ -77,6 +82,9 @@ export abstract class SketchContribution extends Contribution {
7782
@inject(SketchesServiceClientImpl)
7883
protected readonly sketchServiceClient: SketchesServiceClientImpl;
7984

85+
@inject(ArduinoPreferences)
86+
protected readonly preferences: ArduinoPreferences;
87+
8088
}
8189

8290
export namespace Contribution {

Diff for: arduino-ide-extension/src/browser/contributions/edit-contributions.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { CommonCommands } from '@theia/core/lib/browser/common-frontend-contribu
33
import { ClipboardService } from '@theia/core/lib/browser/clipboard-service';
44
import { PreferenceService } from '@theia/core/lib/browser/preferences/preference-service';
55
import { MonacoEditorService } from '@theia/monaco/lib/browser/monaco-editor-service';
6-
import { EDITOR_FONT_DEFAULTS } from '@theia/editor/lib/browser/editor-preferences';
76
import { Contribution, Command, MenuModelRegistry, KeybindingRegistry, CommandRegistry } from './contribution';
87
import { ArduinoMenus } from '../menu/arduino-menus';
98

@@ -31,10 +30,28 @@ export class EditContributions extends Contribution {
3130
registry.registerCommand(EditContributions.Commands.FIND_PREVIOUS, { execute: () => this.run('editor.action.nextMatchFindAction') });
3231
registry.registerCommand(EditContributions.Commands.USE_FOR_FIND, { execute: () => this.run('editor.action.previousSelectionMatchFindAction') });
3332
registry.registerCommand(EditContributions.Commands.INCREASE_FONT_SIZE, {
34-
execute: () => this.preferences.set('editor.fontSize', this.preferences.get('editor.fontSize', EDITOR_FONT_DEFAULTS.fontSize) + 1)
33+
execute: async () => {
34+
const settings = await this.settingsService.settings();
35+
if (settings.autoScaleInterface) {
36+
settings.interfaceScale = settings.interfaceScale + 1;
37+
} else {
38+
settings.editorFontSize = settings.editorFontSize + 1;
39+
}
40+
await this.settingsService.update(settings);
41+
await this.settingsService.save();
42+
}
3543
});
3644
registry.registerCommand(EditContributions.Commands.DECREASE_FONT_SIZE, {
37-
execute: () => this.preferences.set('editor.fontSize', this.preferences.get('editor.fontSize', EDITOR_FONT_DEFAULTS.fontSize) - 1)
45+
execute: async () => {
46+
const settings = await this.settingsService.settings();
47+
if (settings.autoScaleInterface) {
48+
settings.interfaceScale = settings.interfaceScale - 1;
49+
} else {
50+
settings.editorFontSize = settings.editorFontSize - 1;
51+
}
52+
await this.settingsService.update(settings);
53+
await this.settingsService.save();
54+
}
3855
});
3956
/* Tools */registry.registerCommand(EditContributions.Commands.AUTO_FORMAT, { execute: () => this.run('editor.action.formatDocument') });
4057
registry.registerCommand(EditContributions.Commands.COPY_FOR_FORUM, {

0 commit comments

Comments
 (0)