use zero timeout instead of a loop

This commit is contained in:
Fabian Jakobs 2010-09-29 19:31:49 +02:00
commit d9c3c8db30
2 changed files with 69 additions and 81 deletions

View file

@ -5,57 +5,52 @@
* @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt> * @license LGPLv3 <http://www.gnu.org/licenses/lgpl-3.0.txt>
* @author Fabian Jakobs <fabian AT ajax DOT org> * @author Fabian Jakobs <fabian AT ajax DOT org>
*/ */
require.def("ace/RenderLoop", require.def("ace/RenderLoop", function() {
["ace/lib/oop",
"ace/MEventEmitter"],
function(oop, MEventEmitter) {
var RenderLoop = function(fps) { var RenderLoop = function(onRender) {
this.interval = 1000 / fps; this.onRender = onRender;
this.pending = false;
this.changes = 0;
}; };
(function() { (function() {
oop.implement(this, MEventEmitter); this.schedule = function(change) {
this.changes = this.changes | change;
if (window.mozRequestAnimationFrame) { if (!this.pending) {
this.pending = true;
this.start = function() {
var _self = this; var _self = this;
this.stop(); this.setTimeoutZero(function() {
_self.pending = false;
this.$onTimeout = function() { _self.onRender(_self.changes);
_self.$dispatchEvent("tick"); _self.changes = 0;
window.mozRequestAnimationFrame(); })
} }
window.addEventListener("MozBeforePaint", this.$onTimeout, false); };
window.mozRequestAnimationFrame();
};
this.stop = function() { if (window.postMessage) {
window.removeEventListener("MozBeforePaint", this.$onTimeout, false);
this.messageName = "zero-timeout-message";
this.setTimeoutZero = function(callback) {
if (!this.attached) {
var _self = this;
window.addEventListener("message", function(e) {
if (e.source == window && _self.callback && e.data == _self.messageName) {
e.stopPropagation();
_self.callback();
}
}, false);
this.attached = true;
}
this.callback = callback;
window.postMessage(this.messageName, "*");
} }
} else { } else {
this.start = function() { this.setTimeoutZero = function(callback) {
var _self = this; setTimeout(callback, 0);
this.stop();
this.$timer = setTimeout(onTimeout, 0);
function onTimeout() {
var start = new Date();
_self.$dispatchEvent("tick");
var end = new Date();
var timeout = Math.max(10, _self.interval - (end - start));
this.$timer = setTimeout(onTimeout, timeout);
}
};
this.stop = function() {
if (this.$timer)
clearTimeout(this.$timer);
} }
} }

View file

@ -66,7 +66,7 @@ var VirtualRenderer = function(container) {
self.characterWidth = textLayer.getCharacterWidth(); self.characterWidth = textLayer.getCharacterWidth();
self.lineHeight = textLayer.getLineHeight(); self.lineHeight = textLayer.getLineHeight();
this.$changes = this.$changes | this.CHANGE_FULL; self.$loop.schedule(self.CHANGE_FULL);
}); });
event.addListener(this.$gutter, "click", lang.bind(this.$onGutterClick, this)); event.addListener(this.$gutter, "click", lang.bind(this.$onGutterClick, this));
event.addListener(this.$gutter, "dblclick", lang.bind(this.$onGutterClick, this)); event.addListener(this.$gutter, "dblclick", lang.bind(this.$onGutterClick, this));
@ -80,11 +80,8 @@ var VirtualRenderer = function(container) {
this.$updatePrintMargin(); this.$updatePrintMargin();
this.loop = new RenderLoop(50); this.$loop = new RenderLoop(lang.bind(this.$renderChanges, this));
this.loop.on("tick", lang.bind(this.$renderChanges, this)); this.$loop.schedule(this.CHANGE_FULL);
this.loop.start();
this.$changes = this.CHANGE_FULL;
}; };
(function() { (function() {
@ -107,7 +104,7 @@ var VirtualRenderer = function(container) {
this.$markerLayer.setDocument(doc); this.$markerLayer.setDocument(doc);
this.$textLayer.setDocument(doc); this.$textLayer.setDocument(doc);
this.$changes = this.$changes | this.CHANGE_FULL; this.$loop.schedule(this.CHANGE_FULL);
}; };
/** /**
@ -128,28 +125,28 @@ var VirtualRenderer = function(container) {
this.$updateLines.lastRow = lastRow; this.$updateLines.lastRow = lastRow;
} }
this.$changes = this.$changes | this.CHANGE_FULL; this.$loop.schedule(this.CHANGE_FULL);
}; };
/** /**
* Triggers full update of the text layer * Triggers full update of the text layer
*/ */
this.updateText = function() { this.updateText = function() {
this.$changes = this.$changes | this.CHANGE_TEXT; this.$loop.schedule(this.CHANGE_TEXT);
}; };
/** /**
* Triggers a full update of all layers * Triggers a full update of all layers
*/ */
this.updateFull = function() { this.updateFull = function() {
this.$changes = this.$changes | this.CHANGE_FULL; this.$loop.schedule(this.CHANGE_FULL);
}; };
/** /**
* Triggers resize of the editor * Triggers resize of the editor
*/ */
this.onResize = function() { this.onResize = function() {
this.$changes = this.$changes | this.CHANGE_SIZE; this.$loop.schedule(this.CHANGE_SIZE);
var height = dom.getInnerHeight(this.container); var height = dom.getInnerHeight(this.container);
if (this.$size.height != height) { if (this.$size.height != height) {
@ -160,7 +157,7 @@ var VirtualRenderer = function(container) {
if (this.doc) { if (this.doc) {
this.scrollToY(this.getScrollTop()); this.scrollToY(this.getScrollTop());
this.$changes = this.$changes | this.CHANGE_FULL; this.$loop.schedule(this.CHANGE_FULL);
} }
} }
@ -180,7 +177,7 @@ var VirtualRenderer = function(container) {
this.setTokenizer = function(tokenizer) { this.setTokenizer = function(tokenizer) {
this.$textLayer.setTokenizer(tokenizer); this.$textLayer.setTokenizer(tokenizer);
this.$changes = this.$changes | this.CHANGE_TEXT; this.$loop.schedule(this.CHANGE_TEXT);
}; };
this.$onGutterClick = function(e) { this.$onGutterClick = function(e) {
@ -201,7 +198,7 @@ var VirtualRenderer = function(container) {
this.$showInvisibles = showInvisibles; this.$showInvisibles = showInvisibles;
this.$textLayer.setShowInvisibles(showInvisibles); this.$textLayer.setShowInvisibles(showInvisibles);
this.$changes = this.$changes | this.CHANGE_TEXT; this.$loop.schedule(this.CHANGE_TEXT);
}; };
this.getShowInvisibles = function() { this.getShowInvisibles = function() {
@ -268,23 +265,22 @@ var VirtualRenderer = function(container) {
this.scrollBar.setScrollTop(this.scrollTop); this.scrollBar.setScrollTop(this.scrollTop);
}; };
this.$renderChanges = function() { this.$renderChanges = function(changes) {
if (!this.$changes) if (!changes)
return; return;
// text, scrolling and resize changes can cause the view port size to change // text, scrolling and resize changes can cause the view port size to change
if (!this.layerConfig || if (!this.layerConfig ||
this.$changes & this.CHANGE_FULL || changes & this.CHANGE_FULL ||
this.$changes & this.CHANGE_SIZE || changes & this.CHANGE_SIZE ||
this.$changes & this.CHANGE_TEXT || changes & this.CHANGE_TEXT ||
this.$changes & this.CHANGE_LINES || changes & this.CHANGE_LINES ||
this.$changes & this.CHANGE_SCROLL changes & this.CHANGE_SCROLL
) )
this.$computeLayerConfig(); this.$computeLayerConfig();
// full // full
if (this.$changes & this.CHANGE_FULL) { if (changes & this.CHANGE_FULL) {
this.$changes = 0;
this.$textLayer.update(this.layerConfig); this.$textLayer.update(this.layerConfig);
this.$gutterLayer.update(this.layerConfig); this.$gutterLayer.update(this.layerConfig);
this.$markerLayer.update(this.layerConfig); this.$markerLayer.update(this.layerConfig);
@ -294,8 +290,8 @@ var VirtualRenderer = function(container) {
} }
// scrolling // scrolling
if (this.$changes & this.CHANGE_SCROLL) { if (changes & this.CHANGE_SCROLL) {
if (this.$changes & this.CHANGE_TEXT || this.$changes & this.CHANGE_LINES) { if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES) {
this.$textLayer.scrollLines(this.layerConfig); this.$textLayer.scrollLines(this.layerConfig);
this.$gutterLayer.update(this.layerConfig); this.$gutterLayer.update(this.layerConfig);
this.$markerLayer.update(this.layerConfig); this.$markerLayer.update(this.layerConfig);
@ -308,35 +304,32 @@ var VirtualRenderer = function(container) {
this.$cursorLayer.update(this.layerConfig); this.$cursorLayer.update(this.layerConfig);
} }
this.$updateScrollBar(); this.$updateScrollBar();
this.$changes = 0;
return; return;
} }
if (this.$changes & this.CHANGE_TEXT) { if (changes & this.CHANGE_TEXT) {
this.$textLayer.update(this.layerConfig); this.$textLayer.update(this.layerConfig);
this.$gutterLayer.update(this.layerConfig); this.$gutterLayer.update(this.layerConfig);
} }
else if (this.$changes & this.CHANGE_LINES) { else if (changes & this.CHANGE_LINES) {
this.$updateLines(); this.$updateLines();
} }
else if (this.$changes & this.CHANGE_SCROLL) { else if (changes & this.CHANGE_SCROLL) {
this.$textLayer.scrollLines(this.layerConfig); this.$textLayer.scrollLines(this.layerConfig);
this.$gutterLayer.update(this.layerConfig); this.$gutterLayer.update(this.layerConfig);
} if (this.$changes & this.CHANGE_GUTTER) { } if (changes & this.CHANGE_GUTTER) {
this.$gutterLayer.update(this.layerConfig); this.$gutterLayer.update(this.layerConfig);
} }
if (this.$changes & this.CHANGE_CURSOR) if (changes & this.CHANGE_CURSOR)
this.$cursorLayer.update(this.layerConfig); this.$cursorLayer.update(this.layerConfig);
if (this.$changes & this.CHANGE_MARKER) { if (changes & this.CHANGE_MARKER) {
this.$markerLayer.update(this.layerConfig); this.$markerLayer.update(this.layerConfig);
} }
if (this.$changes & this.CHANGE_SIZE) if (changes & this.CHANGE_SIZE)
this.$updateScrollBar(); this.$updateScrollBar();
this.$changes = 0;
}; };
this.$computeLayerConfig = function() { this.$computeLayerConfig = function() {
@ -403,22 +396,22 @@ var VirtualRenderer = function(container) {
this.addMarker = function(range, clazz, type) { this.addMarker = function(range, clazz, type) {
return this.$markerLayer.addMarker(range, clazz, type); return this.$markerLayer.addMarker(range, clazz, type);
this.$changes = this.$changes | this.CHANGE_MARKER; this.$loop.schedule(this.CHANGE_MARKER);
}; };
this.removeMarker = function(markerId) { this.removeMarker = function(markerId) {
this.$markerLayer.removeMarker(markerId); this.$markerLayer.removeMarker(markerId);
this.$changes = this.$changes | this.CHANGE_MARKER; this.$loop.schedule(this.CHANGE_MARKER);
}; };
this.setBreakpoints = function(rows) { this.setBreakpoints = function(rows) {
this.$gutterLayer.setBreakpoints(rows); this.$gutterLayer.setBreakpoints(rows);
this.$changes = this.$changes | this.CHANGE_GUTTER; this.$loop.schedule(this.CHANGE_GUTTER);
}; };
this.updateCursor = function(position, overwrite) { this.updateCursor = function(position, overwrite) {
this.$cursorLayer.setCursor(position, overwrite); this.$cursorLayer.setCursor(position, overwrite);
this.$changes = this.$changes | this.CHANGE_CURSOR; this.$loop.schedule(this.CHANGE_CURSOR);
}; };
this.hideCursor = function() { this.hideCursor = function() {
@ -473,7 +466,7 @@ var VirtualRenderer = function(container) {
if (this.scrollTop !== scrollTop) { if (this.scrollTop !== scrollTop) {
this.scrollTop = scrollTop; this.scrollTop = scrollTop;
this.$changes = this.$changes | this.CHANGE_SCROLL; this.$loop.schedule(this.CHANGE_SCROLL);
} }
}; };