From f695c253f517673a601b3894d6414002a7824cf9 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Thu, 28 Apr 2011 20:04:45 +0200 Subject: [PATCH] Add sub folding feature. addFold can take a Fold object now. --- demo/demo.js | 2 +- lib/ace/edit_session/folding.js | 50 +++++++++++++++++++++++++++++---- lib/ace/edit_session_test.js | 29 +++++++++++++++++++ 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 5bb3e576..5f0cfaab 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -495,7 +495,7 @@ exports.launch = function(env) { exec: function() { var session = env.editor.session, range = env.editor.selection.getRange(); - session.removeFolds(session.getFoldsInRange(range)); + session.expandFolds(session.getFoldsInRange(range)); } }); }; diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index d3514930..bbf0717b 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -52,6 +52,7 @@ function Fold(range, placeholder) { this.end = range.end; this.sameRow = range.start.row == range.end.row; + this.subFolds = []; } Fold.prototype.toString = function() { @@ -223,15 +224,25 @@ function Folding() { var foldRow = null; var foldLine; var fold; + var argsFold; + var folds; var added = false; + if (placeholder instanceof Fold) { + argsFold = placeholder; + startRow = argsFold.range; + placeholder = argsFold.placeholder; + } + // Normalize parameters. if (!(startRow instanceof Range)) { range = new Range(startRow, startColumn, endRow, endColumn); } else { range = startRow; startRow = range.start.row; + startColumn = range.start.column; endRow = range.end.row; + endColumn = range.end.column; } // --- Some checking --- @@ -251,10 +262,14 @@ function Folding() { return fold; } - if (this.getFoldAt(startRow, startColumn, 1) - || this.getFoldAt(endRow, endColumn, -1)) - { - throw "A fold can't start or end inside of an already existing fold"; + fold = this.getFoldAt(startRow, startColumn, 1); + if (fold && !fold.range.isStart(startRow, startColumn)) { + throw "A fold can't start inside of an already existing fold"; + } + + fold = this.getFoldAt(endRow, endColumn, -1); + if (fold && !fold.range.isEnd(endRow, endColumn)) { + throw "A fold can't end inside of an already existing fold"; } if (endRow >= this.doc.$lines.length) { @@ -268,9 +283,18 @@ function Folding() { } // --- Start adding the fold --- - fold = new Fold(range, placeholder); + // 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. + folds = this.getFoldsInRange(range); + if (folds.length > 0) { + // Remove the folds from fold data. + this.removeFolds(folds); + // Add the removed folds as subfolds on the new fold. + fold.subFolds = folds; + } - // For now we assume that no two folds are created for the same range! for (var i = 0; i < foldData.length; i++) { foldLine = foldData[i]; if (endRow == foldLine.start.row) { @@ -375,6 +399,20 @@ function Folding() { this.$modified = true; } + this.expandFold = function(fold) { + this.removeFold(fold); + fold.subFolds.forEach(function(fold) { + this.addFold(fold); + }, this); + fold.subFolds = []; + } + + this.expandFolds = function(folds) { + folds.forEach(function(fold) { + this.expandFold(fold); + }, this); + } + /** * Checks if a given documentRow is folded. This is true if there are some * folded parts such that some parts of the line is still visible. diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index bc5b09fb..8efd0d60 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -826,6 +826,35 @@ module.exports = { tryAddFold("foo", 0, 18, 0, 22, true); tryAddFold("foo", 0, 18, 0, 19, true); tryAddFold("foo", 0, 22, 1, 10, true); + }, + + "test add subfolds": function() { + var session = createFoldTestSession(); + var fold, oldFold; + var foldData = session.$foldData; + + oldFold = foldData[0].folds[0]; + + fold = session.addFold("fold0", 0, 10, 0, 21); + assert.equal(foldData[0].folds.length, 1); + assert.equal(fold.subFolds.length, 1); + assert.equal(fold.subFolds[0], oldFold); + + session.expandFold(fold); + assert.equal(foldData[0].folds.length, 1); + assert.equal(foldData[0].folds[0], oldFold); + assert.equal(fold.subFolds.length, 0); + + fold = session.addFold("fold0", 0, 13, 2, 10); + assert.equal(foldData.length, 1); + assert.equal(fold.subFolds.length, 2); + assert.equal(fold.subFolds[0], oldFold); + + session.expandFold(fold); + assert.equal(foldData.length, 2); + assert.equal(foldData[0].folds.length, 1); + assert.equal(foldData[0].folds[0], oldFold); + assert.equal(fold.subFolds.length, 0); } };