ace/lib/ace/layer/marker.js
2011-01-26 23:51:04 +01:00

191 lines
6.7 KiB
JavaScript

/* ***** 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 <fabian AT ajax DOT org>
* Julian Viereck <julian.viereck@gmail.com>
*
* 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 Range = require("ace/range").Range;
var dom = require("pilot/dom");
var Marker = function(parentEl) {
this.element = document.createElement("div");
this.element.className = "ace_layer ace_marker-layer";
parentEl.appendChild(this.element);
this.markers = {};
this.$markerId = 1;
};
(function() {
this.setSession = function(session) {
this.session = session;
};
this.addMarker = function(range, clazz, type) {
var id = this.$markerId++;
this.markers[id] = {
range : range,
type : type || "line",
clazz : clazz
};
return id;
};
this.removeMarker = function(markerId) {
var marker = this.markers[markerId];
if (marker) {
delete (this.markers[markerId]);
}
};
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];
var range = marker.range.clipRows(config.firstRow, config.lastRow);
if (range.isEmpty()) continue;
range = range.toScreenRange(this.session);
if (range.isMultiLine()) {
if (marker.type == "text") {
this.drawTextMarker(html, range, marker.clazz, config);
} else {
this.drawMultiLineMarker(html, range, marker.clazz, config);
}
}
else {
this.drawSingleLineMarker(html, range, marker.clazz, config);
}
}
this.element = dom.setInnerHtml(this.element, html.join(""));
};
this.$getTop = function(row, layerConfig) {
return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight;
};
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, layerConfig, 1);
// selection end
var row = range.end.row;
var lineRange = new Range(row, 0, row, range.end.column);
this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig);
for (var 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);
}
};
this.drawMultiLineMarker = function(stringBuilder, range, clazz, layerConfig) {
// from selection start to the end of the line
var height = layerConfig.lineHeight;
var width = Math.round(layerConfig.width - (range.start.column * layerConfig.characterWidth));
var top = this.$getTop(range.start.row, layerConfig);
var left = Math.round(range.start.column * layerConfig.characterWidth);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
"left:", left, "px;'></div>"
);
// from start of the last line to the selection end
var top = this.$getTop(range.end.row, layerConfig);
var width = Math.round(range.end.column * layerConfig.characterWidth);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"top:", top, "px;",
"width:", width, "px;'></div>"
);
// all the complete lines
var height = (range.end.row - range.start.row - 1) * layerConfig.lineHeight;
if (height < 0)
return;
var top = this.$getTop(range.start.row + 1, layerConfig);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", layerConfig.width, "px;",
"top:", top, "px;'></div>"
);
};
this.drawSingleLineMarker = function(stringBuilder, range, clazz, layerConfig, extraLength) {
var height = layerConfig.lineHeight;
var 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(range.start.column * layerConfig.characterWidth);
stringBuilder.push(
"<div class='", clazz, "' style='",
"height:", height, "px;",
"width:", width, "px;",
"top:", top, "px;",
"left:", left,"px;'></div>"
);
};
}).call(Marker.prototype);
exports.Marker = Marker;
});