From f74185870fbf57f01c8e36bfb6ff695032301f7f Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 27 Dec 2012 19:39:06 +0400 Subject: [PATCH] better way for managing options --- demo/kitchen-sink/statusbar.js | 6 +- lib/ace/config.js | 89 +++++++++++++ lib/ace/config_test.js | 49 ++++++- lib/ace/edit_session.js | 97 ++++++++------ lib/ace/editor.js | 208 ++++++------------------------ lib/ace/keyboard/hash_handler.js | 2 +- lib/ace/layer/gutter.js | 3 +- lib/ace/mouse/default_handlers.js | 12 +- lib/ace/mouse/mouse_handler.js | 27 ++-- lib/ace/test/all_browser.js | 1 + lib/ace/virtual_renderer.js | 175 ++++++++++--------------- 11 files changed, 324 insertions(+), 345 deletions(-) diff --git a/demo/kitchen-sink/statusbar.js b/demo/kitchen-sink/statusbar.js index 946ae1d4..57620036 100644 --- a/demo/kitchen-sink/statusbar.js +++ b/demo/kitchen-sink/statusbar.js @@ -9,14 +9,14 @@ var StatusBar = function(editor, parentNode) { this.element.style.cssText = "color: gray; position:absolute; right:0; border-left:1px solid"; parentNode.appendChild(this.element); - var statusUpdate = lang.deferredCall(function(){ + var statusUpdate = lang.delayedCall(function(){ this.updateStatus(editor) }.bind(this)); editor.on("changeStatus", function() { - statusUpdate.schedule(50); + statusUpdate.schedule(100); }); editor.on("changeSelection", function() { - statusUpdate.schedule(50); + statusUpdate.schedule(100); }); }; diff --git a/lib/ace/config.js b/lib/ace/config.js index b242e990..bdd6a162 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -169,4 +169,93 @@ function deHyphenate(str) { return str.replace(/-(.)/g, function(m, m1) { return m1.toUpperCase(); }); } +function capitalize(str) { + return str[0].toUpperCase() + str.substr(1); +} + + +var optionsProvider = { + setOptions: function(optList) { + Object.keys(optList).forEach(function(key) { + this.setOption(key, optList[key]); + }, this); + }, + getOptions: function(a) { + var b = {}; + Object.keys(a).forEach(function(key) { + b[key] = this.getOption(key); + }, this); + return b; + }, + setOption: function(name, value) { + if (this["$" + name] === value) + return; + var opt = this.$options[name]; + if (!opt) + return undefined; + if (opt.forwardTo) + return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value); + + if (!opt.handlesSet) + this["$" + name] = value; + if (opt && opt.set) + opt.set.call(this, value); + }, + getOption: function(name) { + var opt = this.$options[name]; + if (!opt) + return undefined; + if (opt.forwardTo) + return this[opt.forwardTo] && this[opt.forwardTo].getOption(name); + return opt && opt.get ? opt.get.call(this) : this["$" + name]; + } +}; + +var defaultOptions = {}; +/* + * option {name, value, initialValue, setterName, set, get } + */ +exports.defineOptions = function(obj, path, options) { + if (!obj.$options) + defaultOptions[path] = obj.$options = {}; + + Object.keys(options).forEach(function(key) { + var opt = options[key]; + if (typeof opt == "string") + opt = {forwardTo: opt}; + + opt.name || (opt.name = key); + obj.$options[opt.name] = opt; + if ("initialValue" in opt) + obj["$" + opt.name] = opt.initialValue; + + opt.setterName = capitalize(opt.name) + if (opt.setterName) { + addSetters(obj, opt.name, opt.setterName); + } + }); + + // implement option provider interface + oop.implement(obj, optionsProvider); + + return this; +}; + +function addSetters(obj, name, setterName) { + obj["set" + setterName] = function(value) { + return this.setOption(name, value) + }; + obj["get" + setterName] = function() { + return this.getOption(name) + }; +}; + +exports.resetOptions = function(obj) { + Object.keys(obj.$options).forEach(function(key) { + var opt = obj.$options[key]; + if ("value" in opt) + obj.setOption(key, opt.value); + }); +}; + }); diff --git a/lib/ace/config_test.js b/lib/ace/config_test.js index 9d0c4697..0e4f5449 100644 --- a/lib/ace/config_test.js +++ b/lib/ace/config_test.js @@ -40,7 +40,7 @@ var assert = require("./test/assertions"); module.exports = { - "test path resolution" : function() { + "test: path resolution" : function() { config.set("packaged", "true"); var url = config.moduleUrl("kr_theme", "theme"); assert.equal(url, "theme-kr.js"); @@ -61,6 +61,53 @@ module.exports = { assert.equal(url, "a/b1.js"); assert.equal(); + }, + "test: define options" : function() { + var o = {}; + config.defineOptions(o, "test_object", { + opt1: { + set: function(val) { + this.x = val; + }, + value: 7, + }, + initialValue: { + set: function(val) { + this.x = val; + }, + initialValue: 8, + }, + opt2: { + get: function(val) { + return this.x; + } + }, + forwarded: "model" + }); + o.model = {}; + config.defineOptions(o.model, "model", { + forwarded: {value: 1} + }); + + config.resetOptions(o); + config.resetOptions(o.model); + assert.equal(o.getOption("opt1"), 7); + assert.equal(o.getOption("opt2"), 7); + o.setOption("opt1", 8); + assert.equal(o.getOption("opt1"), 8); + assert.equal(o.getOption("opt2"), 8); + + assert.equal(o.getOption("forwarded"), 1); + + assert.equal(o.getOption("new"), undefined); + o.setOption("new", 0); + assert.equal(o.getOption("new"), undefined); + + + assert.equal(o.getOption("initialValue"), 8); + o.setOption("initialValue", 7); + assert.equal(o.getOption("opt2"), 7); + } }; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 9ac41352..81afdb4e 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -42,6 +42,7 @@ var Range = require("./range").Range; var Document = require("./document").Document; var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer; var SearchHighlight = require("./search_highlight").SearchHighlight; +var config = require("./config"); /** * @@ -175,6 +176,9 @@ var EditSession = function(text, mode) { this.selection = new Selection(this); this.setMode(mode); + + config.resetOptions(this); + config._emit("session", this); }; @@ -452,50 +456,26 @@ var EditSession = function(text, mode) { } }; - this.$useSoftTabs = true; /** * Pass `true` to enable the use of soft tabs. Soft tabs means you're using spaces instead of the tab character (`'\t'`). * @param {Boolean} useSoftTabs Value indicating whether or not to use soft tabs * - * - * **/ - this.setUseSoftTabs = function(useSoftTabs) { - if (this.$useSoftTabs === useSoftTabs) return; - - this.$useSoftTabs = useSoftTabs; - }; /** * Returns `true` if soft tabs are being used, `false` otherwise. * @returns {Boolean} **/ - this.getUseSoftTabs = function() { - return this.$useSoftTabs; - }; - this.$tabSize = 4; /** * Set the number of spaces that define a soft tab; for example, passing in `4` transforms the soft tabs to be equivalent to four spaces. This function also emits the `changeTabSize` event. * @param {Number} tabSize The new tab size * * **/ - this.setTabSize = function(tabSize) { - if (isNaN(tabSize) || this.$tabSize === tabSize) return; - - this.$modified = true; - this.$rowLengthCache = []; - this.$tabSize = tabSize; - this._emit("changeTabSize"); - }; - /** * Returns the current tab size. **/ - this.getTabSize = function() { - return this.$tabSize; - }; /** * Returns `true` if the character at the position is a soft tab. @@ -864,31 +844,14 @@ var EditSession = function(text, mode) { return this.doc.getNewLineMode(); }; - this.$useWorker = true; - /** * Identifies if you want to use a worker for the `EditSession`. * @param {Boolean} useWorker Set to `true` to use a worker * **/ - this.setUseWorker = function(useWorker) { - if (this.$useWorker == useWorker) - return; - - this.$useWorker = useWorker; - - this.$stopWorker(); - if (useWorker) - this.$startWorker(); - }; - /** * Returns `true` if workers are being used. **/ - this.getUseWorker = function() { - return this.$useWorker; - }; - /** * Reloads all the tokens on the current session. This function calls [[BackgroundTokenizer.start `BackgroundTokenizer.start ()`]] to all the rows; it also emits the `'tokenizerUpdate'` event. **/ @@ -2403,5 +2366,57 @@ var EditSession = function(text, mode) { require("./edit_session/folding").Folding.call(EditSession.prototype); require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype); +config.defineOptions(EditSession.prototype, "session", { + wrap: { + set: function(value) { + if (!value || value == "off") + value = false; + else if (value == "free") + value = true; + else if (typeof value == "string") + value = parseInt(value, 10) || false; + + if (!value) { + this.setUseWrapMode(false); + } else { + var col = typeof value == "number" && value; + this.setUseWrapMode(true); + this.setWrapLimitRange(value, value); + } + this.$wrap = value; + }, + get: function() { + return this.getUseWrapMode() ? this.getWrapLimitRange().min || "free" : "off"; + }, + handlesSet: true + }, + firstLineNumber: { + set: function() {this._emit("changeBreakpoint");}, + initialValue: 1 + }, + useWorker: { + set: function(useWorker) { + this.$useWorker = useWorker; + + this.$stopWorker(); + if (useWorker) + this.$startWorker(); + }, + initialValue: true + }, + useSoftTabs: {initialValue: true}, + tabSize: { + set: function(tabSize) { + if (isNaN(tabSize) || this.$tabSize === tabSize) return; + + this.$modified = true; + this.$rowLengthCache = []; + this.$tabSize = tabSize; + this._emit("changeTabSize"); + }, + initialValue: 4 + } +}); + exports.EditSession = EditSession; }); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index cbd0ef71..7ab2e564 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -88,6 +88,8 @@ var Editor = function(renderer, session) { }); this.setSession(session || new EditSession("")); + config.resetOptions(this); + config._emit("editor", this); }; (function(){ @@ -807,18 +809,10 @@ var Editor = function(renderer, session) { * * **/ - this.setScrollSpeed = function(speed) { - this.$mouseHandler.setScrollSpeed(speed); - }; - /** * Returns the value indicating how fast the mouse scroll speed is (in milliseconds). * @returns {Number} **/ - this.getScrollSpeed = function() { - return this.$mouseHandler.getScrollSpeed(); - }; - /** * Sets the delay (in milliseconds) of the mouse drag. * @param {Number} dragDelay A value indicating the new delay @@ -826,19 +820,10 @@ var Editor = function(renderer, session) { * * **/ - this.setDragDelay = function(dragDelay) { - this.$mouseHandler.setDragDelay(dragDelay); - }; - /** * Returns the current mouse drag delay. * @returns {Number} **/ - this.getDragDelay = function() { - return this.$mouseHandler.getDragDelay(); - }; - - this.$selectionStyle = "line"; /** * Emitted when the selection style changes, via [[Editor.setSelectionStyle]]. @@ -860,133 +845,49 @@ var Editor = function(renderer, session) { * * **/ - this.setSelectionStyle = function(style) { - if (this.$selectionStyle == style) return; - - this.$selectionStyle = style; - this.onSelectionChange(); - this._emit("changeSelectionStyle", {data: style}); - }; - /** * Returns the current selection style. * @returns {String} **/ - this.getSelectionStyle = function() { - return this.$selectionStyle; - }; - - this.$highlightActiveLine = true; - /** * Determines whether or not the current line should be highlighted. * @param {Boolean} shouldHighlight Set to `true` to highlight the current line * **/ - this.setHighlightActiveLine = function(shouldHighlight) { - if (this.$highlightActiveLine == shouldHighlight) - return; - - this.$highlightActiveLine = shouldHighlight; - this.$updateHighlightActiveLine(); - }; - /** * Returns `true` if current lines are always highlighted. * @return {Boolean} **/ - this.getHighlightActiveLine = function() { - return this.$highlightActiveLine; - }; - - this.$highlightGutterLine = true; - this.setHighlightGutterLine = function(shouldHighlight) { - if (this.$highlightGutterLine == shouldHighlight) - return; - - this.renderer.setHighlightGutterLine(shouldHighlight); - this.$highlightGutterLine = shouldHighlight; - }; - - this.getHighlightGutterLine = function() { - return this.$highlightGutterLine; - }; - - this.$highlightSelectedWord = true; /** * Determines if the currently selected word should be highlighted. * @param {Boolean} shouldHighlight Set to `true` to highlight the currently selected word * * **/ - this.setHighlightSelectedWord = function(shouldHighlight) { - if (this.$highlightSelectedWord == shouldHighlight) - return; - - this.$highlightSelectedWord = shouldHighlight; - this.$onSelectionChange(); - }; - /** * Returns `true` if currently highlighted words are to be highlighted. * @returns {Boolean} **/ - this.getHighlightSelectedWord = function() { - return this.$highlightSelectedWord; - }; - - this.setAnimatedScroll = function(shouldAnimate){ - this.renderer.setAnimatedScroll(shouldAnimate); - }; - - this.getAnimatedScroll = function(){ - return this.renderer.getAnimatedScroll(); - }; - /** * If `showInvisibiles` is set to `true`, invisible characters—like spaces or new lines—are show in the editor. * @param {Boolean} showInvisibles Specifies whether or not to show invisible characters * * **/ - this.setShowInvisibles = function(showInvisibles) { - this.renderer.setShowInvisibles(showInvisibles); - }; - /** * Returns `true` if invisible characters are being shown. * @returns {Boolean} **/ - this.getShowInvisibles = function() { - return this.renderer.getShowInvisibles(); - }; - - this.setDisplayIndentGuides = function(display) { - this.renderer.setDisplayIndentGuides(display); - }; - - this.getDisplayIndentGuides = function() { - return this.renderer.getDisplayIndentGuides(); - }; - /** * If `showPrintMargin` is set to `true`, the print margin is shown in the editor. * @param {Boolean} showPrintMargin Specifies whether or not to show the print margin * * **/ - this.setShowPrintMargin = function(showPrintMargin) { - this.renderer.setShowPrintMargin(showPrintMargin); - }; - /** * Returns `true` if the print margin is being shown. * @returns {Boolean} **/ - this.getShowPrintMargin = function() { - return this.renderer.getShowPrintMargin(); - }; - /** * Sets the column defining where the print margin should be. * @param {Number} showPrintMargin Specifies the new print margin @@ -994,61 +895,26 @@ var Editor = function(renderer, session) { * * **/ - this.setPrintMarginColumn = function(showPrintMargin) { - this.renderer.setPrintMarginColumn(showPrintMargin); - }; - /** * Returns the column number of where the print margin is. * @returns {Number} **/ - this.getPrintMarginColumn = function() { - return this.renderer.getPrintMarginColumn(); - }; - - this.$readOnly = false; /** * If `readOnly` is true, then the editor is set to read-only mode, and none of the content can change. * @param {Boolean} readOnly Specifies whether the editor can be modified or not * * **/ - this.setReadOnly = function(readOnly) { - this.$readOnly = readOnly; - this.textInput.setReadOnly(readOnly); - this.renderer.$cursorLayer.setBlinking(!readOnly); - }; - /** * Returns `true` if the editor is set to read-only mode. * @returns {Boolean} **/ - this.getReadOnly = function() { - return this.$readOnly; - }; - - this.$modeBehaviours = true; - /** * Specifies whether to use behaviors or not. ["Behaviors" in this case is the auto-pairing of special characters, like quotation marks, parenthesis, or brackets.]{: #BehaviorsDef} * @param {Boolean} enabled Enables or disables behaviors * * **/ - this.setBehavioursEnabled = function (enabled) { - this.$modeBehaviours = enabled; - }; - - /** - * Returns `true` if the behaviors are currently enabled. {:BehaviorsDef} - * - * @returns {Boolean} - **/ - this.getBehavioursEnabled = function () { - return this.$modeBehaviours; - }; - - this.$modeWrapBehaviours = true; /** * Specifies whether to use wrapping behaviors or not, i.e. automatically wrapping the selection with characters such as brackets @@ -1056,49 +922,19 @@ var Editor = function(renderer, session) { * @param {Boolean} enabled Enables or disables wrapping behaviors * **/ - this.setWrapBehavioursEnabled = function (enabled) { - this.$modeWrapBehaviours = enabled; - }; - /** * Returns `true` if the wrapping behaviors are currently enabled. **/ - this.getWrapBehavioursEnabled = function () { - return this.$modeWrapBehaviours; - }; /** * Indicates whether the fold widgets are shown or not. * @param {Boolean} show Specifies whether the fold widgets are shown * - * **/ - this.setShowFoldWidgets = function(show) { - var gutter = this.renderer.$gutterLayer; - if (gutter.getShowFoldWidgets() == show) - return; - - this.renderer.$gutterLayer.setShowFoldWidgets(show); - this.$showFoldWidgets = show; - this.renderer.updateFull(); - }; - /** * Returns `true` if the fold widgets are shown. * @return {Boolean} **/ - this.getShowFoldWidgets = function() { - return this.renderer.$gutterLayer.getShowFoldWidgets(); - }; - - this.setFadeFoldWidgets = function(show) { - this.renderer.setFadeFoldWidgets(show); - }; - - this.getFadeFoldWidgets = function() { - return this.renderer.getFadeFoldWidgets(); - }; - /** * Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace. * @param {String} dir The direction of the deletion to occur, either "left" or "right" @@ -2172,5 +2008,45 @@ var Editor = function(renderer, session) { }).call(Editor.prototype); + +config.defineOptions(Editor.prototype, "editor", { + selectionStyle: { + set: function(style) { + this.onSelectionChange(); + this._emit("changeSelectionStyle", {data: style}); + }, + initialValue: "line", + }, + highlightActiveLine: { + set: function() {this.$updateHighlightActiveLine();}, + initialValue: true + }, + highlightSelectedWord: { + set: function(shouldHighlight) {this.$onSelectionChange();}, + initialValue: true + }, + readOnly: { + set: function(readOnly) { + this.textInput.setReadOnly(readOnly); + this.renderer.$cursorLayer.setBlinking(!readOnly); + }, + initialValue: false + }, + behavioursEnabled: {initialValue: true}, + wrapBehavioursEnabled: {initialValue: true}, + + highlightGutterLine: "renderer", + animatedScroll: "renderer", + showInvisibles: "renderer", + showPrintMargin: "renderer", + printMarginColumn: "renderer", + fadeFoldWidgets: "renderer", + showFoldWidgets: "renderer", + displayIndentGuides: "renderer", + scrollSpeed: "$mouseHandler", + dragDelay: "$mouseHandler", + focusTimout: "$mouseHandler" +}); + exports.Editor = Editor; }); diff --git a/lib/ace/keyboard/hash_handler.js b/lib/ace/keyboard/hash_handler.js index 92001c02..9f0d7128 100644 --- a/lib/ace/keyboard/hash_handler.js +++ b/lib/ace/keyboard/hash_handler.js @@ -31,7 +31,7 @@ define(function(require, exports, module) { "use strict"; -var keyUtil = require("../lib/keys"); +var keyUtil = require("../lib/keys"); function HashHandler(config, platform) { this.platform = platform; diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index 99fec7b6..109d6a67 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -126,6 +126,7 @@ var Gutter = function(parentEl) { var foldWidgets = this.$showFoldWidgets && this.session.foldWidgets; var breakpoints = this.session.$breakpoints; var decorations = this.session.$decorations; + var firstLineNumber = this.session.$firstLineNumber; var lastLineNumber = 0; while (true) { @@ -142,7 +143,7 @@ var Gutter = function(parentEl) { "
", - lastLineNumber = i + 1 + lastLineNumber = i + firstLineNumber ); if (foldWidgets) { diff --git a/lib/ace/mouse/default_handlers.js b/lib/ace/mouse/default_handlers.js index f58b6644..a6ce5c61 100644 --- a/lib/ace/mouse/default_handlers.js +++ b/lib/ace/mouse/default_handlers.js @@ -34,7 +34,7 @@ define(function(require, exports, module) { var dom = require("../lib/dom"); var useragent = require("../lib/useragent"); -var DRAG_OFFSET = 5; // pixels +var DRAG_OFFSET = 0; // pixels function DefaultHandlers(mouseHandler) { mouseHandler.$clickSelection = null; @@ -55,8 +55,6 @@ function DefaultHandlers(mouseHandler) { mouseHandler.selectByLines = this.extendSelectionBy.bind(mouseHandler, "getLineRange"); mouseHandler.selectByWords = this.extendSelectionBy.bind(mouseHandler, "getWordRange"); - - mouseHandler.$focusWaitTimout = 250; } (function() { @@ -86,7 +84,7 @@ function DefaultHandlers(mouseHandler) { // selection if (inSelection && !editor.isFocused()) { editor.focus(); - if (this.$focusWaitTimout && !this.$clickSelection) { + if (this.$focusTimout && !this.$clickSelection) { this.setState("focusWait"); this.captureMouse(ev); return ev.preventDefault(); @@ -205,8 +203,8 @@ function DefaultHandlers(mouseHandler) { var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); var time = (new Date()).getTime(); - if (distance > DRAG_OFFSET ||time - this.mousedownEvent.time > this.$focusWaitTimout) - this.startSelect(); + if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) + this.startSelect(this.mousedownEvent.getDocumentPosition()); }; this.dragWait = function(e) { @@ -216,7 +214,7 @@ function DefaultHandlers(mouseHandler) { if (distance > DRAG_OFFSET) { this.startSelect(this.mousedownEvent.getDocumentPosition()); - } else if (time - this.mousedownEvent.time > editor.getDragDelay()) { + } else if (time - this.mousedownEvent.time > editor.$mouseHandler.$dragDelay) { this.startDrag(); } }; diff --git a/lib/ace/mouse/mouse_handler.js b/lib/ace/mouse/mouse_handler.js index 503aeabc..bdc0b604 100644 --- a/lib/ace/mouse/mouse_handler.js +++ b/lib/ace/mouse/mouse_handler.js @@ -37,6 +37,7 @@ var DefaultHandlers = require("./default_handlers").DefaultHandlers; var DefaultGutterHandler = require("./default_gutter_handler").GutterHandler; var MouseEvent = require("./mouse_event").MouseEvent; var DragdropHandler = require("./dragdrop").DragdropHandler; +var config = require("../config"); var MouseHandler = function(editor) { this.editor = editor; @@ -64,29 +65,10 @@ var MouseHandler = function(editor) { }; (function() { - - this.$scrollSpeed = 1; - this.setScrollSpeed = function(speed) { - this.$scrollSpeed = speed; - }; - - this.getScrollSpeed = function() { - return this.$scrollSpeed; - }; - this.onMouseEvent = function(name, e) { this.editor._emit(name, new MouseEvent(e, this.editor)); }; - this.$dragDelay = 250; - this.setDragDelay = function(dragDelay) { - this.$dragDelay = dragDelay; - }; - - this.getDragDelay = function() { - return this.$dragDelay; - }; - this.onMouseMove = function(name, e) { // optimization, because mousemove doesn't have a default handler. var listeners = this.editor._eventRegistry && this.editor._eventRegistry.mousemove; @@ -157,5 +139,12 @@ var MouseHandler = function(editor) { }; }).call(MouseHandler.prototype); +config.defineOptions(MouseHandler.prototype, "mouseHandler", { + scrollSpeed: {initialValue: 1}, + dragDelay: {initialValue: 150}, + focusTimout: {initialValue: 0} +}); + + exports.MouseHandler = MouseHandler; }); diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index baa13a1d..9437426a 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -13,6 +13,7 @@ var testNames = [ "ace/anchor_test", "ace/background_tokenizer_test", "ace/commands/command_manager_test", + "ace/config_test", "ace/document_test", "ace/edit_session_test", "ace/editor_change_document_test", diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 6192b133..beebd80c 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -94,7 +94,6 @@ var VirtualRenderer = function(container, theme) { this.content.className = "ace_content"; this.scroller.appendChild(this.content); - this.setHighlightGutterLine(true); this.$gutterLayer = new GutterLayer(this.$gutter); this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this)); @@ -111,8 +110,6 @@ var VirtualRenderer = function(container, theme) { this.$horizScroll = false; this.$horizScrollAlwaysVisible = false; - this.$animatedScroll = false; - this.scrollBar = new ScrollBar(this.container); this.scrollBar.addEventListener("scroll", function(e) { if (!_self.$inScrollAnimation) @@ -167,10 +164,11 @@ var VirtualRenderer = function(container, theme) { this.updateCharacterSize(); this.setPadding(4); + config.resetOptions(this); + config._emit("renderer", this); }; (function() { - this.showGutter = true; this.CHANGE_CURSOR = 1; this.CHANGE_MARKER = 2; @@ -321,7 +319,7 @@ var VirtualRenderer = function(container, theme) { if (width && (force || this.resizing > 1 || size.width != width)) { size.width = width; - var gutterWidth = this.showGutter ? this.$gutter.offsetWidth : 0; + var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; this.scroller.style.left = gutterWidth + "px"; size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth()); this.scroller.style.right = this.scrollBar.getWidth() + "px"; @@ -341,7 +339,7 @@ var VirtualRenderer = function(container, theme) { this.onGutterResize = function() { var width = this.$size.width; - var gutterWidth = this.showGutter ? this.$gutter.offsetWidth : 0; + var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; this.scroller.style.left = gutterWidth + "px"; this.$size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBar.getWidth()); @@ -366,19 +364,11 @@ var VirtualRenderer = function(container, theme) { * * **/ - this.setAnimatedScroll = function(shouldAnimate){ - this.$animatedScroll = shouldAnimate; - }; - /** * * Returns whether an animated scroll happens or not. * @returns {Boolean} **/ - this.getAnimatedScroll = function() { - return this.$animatedScroll; - }; - /** * Identifies whether you want to show invisible characters or not. * @param {Boolean} showInvisibles Set to `true` to show invisibles @@ -386,31 +376,11 @@ var VirtualRenderer = function(container, theme) { * * **/ - this.setShowInvisibles = function(showInvisibles) { - if (this.$textLayer.setShowInvisibles(showInvisibles)) - this.$loop.schedule(this.CHANGE_TEXT); - }; - /** * * Returns whether invisible characters are being shown or not. * @returns {Boolean} **/ - this.getShowInvisibles = function() { - return this.$textLayer.showInvisibles; - }; - - this.getDisplayIndentGuides = function() { - return this.$textLayer.displayIndentGuides; - }; - - this.setDisplayIndentGuides = function(display) { - if (this.$textLayer.setDisplayIndentGuides(display)) - this.$loop.schedule(this.CHANGE_TEXT); - }; - - this.$showPrintMargin = true; - /** * Identifies whether you want to show the print margin or not. * @param {Boolean} showPrintMargin Set to `true` to show the print margin @@ -418,21 +388,10 @@ var VirtualRenderer = function(container, theme) { * * **/ - this.setShowPrintMargin = function(showPrintMargin) { - this.$showPrintMargin = showPrintMargin; - this.$updatePrintMargin(); - }; - /** * Returns whether the print margin is being shown or not. * @returns {Boolean} **/ - this.getShowPrintMargin = function() { - return this.$showPrintMargin; - }; - - this.$printMarginColumn = 80; - /** * Identifies whether you want to show the print margin column or not. * @param {Boolean} showPrintMargin Set to `true` to show the print margin column @@ -440,77 +399,22 @@ var VirtualRenderer = function(container, theme) { * * **/ - this.setPrintMarginColumn = function(showPrintMargin) { - this.$printMarginColumn = showPrintMargin; - this.$updatePrintMargin(); - }; - /** * * Returns whether the print margin column is being shown or not. * @returns {Boolean} **/ - this.getPrintMarginColumn = function() { - return this.$printMarginColumn; - }; - /** * * Returns `true` if the gutter is being shown. * @returns {Boolean} **/ - this.getShowGutter = function(){ - return this.showGutter; - }; - /** * Identifies whether you want to show the gutter or not. * @param {Boolean} show Set to `true` to show the gutter * * **/ - this.setShowGutter = function(show){ - if(this.showGutter === show) - return; - this.$gutter.style.display = show ? "block" : "none"; - this.showGutter = show; - this.onResize(true); - }; - - this.getFadeFoldWidgets = function(){ - return dom.hasCssClass(this.$gutter, "ace_fade-fold-widgets"); - }; - - this.setFadeFoldWidgets = function(show) { - if (show) - dom.addCssClass(this.$gutter, "ace_fade-fold-widgets"); - else - dom.removeCssClass(this.$gutter, "ace_fade-fold-widgets"); - }; - - this.$highlightGutterLine = false; - this.setHighlightGutterLine = function(shouldHighlight) { - if (this.$highlightGutterLine == shouldHighlight) - return; - this.$highlightGutterLine = shouldHighlight; - - if (!this.$gutterLineHighlight) { - this.$gutterLineHighlight = dom.createElement("div"); - this.$gutterLineHighlight.className = "ace_gutter-active-line"; - this.$gutter.appendChild(this.$gutterLineHighlight); - return; - } - - this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; - // if cursorlayer have never been updated there's nothing on screen to update - if (this.$cursorLayer.$pixelPos) - this.$updateGutterLineHighlight(); - }; - - this.getHighlightGutterLine = function() { - return this.$highlightGutterLine; - }; - this.$updateGutterLineHighlight = function() { this.$gutterLineHighlight.style.top = this.$cursorLayer.$pixelPos.top - this.layerConfig.offset + "px"; this.$gutterLineHighlight.style.height = this.layerConfig.lineHeight + "px"; @@ -706,7 +610,7 @@ var VirtualRenderer = function(container, theme) { // update scrollbar first to not lose scroll position when gutter calls resize this.$updateScrollBar(); this.$textLayer.update(this.layerConfig); - if (this.showGutter) + if (this.$showGutter) this.$gutterLayer.update(this.layerConfig); this.$markerBack.update(this.layerConfig); this.$markerFront.update(this.layerConfig); @@ -724,7 +628,7 @@ var VirtualRenderer = function(container, theme) { else this.$textLayer.scrollLines(this.layerConfig); - if (this.showGutter) + if (this.$showGutter) this.$gutterLayer.update(this.layerConfig); this.$markerBack.update(this.layerConfig); this.$markerFront.update(this.layerConfig); @@ -736,15 +640,15 @@ var VirtualRenderer = function(container, theme) { if (changes & this.CHANGE_TEXT) { this.$textLayer.update(this.layerConfig); - if (this.showGutter) + if (this.$showGutter) this.$gutterLayer.update(this.layerConfig); } else if (changes & this.CHANGE_LINES) { - if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.showGutter) + if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter) this.$gutterLayer.update(this.layerConfig); } else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) { - if (this.showGutter) + if (this.$showGutter) this.$gutterLayer.update(this.layerConfig); } @@ -852,7 +756,7 @@ var VirtualRenderer = function(container, theme) { // if the last row is unknown -> redraw everything if (lastRow === Infinity) { - if (this.showGutter) + if (this.$showGutter) this.$gutterLayer.update(layerConfig); this.$textLayer.update(layerConfig); return; @@ -1374,5 +1278,64 @@ var VirtualRenderer = function(container, theme) { }).call(VirtualRenderer.prototype); + +config.defineOptions(VirtualRenderer.prototype, "renderer", { + animatedScroll: {initialValue: false}, + showInvisibles: { + set: function(value) { + if (this.$textLayer.setShowInvisibles(value)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: false + }, + showPrintMargin: { + set: function() { this.$updatePrintMargin(); }, + initialValue: true + }, + printMarginColumn: { + set: function() { this.$updatePrintMargin(); }, + initialValue: 80 + }, + showGutter: { + set: function(show){ + this.$gutter.style.display = show ? "block" : "none"; + this.onGutterResize(); + }, + initialValue: true + }, + fadeFoldWidgets: { + set: function(show) { + dom.addCssClass(this.$gutter, "ace_fade-fold-widgets", show); + }, + initialValue: false + }, + showFoldWidgets: { + set: function(show) {this.$gutterLayer.setShowFoldWidgets(show)}, + initialValue: true + }, + displayIndentGuides: { + set: function(show) { + if (this.$textLayer.setDisplayIndentGuides(show)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: true + }, + + highlightGutterLine: { + set: function(shouldHighlight) { + if (!this.$gutterLineHighlight) { + this.$gutterLineHighlight = dom.createElement("div"); + this.$gutterLineHighlight.className = "ace_gutter_active_line"; + this.$gutter.appendChild(this.$gutterLineHighlight); + return; + } + + this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; + this.$cursorLayer.$pixelPos && this.$updateGutterLineHighlight(); + }, + initialValue: false + } +}); + exports.VirtualRenderer = VirtualRenderer; });