Skip to content

Commit 4612791

Browse files
committed
Empty hidden editors (#14909)
Clear model from editor when the editor is hidden Fixes #14880 Contributed on behalf of STMicroelectronics Signed-off-by: Thomas Mäder <[email protected]>
1 parent ce6fd81 commit 4612791

File tree

7 files changed

+66
-10
lines changed

7 files changed

+66
-10
lines changed

packages/core/src/browser/widgets/widget.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,14 +225,18 @@ export class BaseWidget extends Widget implements PreviewableWidget {
225225
override setFlag(flag: Widget.Flag): void {
226226
super.setFlag(flag);
227227
if (flag === Widget.Flag.IsVisible) {
228-
this.onDidChangeVisibilityEmitter.fire(this.isVisible);
228+
this.handleVisiblityChanged(this.isVisible);
229229
}
230230
}
231231

232+
protected handleVisiblityChanged(isNowVisible: boolean): void {
233+
this.onDidChangeVisibilityEmitter.fire(isNowVisible);
234+
}
235+
232236
override clearFlag(flag: Widget.Flag): void {
233237
super.clearFlag(flag);
234238
if (flag === Widget.Flag.IsVisible) {
235-
this.onDidChangeVisibilityEmitter.fire(this.isVisible);
239+
this.handleVisiblityChanged(this.isVisible);
236240
}
237241
}
238242
}

packages/editor/src/browser/editor-widget.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ export class EditorWidget extends BaseWidget implements SaveableSource, Navigata
6060
}
6161
}
6262

63+
protected override handleVisiblityChanged(isNowVisible: boolean): void {
64+
this.editor.handleVisibilityChanged(isNowVisible);
65+
super.handleVisiblityChanged(isNowVisible);
66+
}
67+
6368
get saveable(): Saveable {
6469
return this.editor.document;
6570
}

packages/editor/src/browser/editor.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,8 @@ export interface TextEditor extends Disposable, TextEditorSelection, Navigatable
295295
readonly onEncodingChanged: Event<string>;
296296

297297
shouldDisplayDirtyDiff(): boolean;
298+
299+
handleVisibilityChanged(nowVisible: boolean): void;
298300
}
299301

