c9-core/plugins/c9.ide.behaviors/dashboard.js

291 wiersze
11 KiB
JavaScript

define(function(require, exports, module) {
main.consumes = ["Plugin", "ui", "dashboard"];
main.provides = ["dashboardbehavior"];
return main;
function main(options, imports, register) {
var Plugin = imports.Plugin;
var ui = imports.ui;
var dashboard = imports.dashboard;
/***** Initialization *****/
var handle = new Plugin("Ajax.org", main.consumes);
// var emit = handle.getEmitter();
var divSplit;
var loaded = false;
function load() {
if (loaded) return false;
loaded = true;
// @todo how to make sure this happens only once?
var css = require("text!./style.css");
ui.insertCss(css, null, handle);
dashboard.on("widgetCreate", function(e) {
if (e.widget.dashboard.configurable)
addInteraction(e.widget);
}, handle);
dashboard.on("widgetAfterClose", function(e) {
//@todo keep total tree small
}, handle);
}
function addInteraction(plugin) {
var widget = plugin.aml;
var titlebar = widget.oCaption && widget.oCaption.parentNode;
if (!titlebar) return;
var container = widget.$ext;
var offsetX, offsetY, startX, startY, dragWidth, dragHeight;
var originalBox, box, started, start;
var originalPosition, splitDirection, splitBox, originalSize;
function finish() {
divSplit.style.display = "none";
apf.removeListener(document, "mousemove", mouseMoveSplit);
apf.removeListener(document, "mouseup", mouseUpSplit);
container.style.zIndex =
container.style.opacity =
container.style.pointerEvents = "";
plugin.dashboard.widgets.forEach(function(widget) {
widget.aml.$int.style.pointerEvents = "";
});
widget.$dragging = false;
}
titlebar.addEventListener("mousedown", function(e) {
// APF stuff
widget.$dragging = true;
// Calculate where on the titlebar was clicked
var rect = container.getBoundingClientRect();
startX = e.clientX;
startY = e.clientY;
offsetX = startX - rect.left;
offsetY = startY - rect.top;
// Use mine
started = false;
// Set current box
box = widget.parentNode;
// Store original info
originalBox = box;
originalPosition = container.nextSibling;
originalSize = [container.style.left, container.style.top,
container.style.width, container.style.height,
ui.getStyle(container, "margin")];
dragWidth = container.offsetWidth;
dragHeight = container.offsetHeight;
// Div that shows where to insert split
if (!divSplit) {
divSplit = document.createElement("div");
divSplit.className = "split-area dark";
document.body.appendChild(divSplit);
}
// Fixate current position and width
start = function() {
rect = container.getBoundingClientRect();
container.style.width = (dragWidth - ui.getWidthDiff(container)) + "px";
container.style.height = (dragHeight - ui.getHeightDiff(container)) + "px";
// Prepare titlebar for dragging
container.style.zIndex = 100000;
container.style.opacity = 0.7;
container.style.margin = 0;
container.style.pointerEvents = "none";
plugin.dashboard.widgets.forEach(function(widget) {
widget.aml.$int.style.pointerEvents = "none";
});
document.body.appendChild(container);
};
apf.addListener(document, "mousemove", mouseMoveSplit);
apf.addListener(document, "mouseup", mouseUpSplit);
});
function showSplitPosition(e) {
var el = document.elementFromPoint(e.clientX, e.clientY);
var aml = apf.findHost(el);
while (aml && aml.localName != "frame")
aml = aml.parentNode;
// If aml is not the box we seek, lets abort
if (!aml) {
divSplit.style.display = "none";
splitBox = null;
splitDirection = null;
return;
}
// Find the rotated quarter that we're in
var rect = aml.$ext.getBoundingClientRect();
var left = (e.clientX - rect.left) / rect.width;
var right = 1 - left;
var top = (e.clientY - rect.top) / rect.height;
var bottom = 1 - top;
// Cannot split box that would be removed later
//@todo this needs to be a check against self
// if (aml.getWidgets().length === 0) { // && aml == originalBox
// divSplit.style.display = "none";
// splitBox = null;
// splitDirection = null;
// return;
// }
splitBox = aml;
// Anchor to closes side
var min = Math.min(left, top, right, bottom);
// Get titlebars height
var bHeight = aml.oCaption.parentNode.offsetHeight;
// Left
if (min == left) {
divSplit.style.left = rect.left + "px";
divSplit.style.top = (bHeight + rect.top) + "px";
divSplit.style.width = (rect.width / 2) + "px";
divSplit.style.height = (rect.height - bHeight) + "px";
splitDirection = "w";
}
// Right
else if (min == right) {
divSplit.style.left = rect.left + (rect.width / 2) + "px";
divSplit.style.top = (bHeight + rect.top) + "px";
divSplit.style.width = (rect.width / 2) + "px";
divSplit.style.height = (rect.height - bHeight) + "px";
splitDirection = "e";
}
// Top
else if (min == top) {
divSplit.style.left = rect.left + "px";
divSplit.style.top = (bHeight + rect.top) + "px";
divSplit.style.width = rect.width + "px";
divSplit.style.height = ((rect.height / 2) - bHeight) + "px";
splitDirection = "n";
}
// Bottom
else if (min == bottom) {
divSplit.style.left = rect.left + "px";
divSplit.style.top = (rect.top + (rect.height / 2)) + "px";
divSplit.style.width = rect.width + "px";
divSplit.style.height = (rect.height / 2) + "px";
splitDirection = "s";
}
divSplit.style.cursor = splitDirection + "-resize";
divSplit.style.display = "block";
}
function mouseMoveSplit(e) {
if (!started) {
if (Math.abs(startX - e.clientX) < 4
&& Math.abs(startY - e.clientY) < 4)
return;
started = true;
start();
}
container.style.left = (e.clientX - offsetX) + "px";
container.style.top = (e.clientY - offsetY) + "px";
return showSplitPosition(e);
}
function mouseUpSplit(e) {
apf.removeListener(document, "mousemove", mouseMoveSplit);
apf.removeListener(document, "mouseup", mouseUpSplit);
if (!started) return finish();
container.style.left = (e.clientX - offsetX) + "px";
container.style.top = (e.clientY - offsetY) + "px";
showSplitPosition(e);
if (splitBox) {
if (splitDirection == "n")
plugin.vsplit(splitBox, widget, false);
else if (splitDirection == "s")
plugin.vsplit(splitBox, widget, true);
else if (splitDirection == "w")
plugin.hsplit(splitBox, widget, false);
else if (splitDirection == "e")
plugin.hsplit(splitBox, widget, true);
var child = box.childNodes[0];
if (child.localName == "splitter")
child = box.childNodes[1];
var pNode = box.parentNode;
var next = box.nextSibling;
pNode.removeChild(box);
pNode.insertBefore(child, next);
if (box.edge) {
child.setAttribute("edge", box.edge);
child.$ext.style.margin = "";
}
child.setAttribute("width", box.width || "");
child.setAttribute("height", box.height || "");
box.destroy(true, true);
}
else {
originalBox.insertBefore(widget, originalPosition);
container.style.left = originalSize[0];
container.style.top = originalSize[1];
container.style.width = originalSize[2];
container.style.height = originalSize[3];
container.style.margin = originalSize[4];
}
// Remove box if empty
// if (originalBox && originalBox.getWidgets().length === 0)
// originalBox.cloud9box.unload();
finish();
}
}
/***** Methods *****/
/***** Lifecycle *****/
handle.on("load", function() {
load();
});
handle.on("enable", function() {
});
handle.on("disable", function() {
});
handle.on("unload", function() {
loaded = false;
});
/***** Register and define API *****/
/**
**/
handle.freezePublicAPI({});
register(null, {
dashboardbehavior: handle
});
}
});