From 0ddbfa66ef3a038aeb21a8187a01111e09ebf653 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 21:24:28 +0200 Subject: [PATCH 1/9] First pass of split implementation --- demo/demo.js | 11 +++- lib/ace/split.js | 142 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 lib/ace/split.js diff --git a/demo/demo.js b/demo/demo.js index 7b0646db..0b4b144c 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -154,7 +154,13 @@ exports.launch = function(env) { var container = document.getElementById("editor"); var cockpitInput = document.getElementById("cockpitInput"); - env.editor = new Editor(new Renderer(container, theme)); + + // Splitting. + var Split = require("ace/split").Split; + var split = new Split(container, theme, 1); + env.editor = split.getEditor(0); + env.split = split; +// env.editor = new Editor(new Renderer(container, theme)); window.env = env; window.ace = env.editor; @@ -343,7 +349,8 @@ exports.launch = function(env) { container.style.width = width + "px"; cockpitInput.style.width = width + "px"; container.style.height = (document.documentElement.clientHeight - 22) + "px"; - env.editor.resize(); + env.split.resize(); +// env.editor.resize(); }; window.onresize = onResize; diff --git a/lib/ace/split.js b/lib/ace/split.js new file mode 100644 index 00000000..b5aea2b3 --- /dev/null +++ b/lib/ace/split.js @@ -0,0 +1,142 @@ +/* vim:ts=4:sts=4:sw=4: + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Julian Viereck + * + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var EventEmitter = require("pilot/event_emitter").EventEmitter; + +var Editor = require("ace/editor").Editor; +var Renderer = require("ace/virtual_renderer").VirtualRenderer; +var EditSession = require("ace/edit_session").EditSession; + +var Split = function(container, theme, splits) { + this.$container = container; + this.$theme = theme; + this.$splits = 0; + this.$editorCSS = ""; + this.$cEditor = null; + this.$editors = []; + + this.setSplits(splits || 1); + + this.on("focus", function(editor) { + this.$cEditor = editor; + }.bind(this)); +}; + +(function(){ + + oop.implement(this, EventEmitter); + + this.$createEditor = function() { + var dom = document.createElement("div"); + dom.className = this.$editorCSS; + dom.style = "position: absolute; top:0px; bottom:0px"; + this.$container.appendChild(dom); + + var session = new EditSession(""); + var editor = new Editor(new Renderer(dom, this.$theme)); + + editor.on("focus", function() { + this._emit("focus", editor); + }.bind(this)); + + this.$editors.push(editor); + return editor; + } + + this.setSplits = function(splits) { + var editor; + if (splits < 1) { + throw "The number of splits have to be > 0!"; + } + + if (splits == this.$splits) { + return; + } else if (splits > this.$splits) { + while (this.$splits < splits) { + this.$createEditor(); + this.$splits ++; + } + } else { + while (this.$splits > splits) { + editor = this.$editors[this.$splits - 1]; + this.$container.removeChild(editor.container); + this.$editors.pop(); + this.$splits --; + } + } + this.resize(); + } + + this.getEditor = function(idx) { + return this.$editors[idx]; + } + + this.setTheme = function(theme) { + this.$editors.forEach(function(editor) { + editor.setTheme(theme); + }); + } + + this.setKeyboardHandler = function(keybinding) { + this.$editors.forEach(function(editor) { + editor.setKeyboardHandler(keybinding); + }); + } + + this.resize = function() { + var width = this.$container.clientWidth; + var height = this.$container.clientHeight; + var editor; + var editorWidth = width / this.$splits; + for (var i = 0; i < this.$splits; i++) { + editor = this.$editors[i]; + editor.container.style.width = editorWidth + "px"; + editor.container.style.left = i * editorWidth + "px"; + editor.container.style.height = height + "px"; + editor.resize(); + } + } + +}).call(Split.prototype); + + +exports.Split = Split; +}); From c38ddf3245c19f9a3a482d0935fecaeb8bde20f8 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 22:51:16 +0200 Subject: [PATCH 2/9] More work on Split. Update the demo UI on changes --- demo/demo.js | 58 ++++++++++++++-- index.html | 18 ++--- lib/ace/edit_session/fold_line.js | 2 +- lib/ace/edit_session/folding.js | 29 ++++++++ lib/ace/editor.js | 4 ++ lib/ace/split.js | 112 +++++++++++++++++++++++++++++- lib/ace/virtual_renderer.js | 5 ++ 7 files changed, 210 insertions(+), 18 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 0b4b144c..7c07eaad 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -152,6 +152,11 @@ exports.launch = function(env) { docs.textile.setMode(new TextileMode()); docs.textile.setUndoManager(new UndoManager()); + // Add a "name" property to all docs + for (doc in docs) { + docs[doc].name = doc; + } + var container = document.getElementById("editor"); var cockpitInput = document.getElementById("cockpitInput"); @@ -159,8 +164,11 @@ exports.launch = function(env) { var Split = require("ace/split").Split; var split = new Split(container, theme, 1); env.editor = split.getEditor(0); + split.on("focus", function(editor) { + env.editor = editor; + updateUIEditorOptions(); + }); env.split = split; -// env.editor = new Editor(new Renderer(container, theme)); window.env = env; window.ace = env.editor; @@ -187,14 +195,36 @@ exports.launch = function(env) { return modes[modeEl.value]; } + var docEl = document.getElementById("doc"); var modeEl = document.getElementById("mode"); var wrapModeEl = document.getElementById("soft_wrap"); + var themeEl = document.getElementById("theme"); + var selectStyleEl = document.getElementById("select_style"); + var highlightActiveEl = document.getElementById("highlight_active"); + var showHiddenEl = document.getElementById("show_hidden"); + var showGutterEl = document.getElementById("show_gutter"); + var showPrintMarginEl = document.getElementById("show_print_margin"); + var highlightSelectedWordE = document.getElementById("highlight_selected_word"); + var showHScrollEl = document.getElementById("show_hscroll"); + var softTabEl = document.getElementById("soft_tab"); bindDropdown("doc", function(value) { var doc = docs[value]; - env.editor.setSession(doc); + var session = env.split.setSession(doc); + session.name = doc.name; - var mode = doc.getMode(); + updateUIEditorOptions(); + + env.editor.focus(); + }); + + function updateUIEditorOptions() { + var editor = env.editor; + var session = editor.session; + + docEl.value = session.name; + + var mode = session.getMode(); if (mode instanceof JavaScriptMode) { modeEl.value = "javascript"; } @@ -244,13 +274,22 @@ exports.launch = function(env) { modeEl.value = "text"; } - if (!doc.getUseWrapMode()) { + if (!session.getUseWrapMode()) { wrapModeEl.value = "off"; } else { - wrapModeEl.value = doc.getWrapLimitRange().min || "free"; + wrapModeEl.value = session.getWrapLimitRange().min || "free"; } - env.editor.focus(); - }); + + selectStyleEl.checked = editor.getSelectionStyle() == "line" + themeEl.value = editor.getTheme(); + highlightActiveEl.checked = editor.getHighlightActiveLine(); + showHiddenEl.checked = editor.getShowInvisibles(); + showGutterEl.checked = editor.renderer.getShowGutter(); + showPrintMarginEl.checked = editor.renderer.getShowPrintMargin(); + highlightSelectedWordE.checked = editor.getHighlightSelectedWord(); + showHScrollEl.checked = editor.renderer.getHScrollBarAlwaysVisible(); + softTabEl.checked = session.getUseSoftTabs(); + } bindDropdown("mode", function(value) { env.editor.getSession().setMode(modes[value] || modes.text); @@ -538,6 +577,11 @@ exports.launch = function(env) { session.addFold(placeHolder, range); } } + + env.split.setSplits(2); + sp = env.split; + session = sp.setSession(sp.getEditor(0).session, 1); + session.name = sp.getEditor(0).session.name; }; }); diff --git a/index.html b/index.html index 13068165..03373d09 100644 --- a/index.html +++ b/index.html @@ -101,7 +101,7 @@ - + @@ -115,21 +115,21 @@ - + - + - + @@ -153,28 +153,28 @@ - + - + - + - + diff --git a/lib/ace/edit_session/fold_line.js b/lib/ace/edit_session/fold_line.js index 51024142..7e017a8c 100644 --- a/lib/ace/edit_session/fold_line.js +++ b/lib/ace/edit_session/fold_line.js @@ -58,7 +58,7 @@ function FoldLine(foldData, folds) { this.end = this.range.end; this.folds.forEach(function(fold) { - fold.foldLine = this; + fold.setFoldLine(this); }, this); } diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index d03de3f6..904e0fb5 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -59,6 +59,22 @@ Fold.prototype.toString = function() { return '"' + this.placeholder + '" ' + this.range.toString(); } +Fold.prototype.setFoldLine = function(foldLine) { + this.foldLine = foldLine; + this.subFolds.forEach(function(fold) { + fold.setFoldLine(foldLine); + }); +} + +Fold.prototype.clone = function() { + var range = this.range.clone(); + var fold = new Fold(range, this.placeholder); + this.subFolds.forEach(function(subFold) { + fold.subFolds.push(subFold.clone()); + }); + return fold; +} + function Folding() { /** * Looks up a fold at a given row/column. Possible values for side: @@ -526,6 +542,19 @@ function Folding() { foldLine, row, endColumn, startRow, startColumn); } }; + + this.$cloneFoldData = function() { + var foldData = this.$foldData; + var fd = []; + fd = this.$foldData.map(function(foldLine) { + var folds = foldLine.folds.map(function(fold) { + return fold.clone(); + }); + return new FoldLine(fd, folds); + }); + + return fd; + }; } exports.Folding = Folding; diff --git a/lib/ace/editor.js b/lib/ace/editor.js index ef9b0e8a..1be117ab 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -217,6 +217,10 @@ var Editor =function(renderer, session) { this.renderer.setTheme(theme); }; + this.getTheme = function() { + this.renderer.getTheme(); + } + this.setStyle = function(style) { this.renderer.setStyle(style) }; diff --git a/lib/ace/split.js b/lib/ace/split.js index b5aea2b3..fd54bb18 100644 --- a/lib/ace/split.js +++ b/lib/ace/split.js @@ -39,6 +39,7 @@ define(function(require, exports, module) { var oop = require("pilot/oop"); +var lang = require("pilot/lang"); var EventEmitter = require("pilot/event_emitter").EventEmitter; var Editor = require("ace/editor").Editor; @@ -50,10 +51,10 @@ var Split = function(container, theme, splits) { this.$theme = theme; this.$splits = 0; this.$editorCSS = ""; - this.$cEditor = null; this.$editors = []; this.setSplits(splits || 1); + this.$cEditor = this.$editors[0]; this.on("focus", function(editor) { this.$cEditor = editor; @@ -109,6 +110,18 @@ var Split = function(container, theme, splits) { return this.$editors[idx]; } + this.getCurrentEditor = function() { + return this.$cEditor; + } + + this.focus = function() { + this.$cEditor.focus(); + } + + this.blur = function() { + this.$cEditor.blur(); + } + this.setTheme = function(theme) { this.$editors.forEach(function(editor) { editor.setTheme(theme); @@ -121,6 +134,63 @@ var Split = function(container, theme, splits) { }); } + this.forEach = function(callback, scope) { + this.$ditors.forEach(callback, scope); + } + + this.$cloneSession = function(session) { + var s = new EditSession(session.getDocument(), session.getMode()); + + var undoManager = session.getUndoManager(); + if (undoManager) { + var undoManagerProxy = new UndoManagerProxy(undoManager, s); + s.setUndoManager(undoManagerProxy); + } + + // Overwrite the default $informUndoManager function such that new delas + // aren't added to the undo manager from the new and the old session. + s.$informUndoManager = lang.deferredCall(function() { s.$deltas = []; }); + + // Copy over 'settings' from the session. + s.setTabSize(session.getTabSize()); + s.setUseSoftTabs(session.getUseSoftTabs()); + s.setOverwrite(session.getOverwrite()); + s.setBreakpoints(session.getBreakpoints()); + s.setUseWrapMode(session.getUseWrapMode()); + s.setUseWorker(session.getUseWorker()); + s.setWrapLimitRange(session.$wrapLimitRange.min, + session.$wrapLimitRange.max); + s.$foldData = session.$cloneFoldData(); + + return s; + } + + this.setSession = function(session, idx) { + var editor + if (idx == null) { + editor = this.$cEditor; + } else { + editor = this.$editors[idx]; + } + + // Check if the session is used already by any of the editors in the + // split. If it is, we have to clone the session as two editors using + // the same session can cause terrible side effects (e.g. UndoQueue goes + // wrong). This also gives the user of Split the possibility to treat + // each session on each split editor different. + var isUsed = this.$editors.some(function(editor) { + return editor.session === session; + }); + + if (isUsed) { + session = this.$cloneSession(session); + } + editor.setSession(session); + + // Return the session set on the editor. This might be a cloned one. + return session; + } + this.resize = function() { var width = this.$container.clientWidth; var height = this.$container.clientHeight; @@ -137,6 +207,46 @@ var Split = function(container, theme, splits) { }).call(Split.prototype); +function UndoManagerProxy(undoManager, session) { + this.$u = undoManager; + this.$doc = session; +} + +(function() { + this.execute = function(options) { + this.$u.execute(options); + } + + this.undo = function() { + var u = this.$u; + var deltas = u.$undoStack.pop(); + if (deltas) { + this.$doc.undoChanges(deltas); + u.$redoStack.push(deltas); + } + } + + this.redo = function() { + var u = this.$u; + var deltas = u.$redoStack.pop(); + if (deltas) { + this.$doc.redoChanges(deltas); + u.$undoStack.push(deltas); + } + } + + this.reset = function() { + this.$u.reset(); + } + + this.hasUndo = function() { + return this.$u.hasUndo(); + } + + this.hasRedo = function() { + return this.$u.hasRedo(); + } +}).call(UndoManagerProxy.prototype); exports.Split = Split; }); diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 913158aa..3001d0ce 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -750,6 +750,7 @@ var VirtualRenderer = function(container, theme) { this.setTheme = function(theme) { var _self = this; + this.$themeValue = theme; if (!theme || typeof theme == "string") { theme = theme || "ace/theme/textmate"; require([theme], function(theme) { @@ -777,6 +778,10 @@ var VirtualRenderer = function(container, theme) { } }; + this.getTheme = function() { + return this.$themeValue; + } + // Methods allows to add / remove CSS classnames to the editor element. // This feature can be used by plug-ins to provide a visual indication of // a certain mode that editor is in. From 55328f36908e825b5201dcccc225b9ce76e36614 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 23:08:26 +0200 Subject: [PATCH 3/9] Add oriantation to Split and demo option --- demo/demo.js | 28 ++++++++++++++++++++++----- index.html | 11 +++++++++++ lib/ace/split.js | 49 +++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 7c07eaad..d3a68480 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -365,6 +365,29 @@ exports.launch = function(env) { env.editor.getSession().setUseSoftTabs(checked); }); + var secondSplitSession = null; + bindDropdown("split", function(value) { + var sp = env.split; + if (value == "none") { + sp.setSplits(1); + } else { + var newEditor = (sp.getSplits() == 1); + if (value == "below") { + sp.setOriantation(sp.BELOW); + } else { + sp.setOriantation(sp.BESIDE); + } + sp.setSplits(2); + + if (newEditor) { + var session = secondSplitSession || sp.getEditor(0).session; + var newSession = sp.setSession(session, 1); + newSession.name = session.name; + secondSplitSession = newSession; + } + } + }); + function bindCheckbox(id, callback) { var el = document.getElementById(id); var onCheck = function() { @@ -577,11 +600,6 @@ exports.launch = function(env) { session.addFold(placeHolder, range); } } - - env.split.setSplits(2); - sp = env.split; - session = sp.setSession(sp.getEditor(0).session, 1); - session.name = sp.getEditor(0).session.name; }; }); diff --git a/index.html b/index.html index 03373d09..c381fee9 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,17 @@ + + +
+ + + +
diff --git a/lib/ace/split.js b/lib/ace/split.js index fd54bb18..57054c0f 100644 --- a/lib/ace/split.js +++ b/lib/ace/split.js @@ -47,15 +47,20 @@ var Renderer = require("ace/virtual_renderer").VirtualRenderer; var EditSession = require("ace/edit_session").EditSession; var Split = function(container, theme, splits) { + this.BELOW = 1; + this.BESIDE = 0; + this.$container = container; this.$theme = theme; this.$splits = 0; this.$editorCSS = ""; this.$editors = []; + this.$oriantation = this.BESIDE; this.setSplits(splits || 1); this.$cEditor = this.$editors[0]; + this.on("focus", function(editor) { this.$cEditor = editor; }.bind(this)); @@ -106,6 +111,10 @@ var Split = function(container, theme, splits) { this.resize(); } + this.getSplits = function() { + return this.$splits; + } + this.getEditor = function(idx) { return this.$editors[idx]; } @@ -191,17 +200,43 @@ var Split = function(container, theme, splits) { return session; } + this.getOriantation = function() { + return this.$oriantation; + } + + this.setOriantation = function(oriantation) { + if (this.$oriantation == oriantation) { + return; + } + this.$oriantation = oriantation; + this.resize(); + } + this.resize = function() { var width = this.$container.clientWidth; var height = this.$container.clientHeight; var editor; - var editorWidth = width / this.$splits; - for (var i = 0; i < this.$splits; i++) { - editor = this.$editors[i]; - editor.container.style.width = editorWidth + "px"; - editor.container.style.left = i * editorWidth + "px"; - editor.container.style.height = height + "px"; - editor.resize(); + + if (this.$oriantation == this.BESIDE) { + var editorWidth = width / this.$splits; + for (var i = 0; i < this.$splits; i++) { + editor = this.$editors[i]; + editor.container.style.width = editorWidth + "px"; + editor.container.style.top = "0px"; + editor.container.style.left = i * editorWidth + "px"; + editor.container.style.height = height + "px"; + editor.resize(); + } + } else { + var editorHeight = height / this.$splits; + for (var i = 0; i < this.$splits; i++) { + editor = this.$editors[i]; + editor.container.style.width = width + "px"; + editor.container.style.top = i * editorHeight + "px" + editor.container.style.left = "0px"; + editor.container.style.height = editorHeight + "px"; + editor.resize(); + } } } From 87003ac4edcdd6060a0ac21273af3f6319c551e9 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 23:30:09 +0200 Subject: [PATCH 4/9] Reuse former session of second split. Add destroy function that stops some timeouts. --- demo/demo.js | 6 ++++-- lib/ace/editor.js | 4 ++++ lib/ace/layer/cursor.js | 8 ++++++-- lib/ace/layer/text.js | 6 +++++- lib/ace/split.js | 1 + lib/ace/virtual_renderer.js | 5 +++++ 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index d3a68480..4a59a8f7 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -369,7 +369,10 @@ exports.launch = function(env) { bindDropdown("split", function(value) { var sp = env.split; if (value == "none") { - sp.setSplits(1); + if (sp.getSplits() == 2) { + secondSplitSession = sp.getEditor(1).session; + sp.setSplits(1); + } } else { var newEditor = (sp.getSplits() == 1); if (value == "below") { @@ -383,7 +386,6 @@ exports.launch = function(env) { var session = secondSplitSession || sp.getEditor(0).session; var newSession = sp.setSession(session, 1); newSession.name = session.name; - secondSplitSession = newSession; } } }); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 1be117ab..f03e95e3 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -1123,6 +1123,10 @@ var Editor =function(renderer, session) { this.session.getUndoManager().redo(); }; + this.destroy = function() { + this.renderer.destroy(); + } + }).call(Editor.prototype); diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index a1cd4698..224b638f 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -123,16 +123,20 @@ var Cursor = function(parentEl) { if (this.isVisible) { this.element.appendChild(this.cursor); } - + if (this.session.getOverwrite()) { dom.addCssClass(this.cursor, "ace_overwrite"); } else { dom.removeCssClass(this.cursor, "ace_overwrite"); } - + this.restartTimer(); }; + this.destroy = function() { + clearInterval(this.blinkId); + } + }).call(Cursor.prototype); exports.Cursor = Cursor; diff --git a/lib/ace/layer/text.js b/lib/ace/layer/text.js index 243e2371..88a4e1bf 100644 --- a/lib/ace/layer/text.js +++ b/lib/ace/layer/text.js @@ -82,7 +82,7 @@ var Text = function(parentEl) { this.$pollSizeChanges = function() { var self = this; - setInterval(function() { + this.$pollSizeChangesTimer = setInterval(function() { self.checkForSizeChanges(); }, 500); }; @@ -517,6 +517,10 @@ var Text = function(parentEl) { this.$renderLineCore(stringBuilder, row, renderTokens, splits); }; + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + }; + }).call(Text.prototype); exports.Text = Text; diff --git a/lib/ace/split.js b/lib/ace/split.js index 57054c0f..fcbe2a14 100644 --- a/lib/ace/split.js +++ b/lib/ace/split.js @@ -103,6 +103,7 @@ var Split = function(container, theme, splits) { } else { while (this.$splits > splits) { editor = this.$editors[this.$splits - 1]; + editor.destroy(); this.$container.removeChild(editor.container); this.$editors.pop(); this.$splits --; diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js index 3001d0ce..a9687660 100644 --- a/lib/ace/virtual_renderer.js +++ b/lib/ace/virtual_renderer.js @@ -794,6 +794,11 @@ var VirtualRenderer = function(container, theme) { dom.removeCssClass(this.container, style) }; + this.destroy = function() { + this.$textLayer.destroy(); + this.$cursorLayer.destroy(); + } + }).call(VirtualRenderer.prototype); exports.VirtualRenderer = VirtualRenderer; From 4f06e21070f584ef56b40c6f195041489fe89f1e Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 23:37:27 +0200 Subject: [PATCH 5/9] Reuse the editor instance in Split. Don't like that, but as the Editor is not destroyed completly, this is the base thing to do at the moment in case of memoery usage --- demo/demo.js | 8 ++------ lib/ace/split.js | 7 +++++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 4a59a8f7..d1bac476 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -365,14 +365,10 @@ exports.launch = function(env) { env.editor.getSession().setUseSoftTabs(checked); }); - var secondSplitSession = null; bindDropdown("split", function(value) { var sp = env.split; if (value == "none") { - if (sp.getSplits() == 2) { - secondSplitSession = sp.getEditor(1).session; - sp.setSplits(1); - } + sp.setSplits(1); } else { var newEditor = (sp.getSplits() == 1); if (value == "below") { @@ -383,7 +379,7 @@ exports.launch = function(env) { sp.setSplits(2); if (newEditor) { - var session = secondSplitSession || sp.getEditor(0).session; + var session = sp.getEditor(0).session; var newSession = sp.setSession(session, 1); newSession.name = session.name; } diff --git a/lib/ace/split.js b/lib/ace/split.js index fcbe2a14..07fa0000 100644 --- a/lib/ace/split.js +++ b/lib/ace/split.js @@ -96,6 +96,11 @@ var Split = function(container, theme, splits) { if (splits == this.$splits) { return; } else if (splits > this.$splits) { + while (this.$splits < this.$editors.length && this.$splits < splits) { + var editor = this.$editors[this.$splits]; + this.$container.appendChild(editor.container); + this.$splits ++; + } while (this.$splits < splits) { this.$createEditor(); this.$splits ++; @@ -103,9 +108,7 @@ var Split = function(container, theme, splits) { } else { while (this.$splits > splits) { editor = this.$editors[this.$splits - 1]; - editor.destroy(); this.$container.removeChild(editor.container); - this.$editors.pop(); this.$splits --; } } From 3f78f87f6eb581789df9644c8ea57e382469a0aa Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 23:43:53 +0200 Subject: [PATCH 6/9] Add missing return to Editor.getTheme(). --- lib/ace/editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index f03e95e3..0202d898 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -218,7 +218,7 @@ var Editor =function(renderer, session) { }; this.getTheme = function() { - this.renderer.getTheme(); + return this.renderer.getTheme(); } this.setStyle = function(style) { From cb6a93a8cef70e3dd46b7cc4f03231f555e54084 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Fri, 20 May 2011 23:47:51 +0200 Subject: [PATCH 7/9] Add storing second session back again --- demo/demo.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/demo/demo.js b/demo/demo.js index d1bac476..75ea91d7 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -365,9 +365,13 @@ exports.launch = function(env) { env.editor.getSession().setUseSoftTabs(checked); }); + var secondSession = null; bindDropdown("split", function(value) { var sp = env.split; if (value == "none") { + if (sp.getSplits() == 2) { + secondSession = sp.getEditor(1).session; + } sp.setSplits(1); } else { var newEditor = (sp.getSplits() == 1); @@ -379,7 +383,7 @@ exports.launch = function(env) { sp.setSplits(2); if (newEditor) { - var session = sp.getEditor(0).session; + var session = secondSession || sp.getEditor(0).session; var newSession = sp.setSession(session, 1); newSession.name = session.name; } From ffeda1ae05ea36367a6fd9dd893b6b5c5314c733 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sat, 21 May 2011 00:06:10 +0200 Subject: [PATCH 8/9] Add setFontSize on Split --- demo/demo.js | 2 +- lib/ace/split.js | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 75ea91d7..b331d642 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -304,7 +304,7 @@ exports.launch = function(env) { }); bindDropdown("fontsize", function(value) { - document.getElementById("editor").style.fontSize = value; + env.split.setFontSize(value); }); bindDropdown("soft_wrap", function(value) { diff --git a/lib/ace/split.js b/lib/ace/split.js index 07fa0000..b1cd2961 100644 --- a/lib/ace/split.js +++ b/lib/ace/split.js @@ -75,7 +75,6 @@ var Split = function(container, theme, splits) { dom.className = this.$editorCSS; dom.style = "position: absolute; top:0px; bottom:0px"; this.$container.appendChild(dom); - var session = new EditSession(""); var editor = new Editor(new Renderer(dom, this.$theme)); @@ -84,6 +83,7 @@ var Split = function(container, theme, splits) { }.bind(this)); this.$editors.push(editor); + editor.container.style.fontSize = this.$fontSize; return editor; } @@ -99,6 +99,7 @@ var Split = function(container, theme, splits) { while (this.$splits < this.$editors.length && this.$splits < splits) { var editor = this.$editors[this.$splits]; this.$container.appendChild(editor.container); + editor.container.style.fontSize = this.$fontSize; this.$splits ++; } while (this.$splits < splits) { @@ -148,7 +149,14 @@ var Split = function(container, theme, splits) { } this.forEach = function(callback, scope) { - this.$ditors.forEach(callback, scope); + this.$editors.forEach(callback, scope); + } + + this.setFontSize = function(size) { + this.$fontSize = size; + this.forEach(function(editor) { + editor.container.style.fontSize = size; + }); } this.$cloneSession = function(session) { From f332e2b90094219ec20e114bc60a19757503cfd1 Mon Sep 17 00:00:00 2001 From: Julian Viereck Date: Sat, 21 May 2011 20:04:53 +0200 Subject: [PATCH 9/9] Fix handling of undo/redo stack in splits do the right thing. --- lib/ace/edit_session.js | 14 ++++++++++---- lib/ace/split.js | 16 ++++++---------- lib/ace/undomanager.js | 14 ++++++++++---- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 6afa7107..92ffc5b4 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -694,7 +694,7 @@ var EditSession = function(text, mode) { return this.doc.remove(range); }; - this.undoChanges = function(deltas) { + this.undoChanges = function(deltas, dontSelect) { if (!deltas.length) return; @@ -713,10 +713,13 @@ var EditSession = function(text, mode) { } } this.$fromUndo = false; - lastUndoRange && this.selection.setSelectionRange(lastUndoRange); + lastUndoRange && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; }, - this.redoChanges = function(deltas) { + this.redoChanges = function(deltas, dontSelect) { if (!deltas.length) return; @@ -731,7 +734,10 @@ var EditSession = function(text, mode) { } } this.$fromUndo = false; - lastUndoRange && this.selection.setSelectionRange(lastUndoRange); + lastUndoRange && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; }, this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { diff --git a/lib/ace/split.js b/lib/ace/split.js index b1cd2961..e6c671ca 100644 --- a/lib/ace/split.js +++ b/lib/ace/split.js @@ -265,20 +265,16 @@ function UndoManagerProxy(undoManager, session) { } this.undo = function() { - var u = this.$u; - var deltas = u.$undoStack.pop(); - if (deltas) { - this.$doc.undoChanges(deltas); - u.$redoStack.push(deltas); + var selectionRange = this.$u.undo(true); + if (selectionRange) { + this.$doc.selection.setSelectionRange(selectionRange); } } this.redo = function() { - var u = this.$u; - var deltas = u.$redoStack.pop(); - if (deltas) { - this.$doc.redoChanges(deltas); - u.$undoStack.push(deltas); + var selectionRange = this.$u.redo(true); + if (selectionRange) { + this.$doc.selection.setSelectionRange(selectionRange); } } diff --git a/lib/ace/undomanager.js b/lib/ace/undomanager.js index 66debe14..48c1ee85 100644 --- a/lib/ace/undomanager.js +++ b/lib/ace/undomanager.js @@ -52,20 +52,26 @@ var UndoManager = function() { this.$redoStack = []; }; - this.undo = function() { + this.undo = function(dontSelect) { var deltas = this.$undoStack.pop(); + var undoSelectionRange = null; if (deltas) { - this.$doc.undoChanges(deltas); + undoSelectionRange = + this.$doc.undoChanges(deltas, dontSelect); this.$redoStack.push(deltas); } + return undoSelectionRange; }; - this.redo = function() { + this.redo = function(dontSelect) { var deltas = this.$redoStack.pop(); + var redoSelectionRange = null; if (deltas) { - this.$doc.redoChanges(deltas); + redoSelectionRange = + this.$doc.redoChanges(deltas, dontSelect); this.$undoStack.push(deltas); } + return redoSelectionRange; }; this.reset = function() {