c9-core/plugins/c9.ide.panels/area.js

489 wiersze
18 KiB
JavaScript

define(function(require, module, exports) {
main.consumes = ["Plugin", "layout", "settings", "anims", "ui", "menus"];
main.provides = ["panels.Area"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var layout = imports.layout;
var anims = imports.anims;
var ui = imports.ui;
var menus = imports.menus;
var settings = imports.settings;
var uCaseFirst = require("c9/string").uCaseFirst;
var BARWIDTH = 36;
var WIDTH = 200;
function Area(where, defaultActive, panels, emit) {
var plugin = new Plugin("Ajax.org", main.consumes);
var query = "state/panels/@width-" + where;
var activePanel = null;
var CURWIDTH = 0;
var column, lastPanel, bar, splitter, animating;
function getElement(name) {
var panel = panels.panels[name];
return panel && panel.aml;
}
var drawn = false;
function draw() {
if (drawn) return bar;
drawn = true;
emit("draw");
column = layout.findParent(plugin, where);
bar = column.appendChild(new ui.bar({ "skinset": "panels" }));
plugin.addElement(bar);
column.setWidth(CURWIDTH);
column.setAttribute("class", where);
bar.oncontextmenu = function(e) {
var menu = menus.get("Window").menu;
menu.display(e.x, e.y);
menu.childNodes.forEach(function(x) {
if (x.visible && !x.panel) {
x.hide();
menu.on("prop.visible", function show(e) {
if (!e.value) {
menu.off("prop.visible", show);
x.show();
}
});
}
});
return false;
};
// Prevent scrolling
column.$int.addEventListener("scroll", function(e) {
column.$int.scrollTop = 0;
}, true);
var name = "splitterPanel" + uCaseFirst(where);
splitter = layout.getElement(name);
splitter.on("dragdrop", function(e) {
if (!activePanel)
return;
var width = column.getWidth() - CURWIDTH;
if (settings.get(query) != width)
settings.set(query, width);
});
bar.hide();
return bar;
}
var animateCounter = 0;
function animate(fromName, toName, toWidth, noAnim) {
var win = getElement(fromName);
var toWin = getElement(toName);
var autohide = fromName && panels.panels[fromName].autohide;
if (win === toWin && win)
return;
column.setAttribute("minwidth", CURWIDTH);
animateCounter++;
var onfinish = function() {
if (onfinish.counter != animateCounter)
return;
setTimeout(function() {
if (onfinish.counter != animateCounter)
return;
if (toWin) {
toWinExt.style.zIndex = zIndex2;
toWinExt.style[where] = CURWIDTH + "px";
toWinExt.style.minWidth = "";
toWinExt.style.maxWidth = "";
if (where == "right")
toWinExt.style.left = "0";
// column.setAttribute("minwidth", toWin.minwidth + CURWIDTH);
panels.showing = false;
}
else {
column.setWidth(CURWIDTH);
}
if (win) {
winExt.style.zIndex = zIndex;
win.$ext.style[where] = CURWIDTH + "px";
win.$ext.style.minWidth = "";
win.hide();
}
}, 100);
emit("afterAnimate");
};
onfinish.counter = animateCounter;
if (toWin) {
var toWinExt = toWin.$altExt || toWin.$ext;
var zIndex2 = toWinExt.style.zIndex;
toWinExt.style.zIndex = 2000;
toWin.show();
if (panels.panels[toName].autohide)
panels.showing = true;
}
var anim = {
duration: 0.15,
timingFunction: "cubic-bezier(.10, .10, .25, .90)",
immediate: noAnim
};
if (win) {
var winExt = win.$altExt || win.$ext;
var zIndex = winExt.style.zIndex;
var diff, width;
if (toWin) {
// Hide over the other
if (autohide) {
winExt.style.zIndex = 3000;
diff = apf.getWidthDiff(winExt);
width = winExt.offsetWidth - diff;
winExt.style.minWidth = width + "px";
winExt.style.maxWidth = width + "px";
if (where == "right")
winExt.style.left = "";
anim[where] = (CURWIDTH - win.getWidth() - 1) + "px";
anims.animate(win, anim, onfinish);
}
// Show over the other
else {
winExt.style.zIndex = 1000;
diff = apf.getWidthDiff(winExt);
width = winExt.offsetWidth - diff - 1;
toWinExt.style.minWidth = width + "px";
toWinExt.style.maxWidth = width + "px";
if (where == "right")
toWinExt.style.left = "";
toWinExt.style[where] = (CURWIDTH - win.getWidth()) + "px";
anim[where] = CURWIDTH + "px";
anims.animate(toWin, anim, onfinish);
}
}
// Hide
else {
winExt.style.minWidth = (winExt.offsetWidth - apf.getWidthDiff(winExt)) + "px";
winExt.style[where] = ""; //CURWIDTH + "px";
anim.width = CURWIDTH + "px";
anims.animateSplitBoxNode(column, anim, onfinish);
}
}
// Show
else {
toWin.show();
if (!column.visible) {
column.show();
setTabPadding(1);
}
toWinExt.style.minWidth = (toWidth - apf.getWidthDiff(toWinExt) - CURWIDTH) + "px";
toWinExt.style[where] = ""; //CURWIDTH + "px";
anim.width = toWidth + "px";
anims.animateSplitBoxNode(column, anim, onfinish);
}
}
function activate(name, noAnim, viaButton) {
if (activePanel == name)
return;
draw();
var panel = panels.panels[name];
// old settings can try to activate panel at the wrong area
// todo should we change area based on setting?
if (!panel || panel.area !== plugin)
return;
lastPanel = activePanel;
if (activePanel && (activePanel != name))
deactivate(true, noAnim === true);
var width = (settings.getNumber("state/panels/@width-" + where)
|| panel.width || WIDTH) + CURWIDTH;
var firstTime = panel.draw();
if (!noAnim)
noAnim = !settings.getBool('user/general/@animateui');
if (firstTime && !noAnim) {
setTimeout(function() {
animate(lastPanel, name, width, noAnim);
});
}
else {
animate(lastPanel, name, width, noAnim);
}
activePanel = name;
emit("showPanel" + uCaseFirst(name), {
lastPanel: lastPanel,
button: viaButton
});
if (!panel.autohide)
settings.set("state/panels/@active-" + where, name);
splitter.show();
}
function deactivate(admin, noAnim, viaButton) {
if (!activePanel)
return;
var animSetting = settings.getBool('user/general/@animateui');
if (!admin) {
if (animSetting) {
noAnim = 0;
animate(activePanel);
}
else {
column.setWidth(CURWIDTH);
anims.emitAnimate({ noanim: true });
}
}
if (noAnim !== 0 && (!admin || !animSetting))
getElement(activePanel).hide();
emit("hidePanel" + uCaseFirst(activePanel), {
button: viaButton
});
activePanel = null;
if (!admin) {
settings.set("state/panels/@active-" + where, "none");
splitter.hide();
}
}
function toggle(name, autohide, viaButton) {
// If this is the current panel, deactivate it
if (activePanel != name)
activate(name, null, viaButton);
// If this is an autohiding panel, activate the last panel
else if (autohide && lastPanel)
activate(lastPanel, null, viaButton);
// Else deactivate the active panel
else
deactivate(null, null, viaButton);
}
function setTabPadding(which) {
if (where != "right") return;
ui.setStyleRule(".editor_tab.morepadding .btnsesssioncontainer",
"padding-right", which ? "14px" : "53px");
}
function enablePanel(name) {
var panel = panels.panels[name];
CURWIDTH = BARWIDTH;
draw();
if (!bar.visible) {
if (panels.areas[panel.where].activePanel == name) {
getElement(name).$ext.style[where] = CURWIDTH + "px";
column.setWidth(column.width + CURWIDTH);
activate(name, true);
}
else {
column.setAttribute("minwidth", CURWIDTH);
column.setWidth(CURWIDTH);
}
bar.show();
if (!column.visible) {
column.show();
// column.show triggers splitter.show, even though the column isn't
// reisizable yet. So we hide it and show again when panel is activated.
splitter.hide();
setTabPadding(1);
}
}
panel.enable();
settings.set("state/panels/" + panel.name + "/@enabled", "true");
}
function disablePanel(name, noAnim, keep) {
var panel = panels.panels[name];
panel.disable();
if (!bar)
return;
// Detect whether all buttons are hidden
if (bar.childNodes) {
var hideBar = bar.childNodes.every(function(x) {
return !x.visible;
});
}
if (hideBar)
CURWIDTH = 0;
if (!keep && panels.areas[panel.where].activePanel == name) {
animating = !noAnim;
panels.areas[panel.where].deactivate(null, noAnim);
}
// If all buttons are invisible, hide bar
if (hideBar) {
setTimeout(function() {
bar.hide();
if (!panels.areas[panel.where].activePanel) {
column.hide();
setTabPadding(0);
}
else {
var width = (settings.getNumber("state/panels/@width-" + panel.where)
|| panel.width || WIDTH) + CURWIDTH;
column.setAttribute("minwidth", panel.minWidth + CURWIDTH);
column.setWidth(width);
column.$int.lastChild.style.left = 0;
if (keep && panels.areas[panel.where].activePanel == name)
panel.aml.setLeft(0);
}
}, animating ? 150 : 0);
}
settings.set("state/panels/" + panel.name + "/@enabled", "false");
}
/**
* Area class for the {@link Panel panels}. Panels are located in
* different areas. By default these areas are on the left and
* right of the screen.
*
* * {@link panels} - Manages all areas and panels
* * **Area - Manages a single area of panels.
* By default there is a panel area on the left and on the right side
* of the UI.**
* * {@link Panel} - A single panel that lives in an area.
*
* In this example we'll fetch the name of the active panel on the
* right side and hide it:
*
* var activePanel = panels.areas.right.activePanel;
* panels.deactivate(activePanel);
*
* @class panels.Area
*/
plugin.freezePublicAPI({
/**
* @property {String} activePanel The name of the active panel in this area, if any.
* @readonly
*/
get activePanel() { return activePanel; },
/**
* @property {String} defaultActive The name of the panel that is active by default in this area.
* @readonly
*/
get defaultActive() { return defaultActive; },
/**
* @property {HTMLElement} container The html element that is the containing element of the area.
* @readonly
*/
get container() { return column.$ext; },
/**
* The APF UI element that is presenting the area in the UI.
* This property is here for internal reasons only. *Do not
* depend on this property in your plugin.*
* @property {AMLElement} aml
* @private
* @readonly
*/
get aml() { return column; },
/**
* @property {Number} width The width in pixels of this area
* @readonly
*/
get width() { return CURWIDTH; },
/**
* @ignore
*/
draw: draw,
/**
* Toggles the activity state of a panel
* @param {String} name The name of the panel to toggle
*/
toggle: toggle,
/**
* Activates a panel, showing it as the only visible
* panel in it's area.
* @param {String} name The name of the panel to activate
* @private
*/
activate: activate,
/**
* Deactivates the active panel of this area.
* @private
*/
deactivate: deactivate,
/**
* Add the button to it's button bar. If the bar was hidden, the
* bar is shown.
* @param {String} name The name of the panel to enable.
* @private
*/
enablePanel: enablePanel,
/**
* Remove the button from it's button bar. If the bar is empty, the
* bar is hidden.
* @param {String} name The name of the panel to disable.
* @private
*/
disablePanel: disablePanel
});
plugin.load("area-" + where);
return plugin;
}
/***** Register and define API *****/
register(null, {
"panels.Area": Area
});
}
});