c9-core/plugins/c9.ide.ace.statusbar/statusbar.js

486 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 = handle.getElement("itmSbWrap");
var itmSbWrapPM = handle.getElement("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 = handle.getElement("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,
}, 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;
var selLen;
if (!ace.selection.isEmpty()) {
var range = ace.getSelectionRange();
if (showRange) {
selLen = "(" +
(range.end.row - range.start.row) + ":" +
(range.end.column - range.start.column) + ")";
}
else {
selLen = "(" + ace.session.getTextRange(range).length + " Bytes)";
}
}
setCaption(lblSelection, selLen);
var cursor = ace.selection.lead;
var columnText = (cursor.row + 1) + ":" + (cursor.column + 1);
if (ace.selection.rangeCount)
columnText += " [\u202f" + ace.selection.rangeCount + "\u202f]";
setCaption(lblRowCol, columnText);
}
function updateStatus() {
var ace = editor.ace;
if (!ace || !drawn) return;
updateSelStatus();
setCaption(lblTabs,
(ace.getOption("useSoftTabs") ? "Spaces" : "Tabs") + ": "
+ ace.getOption("tabSize")); // "\\[" + + "\\]");
var status = ace.keyBinding.getStatusText() || "";
if (ace.commands.recording)
status = "REC";
setCaption(lblStatus, status);
var caption = aceHandle.getSyntaxCaption(ace.session.syntax);
setCaption(lblSyntax, caption);
}
function setCaption(lbl, value) {
if (!lbl) return;
if (!value) return lbl.hide();
if (!lbl.visible) lbl.show();
lbl.setAttribute("caption", value);
}
/***** 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
});
}
});