kopia lustrzana https://github.com/c9/core
485 wiersze
18 KiB
JavaScript
485 wiersze
18 KiB
JavaScript
define(function(require, exports, module) {
|
|
main.consumes = [
|
|
"Plugin", "c9", "settings", "ui", "menus", "ace",
|
|
"ace.gotoline", "tabManager"
|
|
];
|
|
main.provides = ["ace.status"];
|
|
return main;
|
|
|
|
function main(options, imports, register) {
|
|
var c9 = imports.c9;
|
|
var Plugin = imports.Plugin;
|
|
var settings = imports.settings;
|
|
var ui = imports.ui;
|
|
var tabs = imports.tabManager;
|
|
var menus = imports.menus;
|
|
var gotoline = imports["ace.gotoline"];
|
|
var aceHandle = imports.ace;
|
|
|
|
var skin = require("text!./skin.xml");
|
|
var markup = require("text!./statusbar.xml");
|
|
var menuAml = require("text!./menu.xml");
|
|
|
|
var aceWhitespace = require("ace/ext/whitespace");
|
|
var lang = require("ace/lib/lang");
|
|
|
|
/***** Generic Load *****/
|
|
|
|
// Set up the generic handle
|
|
var handle = new Plugin("Ajax.org", main.consumes);
|
|
var statusbars = {};
|
|
var menuItem, menu, menuTabs;
|
|
|
|
handle.on("load", function() {
|
|
settings.on("read", function(e) {
|
|
settings.setDefaults("user/ace/statusbar", [["show", "true"]]);
|
|
}, handle);
|
|
|
|
menuItem = new ui.item({
|
|
test: "1",
|
|
type: "check",
|
|
checked: "user/ace/statusbar/@show"
|
|
// -> if you're looking for disabled, check the init function :-)
|
|
// the moment that someone clicks this thing well call preinit
|
|
// (its already called if the user has it checked on IDE load)
|
|
});
|
|
|
|
menus.addItemByPath("View/Status Bar", menuItem, 600, handle);
|
|
|
|
aceHandle.on("create", function(e) {
|
|
if (e.editor.type != "ace")
|
|
return;
|
|
|
|
var editor = e.editor;
|
|
var statusbar;
|
|
|
|
editor.once("draw", function() {
|
|
statusbar = new Statusbar(editor);
|
|
}, editor);
|
|
editor.once("unload", function h2() {
|
|
if (statusbar) statusbar.unload();
|
|
}, editor);
|
|
});
|
|
|
|
ui.insertMarkup(null, menuAml, handle);
|
|
|
|
menu = handle.getElement("menu");
|
|
menuTabs = handle.getElement("menuTabs");
|
|
|
|
var currentSession;
|
|
function setCurrentSession(menu) {
|
|
var node = menu.opener;
|
|
while (node && node.localName != "tab")
|
|
node = node.parentNode;
|
|
if (!node) return;
|
|
|
|
var tab = node.cloud9pane.getTab();
|
|
currentSession = tab.document.getSession();
|
|
}
|
|
|
|
function setOption(name, value) {
|
|
if (currentSession) {
|
|
if (currentSession.setOption)
|
|
currentSession.setOption(name, value);
|
|
currentSession.statusBar.update();
|
|
}
|
|
}
|
|
|
|
function getOption(name) {
|
|
return currentSession && currentSession.session.getOption(name);
|
|
}
|
|
|
|
// Checkboxes
|
|
menu.on("afterrender", function(e) {
|
|
var itmSbWrap = window.itmSbWrap;
|
|
var itmSbWrapPM = window.itmSbWrapPM;
|
|
|
|
itmSbWrap.on("click", function() {
|
|
setOption("wrap", itmSbWrap.checked
|
|
? itmSbWrapPM.checked ? "printMargin" : true
|
|
: false);
|
|
});
|
|
itmSbWrapPM.on("click", function() {
|
|
setOption("wrap", itmSbWrapPM.checked
|
|
? "printMargin"
|
|
: itmSbWrap.checked);
|
|
});
|
|
|
|
function update(e) {
|
|
if (!e || e.value) {
|
|
setCurrentSession(menu);
|
|
|
|
var wrap = getOption("wrap");
|
|
itmSbWrap.setAttribute("checked", !ui.isFalse(wrap));
|
|
itmSbWrapPM.setAttribute("checked", wrap == "printMargin");
|
|
}
|
|
}
|
|
|
|
menu.on("prop.visible", update);
|
|
update();
|
|
});
|
|
|
|
// Menu Tab functionality
|
|
var handlers = [
|
|
function() { setOption("useSoftTabs", this.checked); },
|
|
function() {},
|
|
function() { setOption("tabSize", 2); },
|
|
function() { setOption("tabSize", 3); },
|
|
function() { setOption("tabSize", 4); },
|
|
function() { setOption("tabSize", 8); },
|
|
function() {
|
|
if (!currentSession) return;
|
|
aceWhitespace.detectIndentation(currentSession.session);
|
|
currentSession.setOption("guessTabSize", true);
|
|
currentSession.statusBar.update();
|
|
},
|
|
// Tabs to Spaces
|
|
function() {
|
|
if (!currentSession) return;
|
|
aceWhitespace.convertIndentation(currentSession.session, " ");
|
|
currentSession.statusBar.update();
|
|
},
|
|
// Spaces to Tabs
|
|
function() {
|
|
if (!currentSession) return;
|
|
aceWhitespace.convertIndentation(currentSession.session, "\t");
|
|
currentSession.statusBar.update();
|
|
}
|
|
];
|
|
|
|
menuTabs.on("afterrender", function(e) {
|
|
var items = menuTabs.selectNodes("a:item");
|
|
items.forEach(function(node, idx) {
|
|
node.on("click", handlers[idx]);
|
|
});
|
|
|
|
var itmTabSize = window.itmTabSize;
|
|
itmTabSize.on("afterchange", function() {
|
|
setOption("tabSize", this.value);
|
|
update();
|
|
});
|
|
|
|
var lut = [0, 0, 2, 3, 4, 0, 0, 0, 5];
|
|
|
|
function update(e) {
|
|
if (e && !e.value)
|
|
return;
|
|
|
|
setCurrentSession(menuTabs);
|
|
|
|
items[0].setAttribute("checked", getOption("useSoftTabs"));
|
|
|
|
var tabSize = getOption("tabSize") || 1;
|
|
items.forEach(function(node, idx) {
|
|
node.setAttribute("selected", "false");
|
|
});
|
|
if (lut[tabSize])
|
|
items[lut[tabSize]].setAttribute("selected", "true");
|
|
itmTabSize.setAttribute("value", getOption("tabSize"));
|
|
}
|
|
|
|
menuTabs.on("prop.visible", update);
|
|
update();
|
|
});
|
|
});
|
|
|
|
handle.on("unload", function() {
|
|
drawn = false;
|
|
|
|
Object.keys(statusbars).forEach(function(name) {
|
|
statusbars[name].unload();
|
|
});
|
|
|
|
statusbars = {};
|
|
menuItem = null;
|
|
menu = null;
|
|
menuTabs = null;
|
|
});
|
|
|
|
/***** Methods *****/
|
|
|
|
var drawn = false;
|
|
function draw() {
|
|
if (drawn) return;
|
|
drawn = true;
|
|
|
|
// Import Skin
|
|
ui.insertSkin({
|
|
name: "c9statusbar",
|
|
data: skin,
|
|
"media-path": options.staticPrefix + "/images/",
|
|
"icon-path": options.staticPrefix + "/icons/"
|
|
}, handle);
|
|
}
|
|
|
|
function getStatusbar(editor) {
|
|
return statusbars[editor.name];
|
|
}
|
|
|
|
function show() {
|
|
settings.set("user/ace/statusbar/@show", "true");
|
|
}
|
|
|
|
function hide() {
|
|
settings.set("user/ace/statusbar/@show", "false");
|
|
}
|
|
|
|
/***** Register and define API *****/
|
|
|
|
/**
|
|
* Manages the status bar instances for ace.
|
|
* @singleton
|
|
**/
|
|
handle.freezePublicAPI({
|
|
/**
|
|
* Show all the status bars.
|
|
*/
|
|
show: show,
|
|
|
|
/**
|
|
* Hide all the status bars.
|
|
*/
|
|
hide: hide,
|
|
|
|
/**
|
|
* Retrieve the status bar that belongs to an ace editor.
|
|
* @param {Editor} ace The ace editor the status bar belongs to.
|
|
* @return {ace.status.Statusbar}
|
|
*/
|
|
getStatusbar: getStatusbar,
|
|
|
|
/**
|
|
* Inserts CSS for the statusbar.
|
|
* @private
|
|
*/
|
|
draw: draw
|
|
});
|
|
|
|
/***** Initialization *****/
|
|
|
|
function Statusbar(editor) {
|
|
var plugin = new Plugin("Ajax.org", main.consumes);
|
|
var emit = plugin.getEmitter();
|
|
|
|
var showRange;
|
|
|
|
var bar, lblSelection, lblStatus, lblRowCol, lblTabs, lblSyntax; // ui elements
|
|
|
|
statusbars[editor.name] = plugin;
|
|
|
|
var loaded = false;
|
|
function load() {
|
|
if (loaded) return false;
|
|
loaded = true;
|
|
|
|
function updateBarVisible() {
|
|
if (!settings.getBool("user/ace/statusbar/@show")) {
|
|
bar && bar.hide();
|
|
menuItem.enable();
|
|
}
|
|
else {
|
|
draw();
|
|
bar.show();
|
|
menuItem.enable();
|
|
}
|
|
}
|
|
|
|
settings.on("user/ace/statusbar", updateBarVisible, plugin);
|
|
|
|
if (settings.getBool("user/ace/statusbar/@show"))
|
|
draw();
|
|
|
|
editor.on("documentLoad", function(e) {
|
|
var doc = e.doc;
|
|
var session = doc.getSession();
|
|
session.statusBar = plugin;
|
|
session.session.on("changeMode", function(e) { statusUpdate.schedule(); });
|
|
|
|
if (!doc.hasValue())
|
|
doc.once("setValue", function() {
|
|
statusUpdate.schedule();
|
|
}, doc);
|
|
}, plugin);
|
|
editor.on("documentActivate", function(e) { statusUpdate.schedule(); }, plugin);
|
|
editor.on("documentUnload", function(e) {
|
|
delete e.doc.getSession().statusBar;
|
|
}, plugin);
|
|
}
|
|
|
|
var drawn = false;
|
|
function draw() {
|
|
if (drawn) return;
|
|
drawn = true;
|
|
|
|
handle.draw();
|
|
|
|
// Create UI elements
|
|
var htmlNode = editor.aml; //ace.container.parentNode.host;
|
|
ui.insertMarkup(htmlNode, markup, plugin);
|
|
|
|
function setTheme(e) {
|
|
var theme = e.theme;
|
|
if (!theme) return;
|
|
|
|
var cssClass = theme.cssClass;
|
|
var isDark = theme.isDark;
|
|
|
|
var bg = ui.getStyleRule("." + cssClass, "backgroundColor");
|
|
|
|
bar.setAttribute("class", isDark ? "ace_dark" : "");
|
|
if (bg) {
|
|
// bg = bg.replace(/rgb\((.*)\)/, "rgba($1, 0.9)");
|
|
bar.$ext.style.backgroundColor = bg;
|
|
}
|
|
}
|
|
editor.on("themeChange", setTheme);
|
|
|
|
bar = plugin.getElement("bar");
|
|
lblSelection = plugin.getElement("lblSelectionLength");
|
|
lblStatus = plugin.getElement("lblEditorStatus");
|
|
lblRowCol = plugin.getElement("lblRowCol");
|
|
lblTabs = plugin.getElement("lblTabs");
|
|
lblSyntax = plugin.getElement("lblSyntax");
|
|
|
|
// For editor search of submenus
|
|
bar.editor = editor;
|
|
|
|
// Set sub menus
|
|
var button = plugin.getElement("btnSbPrefs");
|
|
button.setAttribute("submenu", menu);
|
|
|
|
lblTabs.setAttribute("submenu", menuTabs);
|
|
|
|
var mnuSyntax = menus.get("View/Syntax").menu;
|
|
lblSyntax.setAttribute("submenu", mnuSyntax);
|
|
lblSyntax.on("mousedown", function() {
|
|
if (editor.activeDocument)
|
|
tabs.focusTab(editor.activeDocument.tab);
|
|
});
|
|
|
|
// Click behavior for the labels
|
|
lblSelection.on("click", function() {
|
|
showRange = !showRange;
|
|
updateStatus();
|
|
});
|
|
|
|
lblRowCol.on("click", function() {
|
|
gotoline.gotoline(null, null, true);
|
|
});
|
|
|
|
// Hook into ace
|
|
var ace = editor.ace;
|
|
if (!ace.$hasStatusBar) {
|
|
// Throttle UI updates
|
|
ace.on("changeSelection", function() { selStatusUpdate.schedule(); });
|
|
ace.on("changeStatus", function() { statusUpdate.schedule(); });
|
|
ace.on("keyboardActivity", function() { statusUpdate.schedule(); });
|
|
ace.renderer.on("scrollbarVisibilityChanged", function(e, renderer) {
|
|
bar.$ext.style.right = renderer.scrollBarV.getWidth() + 5 + "px";
|
|
bar.$ext.style.bottom = renderer.scrollBarH.getHeight() + 3 + "px";
|
|
})(null, ace.renderer);
|
|
ace.$hasStatusBar = true;
|
|
|
|
var theme = editor.theme;
|
|
setTheme({ theme: theme });
|
|
}
|
|
|
|
// Update status information
|
|
updateStatus();
|
|
|
|
emit("draw");
|
|
}
|
|
|
|
var selStatusUpdate = lang.delayedCall(updateSelStatus, 10);
|
|
var statusUpdate = lang.delayedCall(updateStatus, 10);
|
|
|
|
/***** Helper Functions *****/
|
|
|
|
function updateSelStatus() {
|
|
var ace = editor.ace;
|
|
if (!ace || !drawn || !ace.selection) return;
|
|
|
|
if (!ace.selection.isEmpty()) {
|
|
var range = ace.getSelectionRange();
|
|
var selLen;
|
|
|
|
if (showRange) {
|
|
selLen = "(" +
|
|
(range.end.row - range.start.row) + ":" +
|
|
(range.end.column - range.start.column) + ")";
|
|
}
|
|
else {
|
|
selLen = "(" + ace.session.getTextRange(range).length + " Bytes)";
|
|
}
|
|
|
|
lblSelection.setAttribute("caption", selLen);
|
|
}
|
|
else {
|
|
lblSelection.setAttribute("caption", "");
|
|
}
|
|
|
|
var cursor = ace.selection.lead;
|
|
var columnText = (cursor.row + 1) + ":" + (cursor.column + 1);
|
|
if (ace.selection.rangeCount)
|
|
columnText += " [" + ace.selection.rangeCount + "\u202f]";
|
|
lblRowCol.setAttribute("caption", columnText);
|
|
}
|
|
|
|
function updateStatus() {
|
|
var ace = editor.ace;
|
|
if (!ace || !drawn) return;
|
|
|
|
updateSelStatus();
|
|
|
|
lblTabs.setAttribute("caption",
|
|
(ace.getOption("useSoftTabs") ? "Spaces" : "Tabs") + ": "
|
|
+ ace.getOption("tabSize")); // "\\[" + + "\\]");
|
|
|
|
var status = ace.keyBinding.getStatusText() || "";
|
|
if (ace.commands.recording)
|
|
status = "REC";
|
|
|
|
lblStatus.setAttribute("caption", status);
|
|
|
|
var caption = aceHandle.getSyntaxCaption(ace.session.syntax);
|
|
lblSyntax && lblSyntax.setAttribute("caption", caption);
|
|
}
|
|
|
|
/***** Lifecycle *****/
|
|
|
|
plugin.on("load", function() {
|
|
load();
|
|
});
|
|
plugin.on("enable", function() {
|
|
|
|
});
|
|
plugin.on("disable", function() {
|
|
|
|
});
|
|
plugin.on("unload", function() {
|
|
loaded = false;
|
|
});
|
|
|
|
/***** Register and define API *****/
|
|
|
|
/**
|
|
* The status bar for ace editors.
|
|
* @class ace.status.Statusbar
|
|
**/
|
|
plugin.freezePublicAPI({
|
|
/**
|
|
* Redraw the display of the statusbar
|
|
*/
|
|
update: updateStatus
|
|
});
|
|
|
|
plugin.load(null, "acestatus");
|
|
|
|
return plugin;
|
|
}
|
|
|
|
register(null, {
|
|
"ace.status": handle
|
|
});
|
|
}
|
|
}); |