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.