300302
export interface Selection extends Range {

packages/monaco/src/browser/monaco-editor-provider.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
4848
export const MonacoEditorFactory = Symbol('MonacoEditorFactory');
4949
export interface MonacoEditorFactory {
5050
readonly scheme: string;
51-
create(model: MonacoEditorModel, defaultOptions: MonacoEditor.IOptions, defaultOverrides: EditorServiceOverrides): MonacoEditor;
51+
create(model: MonacoEditorModel, defaultOptions: MonacoEditor.IOptions, defaultOverrides: EditorServiceOverrides): Promise<MonacoEditor>;
5252
}
5353

5454
@injectable()
@@ -198,8 +198,8 @@ export class MonacoEditorProvider {
198198
const options = this.createMonacoEditorOptions(model);
199199
const factory = this.factories.getContributions().find(({ scheme }) => uri.scheme === scheme);
200200
const editor = factory
201-
? factory.create(model, options, override)
202-
: new MonacoEditor(uri, model, document.createElement('div'), this.services, options, override);
201+
? await factory.create(model, options, override)
202+
: await MonacoEditor.create(uri, model, document.createElement('div'), this.services, options, override);
203203
toDispose.push(this.editorPreferences.onPreferenceChanged(event => {
204204
if (event.affects(uri.toString(), model.languageId)) {
205205
this.updateMonacoEditorOptions(editor, event);
@@ -380,7 +380,7 @@ export class MonacoEditorProvider {
380380
}, this.m2p, this.p2m);
381381
toDispose.push(document);
382382
const model = (await document.load()).textEditorModel;
383-
return new MonacoEditor(
383+
return await MonacoEditor.create(
384384
uri,
385385
document,
386386
node,

packages/monaco/src/browser/monaco-editor.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import { ILanguageFeaturesService } from '@theia/monaco-editor-core/esm/vs/edito
6464
import * as objects from '@theia/monaco-editor-core/esm/vs/base/common/objects';
6565
import { Selection } from '@theia/editor/lib/browser/editor';
6666
import { IHoverService } from '@theia/monaco-editor-core/esm/vs/platform/hover/browser/hover';
67+
import { MonacoTextModelService } from './monaco-text-model-service';
6768

6869
export type ServicePair<T> = [ServiceIdentifier<T>, T];
6970

@@ -81,13 +82,28 @@ export class MonacoEditorServices {
8182
@inject(ContextKeyService)
8283
protected readonly contextKeyService: ContextKeyService;
8384

85+
@inject(MonacoTextModelService)
86+
protected readonly monacoModelService: MonacoTextModelService;
87+
8488
constructor(@unmanaged() services: MonacoEditorServices) {
8589
Object.assign(this, services);
8690
}
8791
}
8892

8993
export class MonacoEditor extends MonacoEditorServices implements TextEditor {
9094

95+
static async create(uri: URI,
96+
document: MonacoEditorModel,
97+
node: HTMLElement,
98+
services: MonacoEditorServices,
99+
options?: MonacoEditor.IOptions,
100+
override?: EditorServiceOverrides,
101+
parentEditor?: MonacoEditor): Promise<MonacoEditor> {
102+
const instance = new MonacoEditor(uri, document, node, services, options, override, parentEditor);
103+
await instance.init();
104+
return instance;
105+
}
106+
91107
protected readonly toDispose = new DisposableCollection();
92108

93109
protected readonly autoSizing: boolean;
@@ -109,8 +125,10 @@ export class MonacoEditor extends MonacoEditorServices implements TextEditor {
109125
readonly onDidResize = this.onResizeEmitter.event;
110126

111127
readonly documents = new Set<MonacoEditorModel>();
128+
protected model: monaco.editor.ITextModel | null;
129+
savedViewState: monaco.editor.ICodeEditorViewState | null;
112130

113-
constructor(
131+
protected constructor(
114132
readonly uri: URI,
115133
readonly document: MonacoEditorModel,
116134
readonly node: HTMLElement,
@@ -140,6 +158,10 @@ export class MonacoEditor extends MonacoEditorServices implements TextEditor {
140158
this.addHandlers(this.editor);
141159
}
142160

161+
protected async init(): Promise<void> {
162+
this.toDispose.push(await this.monacoModelService.createModelReference(this.uri));
163+
}
164+
143165
getEncoding(): string {
144166
return this.document.getEncoding() || UTF8;
145167
}
@@ -228,6 +250,22 @@ export class MonacoEditor extends MonacoEditorServices implements TextEditor {
228250
}));
229251
}
230252

253+
handleVisibilityChanged(nowVisible: boolean): void {
254+
if (nowVisible) {
255+
if (this.model) {
256+
this.editor.setModel(this.model);
257+
this.editor.restoreViewState(this.savedViewState);
258+
this.editor.focus();
259+
}
260+
} else {
261+
this.model = this.editor.getModel();
262+
this.savedViewState = this.editor.saveViewState();
263+
264+
// eslint-disable-next-line no-null/no-null
265+
this.editor.setModel(null); // workaround for https://github.com/eclipse-theia/theia/issues/14880
266+
}
267+
}
268+
231269
getVisibleRanges(): Range[] {
232270
return this.editor.getVisibleRanges().map(range => this.m2p.asRange(range));
233271
}

packages/monaco/src/browser/monaco-to-protocol-converter.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,14 @@ export class MonacoToProtocolConverter {
6969
}
7070
}
7171

72-
asSelection(selection: monaco.Selection): Selection {
72+
asSelection(selection: monaco.Selection | null): Selection {
73+
if (!selection) {
74+
return {
75+
start: { line: 0, character: 0 },
76+
end: { line: 0, character: 0 },
77+
direction: 'ltr'
78+
};
79+
}
7380
const start = this.asPosition(selection.selectionStartLineNumber, selection.selectionStartColumn);
7481
const end = this.asPosition(selection.positionLineNumber, selection.positionColumn);
7582
return {

packages/output/src/browser/output-editor-factory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ export class OutputEditorFactory implements MonacoEditorFactory {
3535

3636
readonly scheme: string = OutputUri.SCHEME;
3737

38-
create(model: MonacoEditorModel, defaultsOptions: MonacoEditor.IOptions): MonacoEditor {
38+
create(model: MonacoEditorModel, defaultsOptions: MonacoEditor.IOptions): Promise<MonacoEditor> {
3939
const uri = new URI(model.uri);
4040
const options = this.createOptions(model, defaultsOptions);
4141
const overrides = this.createOverrides(model);
42-
return new MonacoEditor(uri, model, document.createElement('div'), this.services, options, overrides);
42+
return MonacoEditor.create(uri, model, document.createElement('div'), this.services, options, overrides);
4343
}
4444

4545
protected createOptions(model: MonacoEditorModel, defaultOptions: MonacoEditor.IOptions): MonacoEditor.IOptions {

0 commit comments

Comments
 (0)