kopia lustrzana https://github.com/c9/core
291 wiersze
11 KiB
JavaScript
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
|
|
});
|
|
}
|
|
}); |