make addFold arguments less flexible and do some

cleanups in the folding code
This commit is contained in:
Fabian Jakobs 2011-07-25 12:00:19 +02:00
commit 44b8d656f2
3 changed files with 118 additions and 151 deletions

View file

@ -50,12 +50,12 @@ function Folding() {
*/ */
this.getFoldAt = function(row, column, side) { this.getFoldAt = function(row, column, side) {
var foldLine = this.getFoldLine(row); var foldLine = this.getFoldLine(row);
if (foldLine) { if (!foldLine)
var folds = foldLine.folds, return null;
fold;
var folds = foldLine.folds;
for (var i = 0; i < folds.length; i++) { for (var i = 0; i < folds.length; i++) {
fold = folds[i]; var fold = folds[i];
if (fold.range.contains(row, column)) { if (fold.range.contains(row, column)) {
if (side == 1 && fold.range.isEnd(row, column)) { if (side == 1 && fold.range.isEnd(row, column)) {
continue; continue;
@ -65,10 +65,7 @@ function Folding() {
return fold; return fold;
} }
} }
} else { };
return null;
}
}
/** /**
* Returns all folds in the given range. Note, that this will return folds * Returns all folds in the given range. Note, that this will return folds
@ -76,33 +73,30 @@ function Folding() {
*/ */
this.getFoldsInRange = function(range) { this.getFoldsInRange = function(range) {
range = range.clone(); range = range.clone();
var start = range.start, var start = range.start;
end = range.end; var end = range.end;
var foldLines = this.$foldData, var foldLines = this.$foldData;
folds, var foundFolds = [];
fold;
var cmp,
foundFolds = [];
start.column += 1; start.column += 1;
end.column -= 1; end.column -= 1;
for (var i = 0; i < foldLines.length; i++) { for (var i = 0; i < foldLines.length; i++) {
cmp = foldLines[i].range.compareRange(range); var cmp = foldLines[i].range.compareRange(range);
if (cmp == 2) {
// Range is before foldLine. No intersection. This means, // Range is before foldLine. No intersection. This means,
// there might be other foldLines that intersect. // there might be other foldLines that intersect.
if (cmp == 2) {
continue; continue;
} else }
else if (cmp == -2) {
// Range is after foldLine. There can't be any other foldLines then, // Range is after foldLine. There can't be any other foldLines then,
// so let's give up. // so let's give up.
if (cmp == -2) {
break; break;
} }
folds = foldLines[i].folds; var folds = foldLines[i].folds;
for (var j = 0; j < folds.length; j++) { for (var j = 0; j < folds.length; j++) {
fold = folds[j]; var fold = folds[j];
cmp = fold.range.compareRange(range); cmp = fold.range.compareRange(range);
if (cmp == -2) { if (cmp == -2) {
break; break;
@ -138,39 +132,37 @@ function Folding() {
*/ */
this.getFoldStringAt = function(row, column, trim, foldLine) { this.getFoldStringAt = function(row, column, trim, foldLine) {
var foldLine = foldLine || this.getFoldLine(row); var foldLine = foldLine || this.getFoldLine(row);
if (!foldLine) { if (!foldLine)
return null; return null;
} else {
var fold, lastFold, cmp, str; var lastFold = {
lastFold = {
end: { column: 0 } end: { column: 0 }
}; };
// TODO: Refactor to use getNextFoldTo function. // TODO: Refactor to use getNextFoldTo function.
for (var i = 0; i < foldLine.folds.length; i++) { for (var i = 0; i < foldLine.folds.length; i++) {
fold = foldLine.folds[i]; var fold = foldLine.folds[i];
cmp = fold.range.compareEnd(row, column); var cmp = fold.range.compareEnd(row, column);
if (cmp == -1) { if (cmp == -1) {
str = this.getLine(fold.start.row). var str = this
substring(lastFold.end.column, fold.start.column); .getLine(fold.start.row)
.substring(lastFold.end.column, fold.start.column);
break; break;
} else if (cmp == 0) { }
else if (cmp == 0) {
return null; return null;
} }
lastFold = fold; lastFold = fold;
} }
if (!str) { if (!str)
str = this.getLine(fold.start.row). str = this.getLine(fold.start.row).substring(lastFold.end.column);
substring(lastFold.end.column);
} if (trim == -1)
if (trim == -1) {
return str.substring(0, column - lastFold.end.column); return str.substring(0, column - lastFold.end.column);
} else if (trim == 1) { else if (trim == 1)
return str.substring(column - lastFold.end.column) return str.substring(column - lastFold.end.column)
} else { else
return str; return str;
} }
}
}
this.getFoldLine = function(docRow, startFoldLine) { this.getFoldLine = function(docRow, startFoldLine) {
var foldData = this.$foldData; var foldData = this.$foldData;
@ -246,76 +238,55 @@ function Folding() {
* The new created Fold object or an existing fold object in case the * The new created Fold object or an existing fold object in case the
* passed in range fits an existing fold exactly. * passed in range fits an existing fold exactly.
*/ */
this.addFold = function(placeholder, startRow, startColumn, endRow, endColumn) { this.addFold = function(placeholder, range) {
var range;
var foldData = this.$foldData; var foldData = this.$foldData;
var foldRow = null; var foldRow = null;
var foldLine; var foldLine;
var fold;
var argsFold;
var folds; var folds;
var added = false; var added = false;
if (placeholder instanceof Fold) { if (placeholder instanceof Fold)
argsFold = placeholder; var fold = placeholder;
startRow = argsFold.range; else
placeholder = argsFold.placeholder; fold = new Fold(range, placeholder);
}
// Normalize parameters. var startRow = fold.start.row;
if (!(startRow instanceof Range)) { var startColumn = fold.start.column;
range = new Range(startRow, startColumn, endRow, endColumn); var endRow = fold.end.row;
} else { var endColumn = fold.end.column;
range = startRow;
startRow = range.start.row;
startColumn = range.start.column;
endRow = range.end.row;
endColumn = range.end.column;
}
// --- Some checking --- // --- Some checking ---
if (placeholder.length < 2) { if (fold.placeholder.length < 2)
throw "Placeholder has to be at least 2 characters"; throw "Placeholder has to be at least 2 characters";
}
if (startRow == endRow && endColumn - startColumn < 2) { if (startRow == endRow && endColumn - startColumn < 2)
throw "The range has to be at least 2 characters width"; throw "The range has to be at least 2 characters width";
}
fold = this.getFoldAt(startRow, startColumn, 1); var existingFold = this.getFoldAt(startRow, startColumn, 1);
if (fold if (
&& fold.range.isEnd(endRow, endColumn) existingFold
&& fold.range.isStart(startRow, startColumn)) && existingFold.range.isEnd(endRow, endColumn)
{ && existingFold.range.isStart(startRow, startColumn)
) {
return fold; return fold;
} }
fold = this.getFoldAt(startRow, startColumn, 1); existingFold = this.getFoldAt(startRow, startColumn, 1);
if (fold && !fold.range.isStart(startRow, startColumn)) { if (existingFold && !existingFold.range.isStart(startRow, startColumn))
throw "A fold can't start inside of an already existing fold"; throw "A fold can't start inside of an already existing fold";
}
fold = this.getFoldAt(endRow, endColumn, -1); existingFold = this.getFoldAt(endRow, endColumn, -1);
if (fold && !fold.range.isEnd(endRow, endColumn)) { if (existingFold && !existingFold.range.isEnd(endRow, endColumn))
throw "A fold can't end inside of an already existing fold"; throw "A fold can't end inside of an already existing fold";
}
if (endRow >= this.doc.getLength()) { if (endRow >= this.doc.getLength())
throw "End of fold is outside of the document."; throw "End of fold is outside of the document.";
}
if (endColumn > this.getLine(endRow).length if (endColumn > this.getLine(endRow).length || startColumn > this.getLine(startRow).length)
|| startColumn > this.getLine(startRow).length)
{
throw "End of fold is outside of the document."; throw "End of fold is outside of the document.";
}
// --- Start adding the fold ---
// Use the passed in fold or create a new one.
fold = argsFold || new Fold(range, placeholder);
// Check if there are folds in the range we create the new fold for. // Check if there are folds in the range we create the new fold for.
folds = this.getFoldsInRange(range); folds = this.getFoldsInRange(fold.range);
if (folds.length > 0) { if (folds.length > 0) {
// Remove the folds from fold data. // Remove the folds from fold data.
this.removeFolds(folds); this.removeFolds(folds);
@ -329,7 +300,8 @@ function Folding() {
foldLine.addFold(fold); foldLine.addFold(fold);
added = true; added = true;
break; break;
} else if (startRow == foldLine.end.row) { }
else if (startRow == foldLine.end.row) {
foldLine.addFold(fold); foldLine.addFold(fold);
added = true; added = true;
if (!fold.sameRow) { if (!fold.sameRow) {
@ -342,18 +314,17 @@ function Folding() {
} }
} }
break; break;
} else if (endRow <= foldLine.start.row) { }
else if (endRow <= foldLine.start.row) {
break; break;
} }
} }
if (!added) { if (!added)
foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold)); foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold));
}
if (this.$useWrapMode) { if (this.$useWrapMode)
this.$updateWrapData(foldLine.start.row, foldLine.start.row); this.$updateWrapData(foldLine.start.row, foldLine.start.row);
}
// Notify that fold data has changed. // Notify that fold data has changed.
this.$modified = true; this.$modified = true;

View file

@ -768,45 +768,45 @@ module.exports = {
// Adding a fold. The split position is inside of the fold. As placeholder // Adding a fold. The split position is inside of the fold. As placeholder
// are not splitable, the split should be before the split. // are not splitable, the split should be before the split.
session.addFold("woot", 0, 4, 0, 15); session.addFold("woot", new Range(0, 4, 0, 15));
assertWrap([4], [8], [8]); assertWrap([4], [8], [8]);
// Remove the fold again which should reset the wrapData. // Remove the fold again which should reset the wrapData.
removeFoldAssertWrap(0, 4, [8], [8], [8]); removeFoldAssertWrap(0, 4, [8], [8], [8]);
session.addFold("woot", 0, 6, 0, 9); session.addFold("woot", new Range(0, 6, 0, 9));
assertWrap([6, 13], [8], [8]); assertWrap([6, 13], [8], [8]);
removeFoldAssertWrap(0, 6, [8], [8], [8]); removeFoldAssertWrap(0, 6, [8], [8], [8]);
// The fold fits into the wrap limit - no split expected. // The fold fits into the wrap limit - no split expected.
session.addFold("woot", 0, 3, 0, 15); session.addFold("woot", new Range(0, 3, 0, 15));
assertWrap([], [8], [8]); assertWrap([], [8], [8]);
removeFoldAssertWrap(0, 4, [8], [8], [8]); removeFoldAssertWrap(0, 4, [8], [8], [8]);
// Fold after split position should be all fine. // Fold after split position should be all fine.
session.addFold("woot", 0, 8, 0, 15); session.addFold("woot", new Range(0, 8, 0, 15));
assertWrap([8], [8], [8]); assertWrap([8], [8], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]); removeFoldAssertWrap(0, 8, [8], [8], [8]);
// Fold's placeholder is far too long for wrapSplit. // Fold's placeholder is far too long for wrapSplit.
session.addFold("woot0123456789", 0, 8, 0, 15); session.addFold("woot0123456789", new Range(0, 8, 0, 15));
assertWrap([8], [8], [8]); assertWrap([8], [8], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]); removeFoldAssertWrap(0, 8, [8], [8], [8]);
// Fold's placeholder is far too long for wrapSplit // Fold's placeholder is far too long for wrapSplit
// + content at the end of the line // + content at the end of the line
session.addFold("woot0123456789", 0, 6, 0, 8); session.addFold("woot0123456789", new Range(0, 6, 0, 8));
assertWrap([6, 20], [8], [8]); assertWrap([6, 20], [8], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]); removeFoldAssertWrap(0, 8, [8], [8], [8]);
session.addFold("woot0123456789", 0, 6, 0, 8); session.addFold("woot0123456789", new Range(0, 6, 0, 8));
session.addFold("woot0123456789", 0, 8, 0, 10); session.addFold("woot0123456789", new Range(0, 8, 0, 10));
assertWrap([6, 20, 34], [8], [8]); assertWrap([6, 20, 34], [8], [8]);
session.removeFold(session.getFoldAt(0, 7)); session.removeFold(session.getFoldAt(0, 7));
removeFoldAssertWrap(0, 8, [8], [8], [8]); removeFoldAssertWrap(0, 8, [8], [8], [8]);
session.addFold("woot0123456789", 0, 7, 0, 9); session.addFold("woot0123456789", new Range(0, 7, 0, 9));
session.addFold("woot0123456789", 0, 13, 0, 15); session.addFold("woot0123456789", new Range(0, 13, 0, 15));
assertWrap([7, 21, 25], [8], [8]); assertWrap([7, 21, 25], [8], [8]);
session.removeFold(session.getFoldAt(0, 7)); session.removeFold(session.getFoldAt(0, 7));
removeFoldAssertWrap(0, 14, [8], [8], [8]); removeFoldAssertWrap(0, 14, [8], [8], [8]);
@ -815,15 +815,15 @@ module.exports = {
// Add a fold over two lines. Note, that the wrapData[1] stays the // Add a fold over two lines. Note, that the wrapData[1] stays the
// same. This is an implementation detail and expected behavior. // same. This is an implementation detail and expected behavior.
session.addFold("woot", 0, 8, 1, 15); session.addFold("woot", new Range(0, 8, 1, 15));
assertWrap([8], [8 /* See comments */], [8]); assertWrap([8], [8 /* See comments */], [8]);
removeFoldAssertWrap(0, 8, [8], [8], [8]); removeFoldAssertWrap(0, 8, [8], [8], [8]);
session.addFold("woot", 0, 9, 1, 11); session.addFold("woot", new Range(0, 9, 1, 11));
assertWrap([8, 14], [8 /* See comments */], [8]); assertWrap([8, 14], [8 /* See comments */], [8]);
removeFoldAssertWrap(0, 9, [8], [8], [8]); removeFoldAssertWrap(0, 9, [8], [8], [8]);
session.addFold("woot", 0, 9, 1, 15); session.addFold("woot", new Range(0, 9, 1, 15));
assertWrap([8], [8 /* See comments */], [8]); assertWrap([8], [8 /* See comments */], [8]);
removeFoldAssertWrap(0, 9, [8], [8], [8]); removeFoldAssertWrap(0, 9, [8], [8], [8]);
@ -834,14 +834,10 @@ module.exports = {
var session = createFoldTestSession(); var session = createFoldTestSession();
var fold; var fold;
function tryAddFold( function tryAddFold(placeholder, range, shouldFail) {
placeholder,
startRow, startColumn, endRow, endColumn, shouldFail)
{
var fail = false; var fail = false;
try { try {
fold = session.addFold(placeholder, fold = session.addFold(placeholder, range);
startRow, startColumn, endRow, endColumn);
} catch (e) { } catch (e) {
fail = true; fail = true;
} }
@ -850,19 +846,19 @@ module.exports = {
} }
} }
tryAddFold("foo", 0, 13, 0, 17, true); tryAddFold("foo", new Range(0, 13, 0, 17), true);
tryAddFold("foo", 0, 14, 0, 18, true); tryAddFold("foo", new Range(0, 14, 0, 18), true);
tryAddFold("foo", 0, 13, 0, 18, false); tryAddFold("foo", new Range(0, 13, 0, 18), false);
assert.equal(session.$foldData[0].folds.length, 1); assert.equal(session.$foldData[0].folds.length, 1);
tryAddFold("f", 0, 13, 0, 18, true); tryAddFold("f", new Range(0, 13, 0, 18), true);
tryAddFold("foo", 0, 18, 0, 21, false); tryAddFold("foo", new Range(0, 18, 0, 21), false);
assert.equal(session.$foldData[0].folds.length, 2); assert.equal(session.$foldData[0].folds.length, 2);
session.removeFold(fold); session.removeFold(fold);
tryAddFold("foo", 0, 18, 0, 22, true); tryAddFold("foo", new Range(0, 18, 0, 22), true);
tryAddFold("foo", 0, 18, 0, 19, true); tryAddFold("foo", new Range(0, 18, 0, 19), true);
tryAddFold("foo", 0, 22, 1, 10, true); tryAddFold("foo", new Range(0, 22, 1, 10), true);
}, },
"test add subfolds": function() { "test add subfolds": function() {
@ -872,7 +868,7 @@ module.exports = {
oldFold = foldData[0].folds[0]; oldFold = foldData[0].folds[0];
fold = session.addFold("fold0", 0, 10, 0, 21); fold = session.addFold("fold0", new Range(0, 10, 0, 21));
assert.equal(foldData[0].folds.length, 1); assert.equal(foldData[0].folds.length, 1);
assert.equal(fold.subFolds.length, 1); assert.equal(fold.subFolds.length, 1);
assert.equal(fold.subFolds[0], oldFold); assert.equal(fold.subFolds[0], oldFold);
@ -882,7 +878,7 @@ module.exports = {
assert.equal(foldData[0].folds[0], oldFold); assert.equal(foldData[0].folds[0], oldFold);
assert.equal(fold.subFolds.length, 0); assert.equal(fold.subFolds.length, 0);
fold = session.addFold("fold0", 0, 13, 2, 10); fold = session.addFold("fold0", new Range(0, 13, 2, 10));
assert.equal(foldData.length, 1); assert.equal(foldData.length, 1);
assert.equal(fold.subFolds.length, 2); assert.equal(fold.subFolds.length, 2);
assert.equal(fold.subFolds[0], oldFold); assert.equal(fold.subFolds[0], oldFold);