提交 3c509087 编写于 作者: M Martin Aeschlimann

[folding] store folding state as view state

上级 40635574
......@@ -181,11 +181,20 @@ export class CodeEditorWidget extends CommonCodeEditor implements EditorBrowser.
if (!this.cursor || !this.hasView) {
return null;
}
let contributionsState: {[key:string]:any} = {};
for (let id in this.contributions) {
let contribution = this.contributions[id];
if (typeof contribution.saveViewState === 'function') {
contributionsState[id] = contribution.saveViewState();
}
}
var cursorState = this.cursor.saveState();
var viewState = this._view.saveState();
return {
cursorState: cursorState,
viewState: viewState
viewState: viewState,
contributionsState: contributionsState
};
}
......@@ -204,6 +213,14 @@ export class CodeEditorWidget extends CommonCodeEditor implements EditorBrowser.
this.cursor.restoreState([<EditorCommon.ICursorState>cursorState]);
}
this._view.restoreState(codeEditorState.viewState);
let contributionsState = s.contributionsState || {};
for (let id in this.contributions) {
let contribution = this.contributions[id];
if (typeof contribution.restoreViewState === 'function') {
contribution.restoreViewState(contributionsState[id]);
}
}
}
}
......
......@@ -2310,6 +2310,7 @@ export interface IViewState {
export interface ICodeEditorViewState extends IEditorViewState {
cursorState:ICursorState[];
viewState:IViewState;
contributionsState: {[id:string]:any};
}
/**
......@@ -3001,6 +3002,14 @@ export interface IEditorContribution {
* Dispose this contribution.
*/
dispose(): void;
/**
* Store view state.
*/
saveViewState?(): any;
/**
* Restore view state.
*/
restoreViewState?(state: any): void;
}
export type MarkedString = string | { language: string; value: string };
......
......@@ -33,8 +33,7 @@ class CollapsibleRegion {
private _lastRange: IFoldingRange;
public constructor(range:IFoldingRange, model:EditorCommon.IModel, changeAccessor:EditorCommon.IModelDecorationsChangeAccessor, isCollapsed:boolean) {
this._isCollapsed = isCollapsed;
public constructor(range:IFoldingRange, model:EditorCommon.IModel, changeAccessor:EditorCommon.IModelDecorationsChangeAccessor) {
this.decorationIds = [];
this.update(range, model, changeAccessor);
}
......@@ -80,6 +79,7 @@ class CollapsibleRegion {
public update(newRange:IFoldingRange, model:EditorCommon.IModel, changeAccessor:EditorCommon.IModelDecorationsChangeAccessor): void {
this._lastRange = newRange;
this._isCollapsed = !!newRange.isCollapsed;
let newDecorations : EditorCommon.IModelDeltaDecoration[] = [];
......@@ -166,80 +166,114 @@ export class FoldingController implements EditorCommon.IEditorContribution {
this.globalToDispose = disposeAll(this.globalToDispose);
}
private cleanState(): void {
this.localToDispose = disposeAll(this.localToDispose);
/**
* Store view state.
*/
public saveViewState(): any {
let model = this.editor.getModel();
if (!model) {
return {};
}
var collapsedRegions : IFoldingRange[] = [];
this.decorations.forEach(d => {
if (d.isCollapsed) {
var range = d.getDecorationRange(model);
if (range) {
collapsedRegions.push({ startLineNumber: range.startLineNumber, endLineNumber: range.endLineNumber, isCollapsed: true});
}
};
});
return collapsedRegions;
}
private onModelChanged(): void {
this.cleanState();
if (!this.editor.getConfiguration().folding) {
/**
* Restore view state.
*/
public restoreViewState(state: any): void {
if (!Array.isArray(state)) {
return;
}
this.applyRegions(<IFoldingRange[]> state);
}
private cleanState(): void {
this.localToDispose = disposeAll(this.localToDispose);
}
private applyRegions(regions: IFoldingRange[]) {
let model = this.editor.getModel();
if (!model) {
return;
}
this.updateScheduler = new RunOnceScheduler(() => {
let myToken = (++this.computeToken);
regions = regions.sort((r1, r2) => r1.startLineNumber - r2.startLineNumber);
log('imput ranges ' + regions.map(rangeToString).join(', '));
this.computeCollapsibleRegions().then(regions => {
if (myToken !== this.computeToken) {
// A new request was made in the meantime or the model was changed
return;
}
regions = regions.sort((r1, r2) => r1.startLineNumber - r2.startLineNumber);
log('compute ranges ' + regions.map(rangeToString).join(', '));
this.editor.changeDecorations(changeAccessor => {
this.editor.changeDecorations(changeAccessor => {
let newDecorations : CollapsibleRegion[] = [];
let newDecorations : CollapsibleRegion[] = [];
let k = 0, i = 0;
while (i < this.decorations.length && k < regions.length) {
let dec = this.decorations[i];
let decRange = dec.getDecorationRange(model);
if (!decRange) {
let k = 0, i = 0;
while (i < this.decorations.length && k < regions.length) {
let dec = this.decorations[i];
let decRange = dec.getDecorationRange(model);
if (!decRange) {
log('range no longer valid, was ' + dec.toString());
dec.dispose(changeAccessor);
i++;
} else {
while (k < regions.length && decRange.startLineNumber > regions[k].startLineNumber) {
log('new range ' + rangeToString(regions[k]));
newDecorations.push(new CollapsibleRegion(regions[k], model, changeAccessor));
k++;
}
if (k < regions.length) {
let currRange = regions[k];
if (decRange.startLineNumber < currRange.startLineNumber) {
log('range no longer valid, was ' + dec.toString());
dec.dispose(changeAccessor);
i++;
} else {
while (k < regions.length && decRange.startLineNumber > regions[k].startLineNumber) {
log('new range ' + rangeToString(regions[k]));
newDecorations.push(new CollapsibleRegion(regions[k], model, changeAccessor, false));
k++;
}
if (k < regions.length) {
let currRange = regions[k];
if (decRange.startLineNumber < currRange.startLineNumber) {
log('range no longer valid, was ' + dec.toString());
dec.dispose(changeAccessor);
i++;
} else if (decRange.startLineNumber === currRange.startLineNumber) {
dec.update(currRange, model, changeAccessor);
newDecorations.push(dec);
i++;
k++;
}
}
} else if (decRange.startLineNumber === currRange.startLineNumber) {
currRange.isCollapsed = dec.isCollapsed; // preserve collapse state
dec.update(currRange, model, changeAccessor);
newDecorations.push(dec);
i++;
k++;
}
}
while (i < this.decorations.length) {
log('range no longer valid, was ' + this.decorations[i].toString());
this.decorations[i].dispose(changeAccessor);
i++;
}
while (k < regions.length) {
log('new range ' + rangeToString(regions[k]));
newDecorations.push(new CollapsibleRegion(regions[k], model, changeAccessor, false));
k++;
}
this.decorations = newDecorations;
});
}
}
while (i < this.decorations.length) {
log('range no longer valid, was ' + this.decorations[i].toString());
this.decorations[i].dispose(changeAccessor);
i++;
}
while (k < regions.length) {
log('new range ' + rangeToString(regions[k]));
newDecorations.push(new CollapsibleRegion(regions[k], model, changeAccessor));
k++;
}
this.decorations = newDecorations;
});
this.updateHiddenAreas();
}
private onModelChanged(): void {
this.cleanState();
this.updateHiddenAreas();
let model = this.editor.getModel();
if (!this.editor.getConfiguration().folding || !model) {
return;
}
this.updateScheduler = new RunOnceScheduler(() => {
let myToken = (++this.computeToken);
this.computeCollapsibleRegions().then(regions => {
if (myToken !== this.computeToken) {
return; // A new request was made in the meantime or the model was changed
}
this.applyRegions(regions);
});
}, 200);
......@@ -249,6 +283,7 @@ export class FoldingController implements EditorCommon.IEditorContribution {
++this.computeToken;
this.editor.changeDecorations(changeAccessor => {
this.decorations.forEach(dec => dec.dispose(changeAccessor));
this.decorations = [];
});
}});
this.localToDispose.push(this.editor.addListener2(EditorCommon.EventType.MouseDown, (e) => this._onEditorMouseDown(e)));
......@@ -263,7 +298,6 @@ export class FoldingController implements EditorCommon.IEditorContribution {
return TPromise.as([]);
}
let ranges = foldStrategy.computeRanges(model, tabSize);
return TPromise.as(ranges);
}
......@@ -320,7 +354,7 @@ export class FoldingController implements EditorCommon.IEditorContribution {
private updateHiddenAreas(): void {
let model = this.editor.getModel();
let hiddenAreas:EditorCommon.IRange[] = [];
let hiddenAreas: EditorCommon.IRange[] = [];
this.decorations.filter(dec => dec.isCollapsed).forEach(dec => {
let decRange = dec.getDecorationRange(model);
hiddenAreas.push({
......@@ -377,7 +411,7 @@ export class FoldingController implements EditorCommon.IEditorContribution {
}
abstract class FoldingAction extends EditorAction {
constructor(descriptor:EditorCommon.IEditorActionDescriptorData, editor:EditorCommon.ICommonCodeEditor, @INullService ns) {
constructor(descriptor: EditorCommon.IEditorActionDescriptorData, editor: EditorCommon.ICommonCodeEditor, @INullService ns) {
super(descriptor, editor);
}
......
......@@ -8,8 +8,9 @@
export interface IFoldingRange {
startLineNumber:number;
endLineNumber:number;
isCollapsed?:boolean;
}
export function toString(range: IFoldingRange): string {
return range ? range.startLineNumber + '/' + range.endLineNumber : 'null';
return (range ? range.startLineNumber + '/' + range.endLineNumber : 'null') + range.isCollapsed ? ' (collapsed)' : '';
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册