fix: handle editable region covering editor's top

This commit is contained in:
Oliver Eyton-Williams
2020-08-22 12:53:28 +02:00
committed by Mrugesh Mohapatra
parent 9df098953d
commit 3cfd80a806

View File

@ -570,13 +570,16 @@ class Editor extends Component {
// the region it should cover instead. // the region it should cover instead.
// TODO: DRY // TODO: DRY
getLineAfterViewZone() { getLineAfterViewZone() {
return ( // TODO: abstract away the data, ids etc.
this.data.model.getDecorationRange(this.data.startEditDecId) const range = this.data.model.getDecorationRange(this.data.startEditDecId);
.endLineNumber + 1 // if the first decoration is missing, this implies the region reaches the
); // start of the editor.
return range ? range.endLineNumber + 1 : 1;
} }
getLineAfterEditableRegion() { getLineAfterEditableRegion() {
// TODO: handle the case that the editable region reaches the bottom of the
// editor
return this.data.model.getDecorationRange(this.data.endEditDecId) return this.data.model.getDecorationRange(this.data.endEditDecId)
.startLineNumber; .startLineNumber;
} }
@ -590,6 +593,8 @@ class Editor extends Component {
return this._monaco.Range.lift(iRange); return this._monaco.Range.lift(iRange);
}; };
// TODO: TESTS!
// Make 100% sure this is inclusive.
getLinesBetweenRanges = (firstRange, secondRange) => { getLinesBetweenRanges = (firstRange, secondRange) => {
const startRange = this.translateRange(toLastLine(firstRange), 1); const startRange = this.translateRange(toLastLine(firstRange), 1);
const endRange = this.translateRange( const endRange = this.translateRange(
@ -607,8 +612,15 @@ class Editor extends Component {
const model = this.data.model; const model = this.data.model;
// TODO: this is a little low-level, but we should bail if there is no // TODO: this is a little low-level, but we should bail if there is no
// editable region defined. // editable region defined.
if (!this.data.startEditDecId || !this.data.endEditDecId) return null; // NOTE: if a decoration is missing, there is still an editable region - it
const firstRange = model.getDecorationRange(this.data.startEditDecId); // just extends to the edge of the editor. However, no decorations means no
// editable region.
if (!this.data.startEditDecId && !this.data.endEditDecId) return null;
const firstRange = this.data.startEditDecId
? model.getDecorationRange(this.data.startEditDecId)
: this.getStartOfEditor();
// TODO: handle the case that the editable region reaches the bottom of the
// editor
const secondRange = model.getDecorationRange(this.data.endEditDecId); const secondRange = model.getDecorationRange(this.data.endEditDecId);
const { startLineNumber, endLineNumber } = this.getLinesBetweenRanges( const { startLineNumber, endLineNumber } = this.getLinesBetweenRanges(
firstRange, firstRange,
@ -622,10 +634,19 @@ class Editor extends Component {
return new this._monaco.Range(startLineNumber, 1, endLineNumber, endColumn); return new this._monaco.Range(startLineNumber, 1, endLineNumber, endColumn);
}; };
// TODO: do this once after _monaco has been created.
getStartOfEditor = () =>
this._monaco.Range.lift({
startLineNumber: 1,
endLineNumber: 1,
startColumn: 1,
endColumn: 1
});
decorateForbiddenRanges(editableRegion) { decorateForbiddenRanges(editableRegion) {
const model = this.data.model; const model = this.data.model;
const forbiddenRanges = [ const forbiddenRanges = [
[1, editableRegion[0]], [0, editableRegion[0]],
[editableRegion[1], model.getLineCount()] [editableRegion[1], model.getLineCount()]
]; ];
@ -633,6 +654,9 @@ class Editor extends Component {
return this.positionsToRange(model, positions); return this.positionsToRange(model, positions);
}); });
// if the forbidden range includes the top of the editor
// we simply don't add those decorations
if (forbiddenRanges[0][1] > 0) {
// the first range should expand at the top // the first range should expand at the top
this.data.startEditDecId = this.highlightLines( this.data.startEditDecId = this.highlightLines(
this._monaco.editor.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore, this._monaco.editor.TrackedRangeStickiness.GrowsOnlyWhenTypingBefore,
@ -645,7 +669,9 @@ class Editor extends Component {
model, model,
ranges[0] ranges[0]
); );
}
// TODO: handle the case the region covers the bottom of the editor
// the second range should expand at the bottom // the second range should expand at the bottom
this.data.endEditDecId = this.highlightLines( this.data.endEditDecId = this.highlightLines(
this._monaco.editor.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter, this._monaco.editor.TrackedRangeStickiness.GrowsOnlyWhenTypingAfter,
@ -817,9 +843,13 @@ class Editor extends Component {
// TODO: do the same for the description widget // TODO: do the same for the description widget
// this has to be handle differently, because we care about the END // this has to be handle differently, because we care about the END
// of the zone, not the START // of the zone, not the START
// if the editable region includes the first line, the first decoration
// will be missing.
if (this.data.startEditDecId) {
handleDescriptionZoneChange(this.data.startEditDecId); handleDescriptionZoneChange(this.data.startEditDecId);
handleHintsZoneChange(this.data.endEditDecId);
warnUser(this.data.startEditDecId); warnUser(this.data.startEditDecId);
}
handleHintsZoneChange(this.data.endEditDecId);
warnUser(this.data.endEditDecId); warnUser(this.data.endEditDecId);
}); });
} }
@ -827,6 +857,7 @@ class Editor extends Component {
// creates a range covering all the lines in 'positions' // creates a range covering all the lines in 'positions'
// NOTE: positions is an array of [startLine, endLine] // NOTE: positions is an array of [startLine, endLine]
positionsToRange(model, [start, end]) { positionsToRange(model, [start, end]) {
console.log('positionsToRange', start, end);
// start and end should always be defined, but if not: // start and end should always be defined, but if not:
start = start || 1; start = start || 1;
end = end || model.getLineCount(); end = end || model.getLineCount();
@ -873,7 +904,10 @@ class Editor extends Component {
document.getElementById('test-output').innerHTML = output[1]; document.getElementById('test-output').innerHTML = output[1];
} }
if (this.data.startEditDecId) { // if either id exists, the editable region exists
// TODO: add a layer of abstraction: we should be interacting with
// the editable region, not the ids
if (this.data.startEditDecId || this.data.endEditDecId) {
this.updateOutputZone(); this.updateOutputZone();
} }
} }