Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c6a1db4

Browse files
author
Akos Kitta
committed
ATL-1106: Made all non-workspace editors read-only.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
1 parent f6e623c commit c6a1db4

File tree

5 files changed

+133
-46
lines changed

5 files changed

+133
-46
lines changed

‎arduino-ide-extension/src/browser/arduino-ide-frontend-module.ts‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ import { ListItemRenderer } from './widgets/component-list/list-item-renderer';
6767
import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution';
6868
import { MonacoThemingService } from '@theia/monaco/lib/browser/monaco-theming-service';
6969
import { ArduinoDaemonPath, ArduinoDaemon } from '../common/protocol/arduino-daemon';
70-
import { EditorManager as TheiaEditorManager, EditorCommandContribution as TheiaEditorCommandContribution } from '@theia/editor/lib/browser';
71-
import { EditorManager } from './theia/editor/editor-manager';
70+
import { EditorCommandContribution as TheiaEditorCommandContribution } from '@theia/editor/lib/browser';
7271
import { FrontendConnectionStatusService, ApplicationConnectionStatusContribution } from './theia/core/connection-status-service';
7372
import {
7473
FrontendConnectionStatusService as TheiaFrontendConnectionStatusService,
@@ -153,6 +152,8 @@ import { SearchInWorkspaceWidget as TheiaSearchInWorkspaceWidget } from '@theia/
153152
import { SearchInWorkspaceWidget } from './theia/search-in-workspace/search-in-workspace-widget';
154153
import { SearchInWorkspaceResultTreeWidget as TheiaSearchInWorkspaceResultTreeWidget } from '@theia/search-in-workspace/lib/browser/search-in-workspace-result-tree-widget';
155154
import { SearchInWorkspaceResultTreeWidget } from './theia/search-in-workspace/search-in-workspace-result-tree-widget';
155+
import { MonacoEditorProvider } from './theia/monaco/monaco-editor-provider';
156+
import { MonacoEditorProvider as TheiaMonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
156157

157158
const ElementQueries = require('css-element-queries/src/ElementQueries');
158159

@@ -305,6 +306,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
305306
rebind(TheiaOutputChannelRegistryMainImpl).toService(OutputChannelRegistryMainImpl);
306307
bind(MonacoTextModelService).toSelf().inSingletonScope();
307308
rebind(TheiaMonacoTextModelService).toService(MonacoTextModelService);
309+
bind(MonacoEditorProvider).toSelf().inSingletonScope();
310+
rebind(TheiaMonacoEditorProvider).toService(MonacoEditorProvider);
308311

309312
bind(SearchInWorkspaceWidget).toSelf();
310313
rebind(TheiaSearchInWorkspaceWidget).toService(SearchInWorkspaceWidget);
@@ -321,10 +324,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
321324
bind(FrontendConnectionStatusService).toSelf().inSingletonScope();
322325
rebind(TheiaFrontendConnectionStatusService).toService(FrontendConnectionStatusService);
323326

324-
// Editor customizations. Sets the editor to `readOnly` if under the data dir.
325-
bind(EditorManager).toSelf().inSingletonScope();
326-
rebind(TheiaEditorManager).toService(EditorManager);
327-
328327
// Decorator customizations
329328
bind(TabBarDecoratorService).toSelf().inSingletonScope();
330329
rebind(TheiaTabBarDecoratorService).toService(TabBarDecoratorService);

‎arduino-ide-extension/src/browser/theia/editor/editor-manager.ts‎

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { inject, injectable } from 'inversify';
2+
import URI from '@theia/core/lib/common/uri';
3+
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
4+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
5+
import { MonacoEditorProvider as TheiaMonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
6+
import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
7+
8+
type CancelablePromise = Promise<monaco.referenceSearch.ReferencesModel> & { cancel: () => void };
9+
interface EditorFactory {
10+
(override: monaco.editor.IEditorOverrideServices, toDispose: DisposableCollection): Promise<MonacoEditor>;
11+
}
12+
13+
@injectable()
14+
export class MonacoEditorProvider extends TheiaMonacoEditorProvider {
15+
16+
@inject(SketchesServiceClientImpl)
17+
protected readonly sketchesServiceClient: SketchesServiceClientImpl;
18+
19+
protected async doCreateEditor(uri: URI, factory: EditorFactory): Promise<MonacoEditor> {
20+
const editor = await super.doCreateEditor(uri, factory);
21+
const toDispose = new DisposableCollection();
22+
toDispose.push(this.installCustomReferencesController(editor));
23+
toDispose.push(editor.onDispose(() => toDispose.dispose()));
24+
return editor;
25+
}
26+
27+
private installCustomReferencesController(editor: MonacoEditor): Disposable {
28+
const control = editor.getControl();
29+
const referencesController = control._contributions['editor.contrib.referencesController'];
30+
const originalToggleWidget = referencesController.toggleWidget;
31+
const toDispose = new DisposableCollection();
32+
const toDisposeBeforeToggleWidget = new DisposableCollection();
33+
referencesController.toggleWidget = (range: monaco.Range, modelPromise: CancelablePromise, peekMode: boolean) => {
34+
toDisposeBeforeToggleWidget.dispose();
35+
originalToggleWidget.bind(referencesController)(range, modelPromise, peekMode);
36+
if (referencesController._widget) {
37+
if ('onDidClose' in referencesController._widget) {
38+
toDisposeBeforeToggleWidget.push((referencesController._widget as any).onDidClose(() => toDisposeBeforeToggleWidget.dispose()));
39+
}
40+
const preview = (referencesController._widget as any)._preview as monaco.editor.ICodeEditor;
41+
if (preview) {
42+
toDisposeBeforeToggleWidget.push(preview.onDidChangeModel(() => this.updateReadOnlyState(preview)))
43+
this.updateReadOnlyState(preview);
44+
}
45+
}
46+
};
47+
toDispose.push(Disposable.create(() => toDisposeBeforeToggleWidget.dispose()));
48+
toDispose.push(Disposable.create(() => referencesController.toggleWidget = originalToggleWidget));
49+
return toDispose;
50+
}
51+
52+
private updateReadOnlyState(editor: monaco.editor.ICodeEditor | undefined): void {
53+
if (!editor) {
54+
return;
55+
}
56+
const model = editor.getModel();
57+
if (!model) {
58+
return;
59+
}
60+
const readOnly = this.sketchesServiceClient.isReadOnly(model.uri);
61+
editor.updateOptions({ readOnly });
62+
}
63+
64+
}
Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
1-
import { injectable } from 'inversify';
1+
import { inject,injectable } from 'inversify';
22
import { Resource } from '@theia/core/lib/common/resource';
3-
import { MaybePromise } from '@theia/core/lib/common/types';
4-
import { Log, Loggable } from '@theia/core/lib/common/logger';
3+
import { ILogger, Log, Loggable } from '@theia/core/lib/common/logger';
54
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
5+
import { EditorPreferences } from '@theia/editor/lib/browser/editor-preferences';
6+
import { MonacoToProtocolConverter } from '@theia/monaco/lib/browser/monaco-to-protocol-converter';
7+
import { ProtocolToMonacoConverter } from '@theia/monaco/lib/browser/protocol-to-monaco-converter';
68
import { MonacoTextModelService as TheiaMonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
9+
import { SketchesServiceClientImpl } from '../../../common/protocol/sketches-service-client-impl';
710

811
@injectable()
912
export class MonacoTextModelService extends TheiaMonacoTextModelService {
1013

11-
protected createModel(resource: Resource): MaybePromise<MonacoEditorModel> {
14+
@inject(SketchesServiceClientImpl)
15+
protected readonly sketchesServiceClient: SketchesServiceClientImpl;
16+
17+
protected async createModel(resource: Resource): Promise<MonacoEditorModel> {
1218
const factory = this.factories.getContributions().find(({ scheme }) => resource.uri.scheme === scheme);
13-
return factory ? factory.createModel(resource) : new SilentMonacoEditorModel(resource, this.m2p, this.p2m, this.logger);
19+
const readOnly = this.sketchesServiceClient.isReadOnly(resource.uri);
20+
return factory ? factory.createModel(resource) : new MaybeReadonlyMonacoEditorModel(resource, this.m2p, this.p2m, this.logger, undefined, readOnly);
1421
}
1522

1623
}
1724

1825
// https://github.com/eclipse-theia/theia/pull/8491
19-
exportclass SilentMonacoEditorModel extends MonacoEditorModel {
26+
class SilentMonacoEditorModel extends MonacoEditorModel {
2027

2128
protected trace(loggable: Loggable): void {
2229
if (this.logger) {
@@ -27,3 +34,41 @@ export class SilentMonacoEditorModel extends MonacoEditorModel {
2734
}
2835

2936
}
37+
38+
class MaybeReadonlyMonacoEditorModel extends SilentMonacoEditorModel {
39+
40+
constructor(
41+
protected readonly resource: Resource,
42+
protected readonly m2p: MonacoToProtocolConverter,
43+
protected readonly p2m: ProtocolToMonacoConverter,
44+
protected readonly logger?: ILogger,
45+
protected readonly editorPreferences?: EditorPreferences,
46+
protected readonly _readOnly?: boolean,
47+
) {
48+
super(resource, m2p, p2m, logger, editorPreferences)
49+
}
50+
51+
get readOnly(): boolean {
52+
if (typeof this._readOnly === 'boolean') {
53+
return this._readOnly;
54+
}
55+
return this.resource.saveContents === undefined;
56+
}
57+
58+
protected setDirty(dirty: boolean): void {
59+
if (this._readOnly === true) {
60+
// NOOP
61+
return;
62+
}
63+
if (dirty === this._dirty) {
64+
return;
65+
}
66+
this._dirty = dirty;
67+
if (dirty === false) {
68+
(this as any).updateSavedVersionId();
69+
}
70+
this.onDirtyChangedEmitter.fire(undefined);
71+
}
72+
73+
74+
}

‎arduino-ide-extension/src/common/protocol/sketches-service-client-impl.ts‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { inject, injectable } from 'inversify';
22
import URI from '@theia/core/lib/common/uri';
3+
import { Emitter } from '@theia/core/lib/common/event';
34
import { notEmpty } from '@theia/core/lib/common/objects';
45
import { FileService } from '@theia/filesystem/lib/browser/file-service';
56
import { MessageService } from '@theia/core/lib/common/message-service';
7+
import { FileChangeType } from '@theia/filesystem/lib/common/files';
68
import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
9+
import { DisposableCollection } from '@theia/core/lib/common/disposable';
10+
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
711
import { Sketch, SketchesService } from '../../common/protocol';
8-
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
912
import { ConfigService } from './config-service';
10-
import { DisposableCollection, Emitter } from '@theia/core';
11-
import { FileChangeType } from '@theia/filesystem/lib/browser';
1213
import { SketchContainer } from './sketches-service';
1314

1415
@injectable()
@@ -129,4 +130,13 @@ export class SketchesServiceClientImpl implements FrontendApplicationContributio
129130
}, 100);
130131
}
131132

133+
/**
134+
* `true` if the `uri` is not contained in any of the opened workspaces. Otherwise, `false`.
135+
*/
136+
isReadOnly(uri: URI | monaco.Uri | string): boolean {
137+
const toCheck = uri instanceof URI ? uri : new URI(uri);
138+
const readOnly = !this.workspaceService.tryGetRoots().some(({ resource }) => resource.isEqualOrParent(toCheck));
139+
return readOnly;
140+
}
141+
132142
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /