diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 61fd316e..47b38d7a 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -1,10 +1,42 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + define(function(require, exports, module) { "use strict"; -var dom = require("ace/lib/dom"); -var layout = require("./layout"); -var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var EditSession = require("ace/edit_session").EditSession; +var Renderer = require("ace/virtual_renderer").VirtualRenderer; +var UndoManager = require("ace/undomanager").UndoManager; + +var dom = require("ace/lib/dom"); +var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var TextMode = require("ace/mode/text").Mode; var mode = new TextMode(); @@ -13,7 +45,7 @@ mode.$tokenizer = { } }; -var Autocompleter = function() { +var Autocomplete = function() { this.keyboardHandler = new HashHandler(); this.keyboardHandler.bindKeys(this.commands); @@ -21,10 +53,12 @@ var Autocompleter = function() { this.$changeListener = this.changeListener.bind(this); }; -(function(){ + +(function() { + this.$init = function(e) { var el = dom.createElement("div"); - var popup = new layout.singleLineEditor(el); + var popup = new this.$singleLineEditor(el); document.body.appendChild(el); el.style.width="200px" el.style.zIndex="20000" @@ -128,15 +162,16 @@ var Autocompleter = function() { if (this.editor) this.detach(); this.editor = editor; - if (editor.autocompleter != this) { - if (editor.autocompleter) - editor.autocompleter.detach(); - editor.autocompleter = this; + if (editor.Autocomplete != this) { + if (editor.Autocomplete) + editor.Autocomplete.detach(); + editor.Autocomplete = this; } editor.keyBinding.addKeyboardHandler(this.keyboardHandler) editor.on("changeSelection", this.$changeListener) editor.on("blur", this.$blurListener) }; + this.detach = function() { this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); this.editor.removeEventListener("changeSelection", this.changeListener); @@ -155,14 +190,20 @@ var Autocompleter = function() { this.goTo = function(where) { var row = this.popup.getRow(); - var max = this.popup.session.getLength() - 1 + var max = this.popup.session.getLength() - 1; + + var choices = this.popup.container.getElementsByClassName("ace_text-layer")[0].childNodes; + dom.removeCssClass(choices[row], "autocomplete_selected"); + switch(where) { case "up": row = row < 0 ? max : row-1; break; case "down": row = row >= max ? -1 : row+1; break; case "start": row = 0; break; case "end": row = max; break } - this.popup.setRow(row) + + dom.addCssClass(choices[row], "autocomplete_selected"); + this.popup.setRow(row); }; this.insertMatch = function(row) { @@ -176,15 +217,15 @@ var Autocompleter = function() { }; this.commands = { - "up": function(editor) { editor.autocompleter.goTo("up"); }, - "down": function(editor) { editor.autocompleter.goTo("down"); }, - "ctrl-up": function(editor) { editor.autocompleter.goTo("start"); }, - "ctrl-down": function(editor) { editor.autocompleter.goTo("end"); }, + "up": function(editor) { editor.Autocomplete.goTo("up"); }, + "down": function(editor) { editor.Autocomplete.goTo("down"); }, + "ctrl-up": function(editor) { editor.Autocomplete.goTo("start"); }, + "ctrl-down": function(editor) { editor.Autocomplete.goTo("end"); }, - "esc": function(editor) { editor.autocompleter.detach(); }, - "Return": function(editor) { editor.autocompleter.insertMatch(); }, - "Shift-Return": function(editor) { editor.autocompleter.insertMatch(true); }, - "Tab": function(editor) {}, + "esc": function(editor) { editor.Autocomplete.detach(); }, + "Return": function(editor) { editor.Autocomplete.insertMatch(); }, + "Shift-Return": function(editor) { editor.Autocomplete.insertMatch(true); }, + "Tab": function(editor) { editor.Autocomplete.insertMatch(); }, "Shift-Tab": function(editor) {}, }; @@ -202,23 +243,113 @@ var Autocompleter = function() { }; this.gatherCompletions = function() { - return ["asdaf", "foo", "bar", "baz"] - } + return ["asdaf", "foo", "bar", "baz"]; + }; - -}).call(Autocompleter.prototype); + this.$singleLineEditor = function(el) { + var renderer = new Renderer(el); + el.style.overflow = "hidden"; + renderer.scrollBar.element.style.top = "0"; + renderer.scrollBar.element.style.display = "none"; + renderer.scrollBar.orginalWidth = renderer.scrollBar.width; + renderer.scrollBar.width = 0; + renderer.content.style.height = "auto"; -Autocompleter.startCommand = { + renderer.screenToTextCoordinates = function(x, y) { + var pos = this.pixelToScreenCoordinates(x, y); + return this.session.screenToDocumentPosition( + Math.min(this.session.getScreenLength() - 1, Math.max(pos.row, 0)), + Math.max(pos.column, 0) + ); + }; + + renderer.maxLines = 4; + renderer.$computeLayerConfigWithScroll = renderer.$computeLayerConfig; + renderer.$computeLayerConfig = function() { + var config = this.layerConfig; + var height = this.session.getScreenLength() * this.lineHeight; + if (config.height != height) { + var vScroll = height > this.maxLines * this.lineHeight; + + if (vScroll != this.$vScroll) { + if (vScroll) { + this.scrollBar.element.style.display = ""; + this.scrollBar.width = this.scrollBar.orginalWidth; + this.container.style.height = config.height + "px"; + height = config.height; + this.scrollTop = height - this.maxLines * this.lineHeight; + } else { + this.scrollBar.element.style.display = "none"; + this.scrollBar.width = 0; + } + + this.onResize(); + this.$vScroll = vScroll; + } + + if (this.$vScroll) + return renderer.$computeLayerConfigWithScroll(); + + this.container.style.height = height + "px"; + this.scroller.style.height = height + "px"; + this.content.style.height = height + "px"; + this._emit("resize"); + } + + var longestLine = this.$getLongestLine(); + var firstRow = 0; + var lastRow = this.session.getLength(); + + this.scrollTop = 0; + config.width = longestLine; + config.padding = this.$padding; + config.firstRow = 0; + config.firstRowScreen = 0; + config.lastRow = lastRow; + config.lineHeight = this.lineHeight; + config.characterWidth = this.characterWidth; + config.minHeight = height; + config.maxHeight = height; + config.offset = 0; + config.height = height; + + this.$gutterLayer.element.style.marginTop = 0 + "px"; + this.content.style.marginTop = 0 + "px"; + this.content.style.width = longestLine + 2 * this.$padding + "px"; + }; + renderer.isScrollableBy=function(){return false}; + + renderer.setStyle("ace_one-line"); + + var Editor = require("ace/editor").Editor; + var editor = new Editor(renderer); + + //var MultiSelect = require("ace/multi_select").MultiSelect; + //new MultiSelect(editor); + editor.session.setUndoManager(new UndoManager()); + + editor.setHighlightActiveLine(false); + editor.setShowPrintMargin(false); + editor.renderer.setShowGutter(false); + editor.renderer.setHighlightGutterLine(false); + + editor.$mouseHandler.$focusWaitTimout = 0; + + return editor; + }; +}).call(Autocomplete.prototype); + +Autocomplete.startCommand = { name: "startAutocomplete", exec: function(editor) { - if (!editor.autocompleter) - editor.autocompleter = new Autocompleter(); - editor.autocompleter.complete(editor); + if (!editor.Autocomplete) + editor.Autocomplete = new Autocomplete(); + editor.Autocomplete.complete(editor); }, bindKey: "Ctrl-Space|Shift-Space|Alt-Space" } -Autocompleter.addTo = function(editor) { - editor.commands.addCommand(Autocompleter.startCommand); +Autocomplete.addTo = function(editor) { + editor.commands.addCommand(Autocomplete.startCommand); } var FilteredList = function(array, mutateData) { @@ -233,8 +364,7 @@ var FilteredList = function(array, mutateData) { }).call(FilteredList.prototype); -exports.Autocompleter = Autocompleter; +exports.Autocomplete = Autocomplete; exports.FilteredList = FilteredList; -}); - +}); \ No newline at end of file