From e766d70b077ebc44350643c83bb7e22c49b2256b Mon Sep 17 00:00:00 2001 From: Fabian Jakobs Date: Tue, 20 Dec 2011 14:00:47 +0100 Subject: [PATCH] move scroll top and scroll left into the edit_session so they can be persisted when changing sessions. --- lib/ace/edit_session.js | 28 +++++++++++++++----- lib/ace/editor.js | 21 ++++++++++++--- lib/ace/virtual_renderer.js | 53 ++++++++++++++++++++++--------------- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index fad643c0..6aa21896 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -546,18 +546,34 @@ var EditSession = function(text, mode) { this.getMode = function() { return this.$mode; }; - + this.$scrollTop = 0; - this.setScrollTopRow = function(scrollTopRow) { - if (this.$scrollTop === scrollTopRow) return; + this.setScrollTop = function(scrollTop) { + scrollTop = Math.round(Math.max(0, scrollTop)); + if (this.$scrollTop === scrollTop) + return; - this.$scrollTop = scrollTopRow; - this._emit("changeScrollTop"); + this.$scrollTop = scrollTop; + this._emit("changeScrollTop", scrollTop); }; - this.getScrollTopRow = function() { + this.getScrollTop = function() { return this.$scrollTop; }; + + this.$scrollLeft = 0; + this.setScrollLeft = function(scrollLeft) { + scrollLeft = Math.round(Math.max(0, scrollLeft)); + if (this.$scrollLeft === scrollLeft) + return; + + this.$scrollLeft = scrollLeft; + this._emit("changeScrollLeft", scrollLeft); + }; + + this.getScrollLeft = function() { + return this.$scrollLeft; + }; this.getWidth = function() { this.$computeWidth(); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 22284763..423300f1 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -116,12 +116,12 @@ var Editor = function(renderer, session) { this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint); this.session.removeEventListener("changeAnnotation", this.$onChangeAnnotation); this.session.removeEventListener("changeOverwrite", this.$onCursorChange); + this.session.removeEventListener("changeScrollTop", this.$onScrollTopChange); + this.session.removeEventListener("changeLeftTop", this.$onScrollLeftChange); var selection = this.session.getSelection(); selection.removeEventListener("changeCursor", this.$onCursorChange); selection.removeEventListener("changeSelection", this.$onSelectionChange); - - this.session.setScrollTopRow(this.renderer.getScrollTopRow()); } this.session = session; @@ -163,6 +163,12 @@ var Editor = function(renderer, session) { this.$onCursorChange = this.onCursorChange.bind(this); this.session.addEventListener("changeOverwrite", this.$onCursorChange); + this.$onScrollTopChange = this.onScrollTopChange.bind(this); + this.session.addEventListener("changeScrollTop", this.$onScrollTopChange); + + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); + this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange); + this.selection = session.getSelection(); this.selection.addEventListener("changeCursor", this.$onCursorChange); @@ -172,13 +178,14 @@ var Editor = function(renderer, session) { this.onChangeMode(); this.onCursorChange(); + this.onScrollTopChange(); + this.onScrollLeftChange(); this.onSelectionChange(); this.onChangeFrontMarker(); this.onChangeBackMarker(); this.onChangeBreakpoint(); this.onChangeAnnotation(); this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); - this.renderer.scrollToRow(session.getScrollTopRow()); this.renderer.updateFull(); this._emit("changeSession", { @@ -296,6 +303,14 @@ var Editor = function(renderer, session) { this.renderer.updateLines(rows.first, rows.last); }; + this.onScrollTopChange = function() { + this.renderer.scrollToY(this.session.getScrollTop()); + }; + + this.onScrollLeftChange = function() { + this.renderer.scrollToX(this.session.getScrollLeft()); + }; + this.onCursorChange = function() { this.renderer.updateCursor(); diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 6664177e..f9f8010d 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -43,6 +43,7 @@ define(function(require, exports, module) { var oop = require("./lib/oop"); var dom = require("./lib/dom"); +var event = require("./lib/event"); var useragent = require("./lib/useragent"); var GutterLayer = require("./layer/gutter").Gutter; var MarkerLayer = require("./layer/marker").Marker; @@ -56,6 +57,8 @@ var editorCss = require("ace/requirejs/text!./css/editor.css"); dom.importCssString(editorCss, "ace_editor"); var VirtualRenderer = function(container, theme) { + var _self = this; + this.container = container; // TODO: this breaks rendering in Cloud9 with multiple ace instances @@ -99,16 +102,22 @@ var VirtualRenderer = function(container, theme) { this.$horizScrollAlwaysVisible = true; this.scrollBar = new ScrollBar(container); - this.scrollBar.addEventListener("scroll", this.onScroll.bind(this)); + this.scrollBar.addEventListener("scroll", function(e) { + _self.session.setScrollTop(e.data); + }); this.scrollTop = 0; + this.scrollLeft = 0; + + event.addListener(this.scroller, "scroll", function() { + _self.session.setScrollLeft(_self.scroller.scrollLeft); + }); this.cursorPos = { row : 0, column : 0 }; - var _self = this; this.$textLayer.addEventListener("changeCharaterSize", function() { _self.characterWidth = textLayer.getCharacterWidth(); _self.lineHeight = textLayer.getLineHeight(); @@ -393,10 +402,6 @@ var VirtualRenderer = function(container, theme) { } }; - this.onScroll = function(e) { - this.scrollToY(e.data); - }; - this.$updateScrollBar = function() { this.scrollBar.setInnerHeight(this.layerConfig.maxHeight); this.scrollBar.setScrollTop(this.scrollTop); @@ -488,7 +493,7 @@ var VirtualRenderer = function(container, theme) { this.scroller.style.overflowX = horizScroll ? "scroll" : "hidden"; var maxHeight = this.session.getScreenLength() * this.lineHeight; - this.scrollTop = Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight)); + this.session.setScrollTop(Math.max(0, Math.min(this.scrollTop, maxHeight - this.$size.scrollerHeight))); var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); @@ -643,7 +648,7 @@ var VirtualRenderer = function(container, theme) { this.scrollToY(top + this.lineHeight - this.$size.scrollerHeight); } - var scrollLeft = this.scroller.scrollLeft; + var scrollLeft = this.scrollLeft; if (scrollLeft > left) { if (left < this.$padding + 2 * this.layerConfig.characterWidth) @@ -660,11 +665,11 @@ var VirtualRenderer = function(container, theme) { }; this.getScrollTop = function() { - return this.scrollTop; + return this.session.getScrollTop(); }; this.getScrollLeft = function() { - return this.scroller.scrollLeft; + return this.session.getScrollLop(); }; this.getScrollTopRow = function() { @@ -695,7 +700,6 @@ var VirtualRenderer = function(container, theme) { this.scrollToY = function(scrollTop) { // after calling scrollBar.setScrollTop // scrollbar sends us event with same scrollTop. ignore it - scrollTop = Math.max(0, scrollTop); if (this.scrollTop !== scrollTop) { this.$loop.schedule(this.CHANGE_SCROLL); this.scrollTop = scrollTop; @@ -708,18 +712,19 @@ var VirtualRenderer = function(container, theme) { scrollLeft = 0; this.scroller.scrollLeft = scrollLeft; - this._emit("scrollX", this.scroller.scrollLeft); + scrollLeft = this.scroller.scrollLeft; + this._emit("scrollX", scrollLeft); }; this.scrollBy = function(deltaX, deltaY) { - deltaY && this.scrollToY(this.scrollTop + deltaY); - deltaX && this.scrollToX(this.scroller.scrollLeft + deltaX); + deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY); + deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX); }; this.isScrollableBy = function(deltaX, deltaY) { - if (deltaY < 0 && this.scrollTop > 0) + if (deltaY < 0 && this.session.getScrollTop() > 0) return true; - if (deltaY > 0 && this.scrollTop + this.$size.scrollerHeight < this.layerConfig.maxHeight) + if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight < this.layerConfig.maxHeight) return true; // todo: handle horizontal scrolling }; @@ -727,10 +732,14 @@ var VirtualRenderer = function(container, theme) { this.screenToTextCoordinates = function(pageX, pageY) { var canvasPos = this.scroller.getBoundingClientRect(); - var col = Math.round((pageX + this.scroller.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) - / this.characterWidth); - var row = Math.floor((pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) - / this.lineHeight); + var col = Math.round( + (pageX + this.scrollLeft - canvasPos.left - this.$padding - dom.getPageScrollLeft()) + / this.characterWidth + ); + var row = Math.floor( + (pageY + this.scrollTop - canvasPos.top - dom.getPageScrollTop()) + / this.lineHeight + ); return this.session.screenToDocumentPosition(row, Math.max(col, 0)); }; @@ -743,8 +752,8 @@ var VirtualRenderer = function(container, theme) { var y = pos.row * this.lineHeight; return { - pageX: canvasPos.left + x - this.getScrollLeft(), - pageY: canvasPos.top + y - this.getScrollTop() + pageX: canvasPos.left + x - this.scrollLeft, + pageY: canvasPos.top + y - this.scrollTop }; };