From 1d4c6fea49fd90915bcdb217dfdc87df3a74d4c6 Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Mon, 20 Sep 2010 09:08:09 +0200 Subject: [PATCH] optimize scrolling by reusing already rendered lines --- src/ace/VirtualRenderer.js | 7 ++-- src/ace/layer/Text.js | 65 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/ace/VirtualRenderer.js b/src/ace/VirtualRenderer.js index 5582d377..7efb57ec 100644 --- a/src/ace/VirtualRenderer.js +++ b/src/ace/VirtualRenderer.js @@ -194,7 +194,7 @@ var VirtualRenderer = function(container) { this.$textLayer.updateLines(layerConfig, firstRow, lastRow); }; - this.draw = function() { + this.draw = function(scrollOnly) { var lines = this.lines; var offset = this.scrollTop % this.lineHeight; @@ -216,7 +216,8 @@ var VirtualRenderer = function(container) { lastRow : lastRow, lineHeight : this.lineHeight, characterWidth : this.characterWidth, - minHeight : minHeight + minHeight : minHeight, + scrollOnly: !!scrollOnly }; this.content.style.marginTop = (-offset) + "px"; @@ -309,7 +310,7 @@ var VirtualRenderer = function(container) { if (this.scrollTop !== scrollTop) { this.scrollTop = scrollTop; this.$updateScrollBar(); - this.draw(); + this.draw(true); } }; diff --git a/src/ace/layer/Text.js b/src/ace/layer/Text.js index 80656192..aab584b1 100644 --- a/src/ace/layer/Text.js +++ b/src/ace/layer/Text.js @@ -119,13 +119,74 @@ var Text = function(parentEl) { }; }; + this.$scrollLines = function(oldConfig, config) { + if (oldConfig.lastRow < config.firstRow) + return this.$fullUpdate(config); + + if (config.lastRow < oldConfig.firstRow) + return this.$fullUpdate(config); + + var el = this.element; + + if (oldConfig.firstRow < config.firstRow) + for (var row=oldConfig.firstRow; row config.lastRow) + for (var row=config.lastRow+1; row<=oldConfig.lastRow; row++) + el.removeChild(el.lastChild); + + if (config.firstRow < oldConfig.firstRow) { + var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); + if (el.firstChild) + el.insertBefore(fragment, el.firstChild); + else + el.appendChild(fragment); + } + + if (config.lastRow > oldConfig.lastRow) { + var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); + el.appendChild(fragment); + } + }; + + this.$renderLinesFragment = function(config, firstRow, lastRow) { + var fragment = document.createDocumentFragment(); + for (var row=firstRow; row<=lastRow; row++) { + var lineEl = document.createElement("div"); + lineEl.className = "ace_line"; + var style = lineEl.style; + style.height = this.$characterSize.height + "px"; + style.width = config.width + "px"; + + var html = []; + this.renderLine(html, row); + lineEl.innerHTML = html.join(""); + fragment.appendChild(lineEl); + } + return fragment; + }; + this.update = function(config) { + if (!config.minHeight) + return; + this.$computeTabString(); + if (this.config && config.scrollOnly) { + this.$scrollLines(this.config, config); + } else { + this.$fullUpdate(config); + } + + this.config = config; + }; + + this.$fullUpdate = function(config) { var html = []; for ( var i = config.firstRow; i <= config.lastRow; i++) { html.push("
"); + config.width, "px'>"); this.renderLine(html, i), html.push("
"); } @@ -137,7 +198,7 @@ var Text = function(parentEl) { "rparen": true, "lparen": true }; - + this.renderLine = function(stringBuilder, row) { var tokens = this.tokenizer.getTokens(row);