src/OutlineManager.js
define(function OutlineManager(require, exports, module) {
"use strict";
/* beautify preserve:start *//* eslint-disable no-multi-spaces */
var Mustache = brackets.getModule("thirdparty/mustache/mustache");
var Resizer = brackets.getModule("utils/Resizer");
var Promise = require("thirdparty/promise");
var Strings = require("strings");
var prefs = require("src/Preferences");
var SettingsMenu = require("src/SettingsMenu");
var ListTemplate = require("text!templates/outline.html");
/* eslint-enable no-multi-spaces *//* beautify preserve:end */
/** @const {number} Position for sidebar */
var POSITION_SIDEBAR = 0;
/** @const {number} Position for main window. */
var POSITION_TOOLBAR = 1;
/* beautify preserve:start *//* eslint-disable key-spacing */
var outlineProviders = {
JavaScript: require("src/languages/JavaScript"),
Haxe: require("src/languages/Haxe"),
CoffeeScript: require("src/languages/CoffeeScript"),
CSS: require("src/languages/CSS"),
Stylus: require("src/languages/Stylus"),
PHP: require("src/languages/PHP"),
Ruby: require("src/languages/Ruby"),
Python: require("src/languages/Python"),
Markdown: require("src/languages/Markdown"),
XML: require("src/languages/XML"),
Jade: require("src/languages/Jade")
};
/* eslint-enable key-spacing *//* beautify preserve:end */
var listeners = [];
var outlineProvider;
var isVisible = false;
var position = prefs.get("sidebar") ? POSITION_SIDEBAR : POSITION_TOOLBAR;
var settingsMenuAssigned = false;
var $outline = $(Mustache.render(ListTemplate, {
Strings: Strings
}));
$outline.on("click", "#outline-close", function () {
prefs.togglePref("enabled");
});
$outline.on("click", "#outline-move", function () {
prefs.togglePref("sidebar");
});
prefs.onChange("args", function () {
$outline.find("ul").toggleClass("outline-hide-args", !prefs.get("args"));
});
prefs.onChange("indent", function () {
$outline.find("ul").toggleClass("outline-hide-indent", !prefs.get("indent"));
});
prefs.onChange("unnamed", function () {
$outline.find("ul").toggleClass("outline-hide-unnamed", !prefs.get("unnamed"));
});
prefs.onChange("sort", function () {
if (outlineProvider && outlineProvider.compare) {
if (prefs.get("sort")) {
$outline.find(".outline-entry").sort(function (entryA, entryB) {
return outlineProvider.compare($(entryA).data("name"), $(entryB).data("name"));
}).appendTo($outline.find("ul"));
} else {
$outline.find(".outline-entry").sort(function (entryA, entryB) {
return $(entryA).data("index") - $(entryB).data("index");
}).appendTo($outline.find("ul"));
}
}
});
/**
* Handler for a horizontal resize of the outline list.
*/
function resize() {
var toolbarPx = $("#main-toolbar:visible").width() || 0;
$(".content").css("right", ($("#outline").width() || 0) + toolbarPx + "px");
}
/**
* Add a listener to be called when an entry is selected.
* @param {function} callback Listener function.
*/
function onSelect(callback) {
listeners.push(callback);
}
/**
* Set the outline provider.
* Does not update the outline.
* @param {string} outlineProviderName Name of the outline provider.
*/
function setOutlineProvider(outlineProviderName) {
outlineProvider = outlineProviders[outlineProviderName];
}
/**
* Update the outline.
* Get the outline from the set outline provider and update the HTML.
* Sort the entries if sorting is enabled.
* @param {string} text Code to generate outline for.
*/
function updateOutline(text) {
var $ul = $outline.find("ul");
$ul.empty();
var promise;
try {
promise = outlineProvider.getOutlineList(text);
if (!(promise instanceof Promise)) {
promise = Promise.resolve(promise);
}
} catch (error) {
promise = Promise.reject(error);
}
promise.then(function (list) {
list = list.map(function (entry, index) {
var $entry = $(document.createElement("li"));
$entry.addClass("outline-entry " + entry.classes);
$entry.data("index", index);
$entry.data("name", entry.name);
$entry.append(entry.$html);
$entry.click(function () {
listeners.forEach(function (callback) {
callback({
line: entry.line,
ch: entry.ch
});
});
});
return $entry;
});
if (outlineProvider.compare && prefs.get("sort")) {
list.sort(function (entryA, entryB) {
return outlineProvider.compare(entryA.data("name"), entryB.data("name"));
});
}
$ul.append(list);
}).catch(function (error) {
if (error.message === "SyntaxError") {
var $li = $(document.createElement("li"));
$li.addClass("outline-message");
$li.append(Strings.MESSAGE_SYNTAX_ERROR);
$ul.append($li);
}
});
}
/**
* Show the outline if it is not yet visible.
* The position is depending on the preferences.
*/
function showOutline() {
if (!isVisible) {
if (position === POSITION_SIDEBAR) {
$("#sidebar").append($outline);
$outline.addClass("outline-sidebar");
Resizer.makeResizable($outline, "vert", "top", 75);
} else {
var toolbarPx = $("#main-toolbar:visible").width() || 0;
$(".main-view").append($outline);
$outline.css("right", toolbarPx + "px");
$outline.addClass("outline-main quiet-scrollbars");
Resizer.makeResizable($outline, "horz", "left", 150);
$outline.on("panelResizeUpdate.outline-list", resize);
resize();
}
if (!settingsMenuAssigned) {
SettingsMenu.assignToSelector("#outline-settings");
settingsMenuAssigned = true;
}
isVisible = true;
}
}
/**
* Hide the outline.
* Detach the jQuery Element and clean it for re-use.
*/
function hideOutline() {
if (isVisible) {
isVisible = false;
$outline.detach();
$outline.css("display", "");
$outline.css("height", "");
$outline.css("right", "");
$outline.css("width", "");
$outline.removeClass("outline-sidebar outline-main quiet-scrollbars");
$outline.off("panelResizeUpdate.outline-list", resize);
Resizer.removeSizable($outline);
if (position === POSITION_TOOLBAR) {
resize();
}
}
}
/**
* Set the position of the outline.
* Hides and shows the outline again if it was visible.
* @param {number} newPosition Position as number.
*/
function setPosition(newPosition) {
if (isVisible) {
hideOutline();
position = newPosition;
showOutline();
} else {
position = newPosition;
}
}
module.exports = {
onSelect: onSelect,
setOutlineProvider: setOutlineProvider,
setPosition: setPosition,
updateOutline: updateOutline,
showOutline: showOutline,
hideOutline: hideOutline,
POSITION_SIDEBAR: POSITION_SIDEBAR,
POSITION_TOOLBAR: POSITION_TOOLBAR
};
});