From 3cd9162103e48a27c42230752e4dce0c829a6b5c Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 10 May 2011 20:54:44 +0500 Subject: [PATCH] fix bug when same folded row is shown twice while scrolling and optimize usage of getRowFoldEnd --- lib/ace/edit_session/folding.js | 50 +++++++++++++++++++++++++++++++-- lib/ace/layer/gutter.js | 25 +++++++++++------ lib/ace/layer/text.js | 41 +++++++++++++++++++++------ 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 0e3fb889..3a2e6121 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -191,7 +191,11 @@ function Folding() { this.getFoldLine = function(docRow, startFoldLine) { var foldData = this.$foldData; - var i = Math.max(foldData.indexOf(startFoldLine), 0); + var i = 0; + if(startFoldLine) + i = foldData.indexOf(startFoldLine); + if(i == -1) + i = 0; for (i; i < foldData.length; i++) { var foldLine = foldData[i]; if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) { @@ -203,6 +207,47 @@ function Folding() { return null; } + // returns the fold which starts after or contains docRow + this.getNextFold = function(docRow, startFoldLine) { + var foldData = this.$foldData, ans; + var i = 0; + if(startFoldLine) + i = foldData.indexOf(startFoldLine); + if(i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.end.row >= docRow) { + return foldLine; + } + } + return null; + } + + this.getFoldedRowCount = function(first, last) { + var foldData = this.$foldData, rowCount = last-first+1; + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i], + end = foldLine.end.row, + start = foldLine.start.row; + if(end >= last) { + if(start < last) { + if(start >= first) + rowCount -= last-start; + else + rowCount = 0;//in one fold + } + break; + } else if(end >= first){ + if (start >= first) //fold inside range + rowCount -= end-start; + else + rowCount -= end-first+1; + } + } + return rowCount; + } + this.$addFoldLine = function(foldLine) { this.$foldData.push(foldLine); this.$foldData.sort(function(a, b) { @@ -428,6 +473,7 @@ function Folding() { }; this.getRowFoldEnd = function(docRow, startFoldRow) { + //console.trace() var foldLine = this.getFoldLine(docRow, startFoldRow); return (foldLine ? foldLine.end.row @@ -484,4 +530,4 @@ function Folding() { exports.Folding = Folding; -}); +}); \ No newline at end of file diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 84a36ca2..344018ec 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -99,12 +99,22 @@ var Gutter = function(parentEl) { this.update = function(config) { this.$config = config; + var emptyAnno = {className: "", text: []}; var html = []; - for ( var i = config.firstRow; i <= config.lastRow; i++) { - var annotation = this.$annotations[i] || { - className: "", - text: [] - }; + var i = config.firstRow, lastRow = config.lastRow + fold = this.session.getNextFold(i), + foldStart = fold ?fold.start.row :Infinity; + + while (true) { + if(i > foldStart) { + i = fold.end.row+1; + fold = this.session.getNextFold(i); + foldStart = fold ?fold.start.row :Infinity; + } + if(i > lastRow) + break; + + var annotation = this.$annotations[i] || emptyAnno; html.push("
", (i+1), "
"); - - i = this.session.getRowFoldEnd(i); + i++; } - this.element = dom.setInnerHtml(this.element, html.join("")); + this.element = dom.setInnerHtml(this.element, html.join("")); this.element.style.height = config.minHeight + "px"; }; diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index d28d34a5..243e2371 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -230,13 +230,12 @@ var Text = function(parentEl) { return this.update(config); var el = this.element; - if (oldConfig.firstRow < config.firstRow) - for (var row=oldConfig.firstRow; row0; row--) el.removeChild(el.firstChild); if (oldConfig.lastRow > config.lastRow) - for (var row=config.lastRow+1; row<=oldConfig.lastRow; row = this.session.getRowFoldEnd(row) + 1) + for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) el.removeChild(el.lastChild); if (config.firstRow < oldConfig.firstRow) { @@ -254,8 +253,20 @@ var Text = function(parentEl) { }; this.$renderLinesFragment = function(config, firstRow, lastRow) { - var fragment = document.createDocumentFragment(); - for (var row=firstRow; row<=lastRow; row++) { + var fragment = document.createDocumentFragment(), + row = firstRow, + fold = this.session.getNextFold(row), + foldStart = fold ?fold.start.row :Infinity; + + while (true) { + if(row > foldStart) { + row = fold.end.row+1; + fold = this.session.getNextFold(row); + foldStart = fold ?fold.start.row :Infinity; + } + if(row > lastRow) + break; + var lineEl = dom.createElement("div"); lineEl.className = "ace_line"; @@ -276,7 +287,7 @@ var Text = function(parentEl) { lineEl.innerHTML = html.join(""); fragment.appendChild(lineEl); - row = this.session.getRowFoldEnd(row); + row++; } return fragment; }; @@ -287,9 +298,20 @@ var Text = function(parentEl) { var html = []; var firstRow = config.firstRow, lastRow = config.lastRow; - var tokens = this.session.getTokens(firstRow, lastRow) - for (var row=firstRow; row<=lastRow; row++) { + var row = firstRow, + fold = this.session.getNextFold(row), + foldStart = fold ?fold.start.row :Infinity; + + while (true) { + if(row > foldStart) { + row = fold.end.row+1; + fold = this.session.getNextFold(row); + foldStart = fold ?fold.start.row :Infinity; + } + if(row > lastRow) + break; + html.push("
" ) @@ -301,7 +323,8 @@ var Text = function(parentEl) { if (tokens.length == 1) this.$renderLine(html, row, tokens[0].tokens); html.push("
") - row = this.session.getRowFoldEnd(row); + + row++; } this.element = dom.setInnerHtml(this.element, html.join("")); };