/* 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 * Ajax.org B.V. * Portions created by the Initial Developer are Copyright (C) 2010 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Fabian Jakobs * Julian Viereck * * 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) { "use strict"; var Range = require("../range").Range; var dom = require("../lib/dom"); var Marker = function(parentEl) { this.element = dom.createElement("div"); this.element.className = "ace_layer ace_marker-layer"; parentEl.appendChild(this.element); }; (function() { this.$padding = 0; this.setPadding = function(padding) { this.$padding = padding; }; this.setSession = function(session) { this.session = session; }; this.setMarkers = function(markers) { this.markers = markers; }; this.update = function(config) { var config = config || this.config; if (!config) return; this.config = config; var html = []; for (var key in this.markers) { var marker = this.markers[key]; if (!marker.range) { marker.update(html, this, this.session, config); continue; } var range = marker.range.clipRows(config.firstRow, config.lastRow); if (range.isEmpty()) continue; range = range.toScreenRange(this.session); if (marker.renderer) { var top = this.$getTop(range.start.row, config); var left = Math.round( this.$padding + range.start.column * config.characterWidth ); marker.renderer(html, range, left, top, config); } else if (range.isMultiLine()) { if (marker.type == "text") { this.drawTextMarker(html, range, marker.clazz, config); } else { this.drawMultiLineMarker( html, range, marker.clazz, config, marker.type ); } } else { this.drawSingleLineMarker( html, range, marker.clazz + " start", config, null, marker.type ); } } this.element = dom.setInnerHtml(this.element, html.join("")); }; this.$getTop = function(row, layerConfig) { return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; }; // Draws a marker, which spans a range of text on multiple lines this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig) { // selection start var row = range.start.row; var lineRange = new Range( row, range.start.column, row, this.session.getScreenLastRowColumn(row) ); this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " start", layerConfig, 1, "text"); // selection end row = range.end.row; lineRange = new Range(row, 0, row, range.end.column); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, "text"); for (row = range.start.row + 1; row < range.end.row; row++) { lineRange.start.row = row; lineRange.end.row = row; lineRange.end.column = this.session.getScreenLastRowColumn(row); this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, "text"); } }; // Draws a multi line marker, where lines span the full width this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, type) { var padding = type === "background" ? 0 : this.$padding; // from selection start to the end of the line var height = config.lineHeight; var top = this.$getTop(range.start.row, config); var left = Math.round(padding + range.start.column * config.characterWidth); stringBuilder.push( "
" ); // from start of the last line to the selection end top = this.$getTop(range.end.row, config); var width = Math.round(range.end.column * config.characterWidth); stringBuilder.push( "
" ); // all the complete lines height = (range.end.row - range.start.row - 1) * config.lineHeight; if (height < 0) return; top = this.$getTop(range.start.row + 1, config); stringBuilder.push( "
" ); }; // Draws a marker which covers part or whole width of a single screen line this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength, type) { var padding = type === "background" ? 0 : this.$padding; var height = layerConfig.lineHeight; if (type === "background") var width = layerConfig.width; else width = Math.round((range.end.column + (extraLength || 0) - range.start.column) * layerConfig.characterWidth); var top = this.$getTop(range.start.row, layerConfig); var left = Math.round( padding + range.start.column * layerConfig.characterWidth ); stringBuilder.push( "
" ); }; }).call(Marker.prototype); exports.Marker = Marker; });