c9-core/plugins/c9.ide.local/windowframe.js

507 wiersze
18 KiB
JavaScript

/*global nativeRequire nwDispatcher windowManager*/
define(function(require, exports, module) {
main.consumes = [
"c9", "Plugin", "menus", "settings", "ui",
"upload", "commands", "dialog.question",
"layout", "dialog.error", "util", "MenuItem",
];
main.provides = ["window.frame"];
return main;
function main(options, imports, register) {
var c9 = imports.c9;
var ui = imports.ui;
var menus = imports.menus;
var Plugin = imports.Plugin;
var settings = imports.settings;
var commands = imports.commands;
var util = imports.util;
var layout = imports.layout;
var question = imports["dialog.question"];
var error = imports["dialog.error"];
// Some require magic to get nw.gui
var nw = nativeRequire("nw.gui");
// Ref to window
var win = nw.Window.get();
var Menu = nw.Menu;
var MenuItem = nw.MenuItem;
var Tray = nw.Tray;
var tray, nativeTitle, title, titlebar;
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
// var emit = plugin.getEmitter();
var loaded = false;
function load() {
if (loaded) return false;
loaded = true;
// Load native title
setNativeTitle();
// When the UI is loaded, show the window
c9.once("ready", function() {
// Check Window Location
validateWindowGeometry();
}, plugin);
win.on("focusWindow", focusWindow);
// Menu Items
menus.addItemByPath("Cloud9/~", new ui.divider(), 2000000, plugin);
menus.addItemByPath("Cloud9/Quit Cloud9", new ui.item({
selector: "closeAllWindowsQuit:",
command: "exit"
}), 2000100, plugin);
menus.addItemByPath("Window/Developer Tools", new ui.item({
onclick: function() {
win.showDevTools();
}
}), 2000000, plugin);
menus.addItemByPath("View/~", new ui.divider(), 800, plugin);
var itemFullscreen = new ui.item({
isAvailable: function() {
itemFullscreen.setAttribute("caption",
win.isFullscreen
? "Leave Full Screen"
: "Enter Full Screen");
return true;
},
command: "toggleFullscreen"
});
menus.addItemByPath("View/Enter Full Screen",
itemFullscreen, 900, plugin);
commands.addCommand({
name: "exit",
bindKey: { mac: "Command-Q", win: "" },
exec: function() { windowManager.quit(); }
}, plugin);
commands.addCommand({
name: "closeWindow",
bindKey: { mac: "", win: "Alt-F4" },
exec: function() { win.emit("close", "quit"); }
}, plugin);
commands.addCommand({
name: "fallback",
bindKey: { mac: "Command-W", win: "Ctrl-F4" },
isAvailable: function() {
return true;
},
exec: function() {
// Do nothing
}
}, plugin);
commands.addCommand({
name: "toggleFullscreen",
exec: function() {
setTimeout(function() {
win.isFullscreen
? win.leaveFullscreen()
: win.enterFullscreen();
}, 100);
}
}, plugin);
// Deal with closing
win.on("askForQuit", function(quit) {
var acceptQuit = quit ? windowManager.quitAll : saveAndQuit;
// Fetch quit message, if any
var message = window.onbeforeunload && window.onbeforeunload();
if (message) {
question.show("Quit Cloud9?",
"Are you sure you want to " + (quit ? "exit Cloud9?" : "close this window"),
"Cloud9 will preserve your entire state. "
+ "Even unsaved files or changes will still "
+ "be available the next time you start cloud9.",
function() { // yes
settings.set("user/general/@confirmexit",
!question.dontAsk);
acceptQuit();
},
function() { // no
settings.set("user/general/@confirmexit",
!question.dontAsk);
if (quit)
windowManager.unquit();
}, {
showDontAsk: true,
yes: "Quit",
no: "Cancel",
});
// make sure nothing can cover this dialog
question.once("show", function() {
question.aml.setProperty("zindex", 30000000);
});
focusWindow();
} else {
acceptQuit();
}
});
win.on("saveAndQuit", saveAndQuit);
win.on("close", function(quit) {
win.emit("askForQuit", quit);
});
// saving can be slow for remote workspaces
// so we hide window, Save All State and then quit
function saveAndQuit() {
win.hide();
// Prepare cloud9 for quitting
c9.beforequit();
// Notify plugins that we're quitting
c9.quit();
// Unregister the window
windowManager.onClose(window.win.options.id);
win.close(true);
}
// Settings
settings.on("read", function() {
settings.setDefaults("user/local", [
["tray", "false"]
]);
if (settings.getBool("user/local/@tray"))
toggleTray(true);
}, plugin);
settings.on("user/local", function() {
if (Boolean(tray) !== settings.getBool("user/local/@tray"))
toggleTray(!tray);
if (nativeTitle !== settings.getBool("user/local/@nativeTitle"))
switchNativeTitle(!nativeTitle);
}, plugin);
// Preferences
// prefs.add({
// "General" : {
// position: 100,
// "General" : {
// "Show Tray Icon" : {
// type: "checkbox",
// path: "user/local/@tray",
// position: 300
// }
// // "Use Native Title Bar (requires restart)" : {
// // type : "checkbox",
// // path : "user/local/@nativeTitle",
// // position : 300
// // }
// }
// }
// }, plugin);
// Window
win.on("minimize", function() {
win.isMinimized = true;
settings.set("state/local/window/@minimized", true);
});
win.on("restore", function() {
win.isMinimized = false;
settings.set("state/local/window/@minimized", false);
});
win.on("maximize", function() {
win.isMaximized = true;
settings.set("state/local/window/@maximized", true);
});
win.on("unmaximize", function() {
win.isMaximized = false;
settings.set("state/local/window/@maximized", false);
});
var handler = storeWindowSettings.bind(null, false);
win.on("move", handler);
win.on("resize", handler);
win.on("enter-fullscreen", handler);
win.on("leave-fullscreen", handler);
}
/***** Methods *****/
var timer;
function storeWindowSettings(force) {
if (!force) {
clearTimeout(timer);
timer = setTimeout(storeWindowSettings.bind(null, true), 1000);
return;
}
settings.set("state/local/window/@fullscreen", win.isFullscreen);
win.emit("savePosition");
if (win.isFullscreen || win.isMaximized || win.isMinimized)
return;
settings.set("state/local/window/@position", win.x + ":" + win.y);
settings.set("state/local/window/@size", win.width + ":" + win.height);
}
function toggleTray(to) {
if (to) {
// Create a tray icon
tray = new Tray({ icon: 'favicon.ico' });
// Give it a menu
var menu = new Menu();
menu.append(new MenuItem({
label: 'Visit c9.io',
click: function() {
window.open("http://c9.io");
}
}));
menu.append(new MenuItem({
label: 'Show Developer Tools',
click: function() {
win.showDevTools();
}
}));
tray.menu = menu;
}
else {
// Remove the tray
tray.remove();
tray = null;
}
}
function switchNativeTitle(to) {
}
function setNativeTitle() {
ui.insertCss(require("text!./local.less"), options.staticPrefix, plugin);
var platform = process.platform; // c9.platform is remote os platform so we use process instead
var titleHeight = platform == "win32" ? 27 : 23;
var isMaximized = settings.get("state/local/window/@maximized");
error.top = titleHeight + 1;
var div = document.body.appendChild(document.createElement("div"));
div.className = "window-border";
// Move elements down to make room for the title bar
layout.getElement("root").setAttribute("anchors", titleHeight + " 0 0 0");
document.querySelector(".c9-mbar-round").style.display = "none";
document.querySelector(".c9-mbar-logo").style.paddingTop = "0";
document.querySelector(".c9-menu-bar .c9-mbar-cont").style.paddingRight = "16px";
ui.setStyleRule(".right .panelsbar", "top", "-1px");
ui.setStyleRule(".right .panelsbar", "position", "absolute");
var logobar = layout.getElement("logobar");
if (!menus.minimized)
logobar.setHeight(27);
logobar.$ext.style.maxHeight = "27px";
titlebar = document.body.appendChild(document.createElement("div"));
titlebar.className = "window-titlebar focus " + platform + (isMaximized ? " maximized" : "");
// Caption
title = titlebar.appendChild(document.createElement("div"));
title.className = "caption";
// Maximize
var fullscreenbtn = titlebar.appendChild(document.createElement("div"));
fullscreenbtn.className = "fullscreen";
fullscreenbtn.addEventListener("click", function() {
win.enterFullscreen();
});
// Buttons
var closebtn = titlebar.appendChild(document.createElement("div"));
closebtn.className = "closebtn";
closebtn.addEventListener("click", function() {
win.close();
});
var minbtn = titlebar.appendChild(document.createElement("div"));
minbtn.className = "minbtn";
minbtn.addEventListener("click", function() {
win.minimize();
});
var maxbtn = titlebar.appendChild(document.createElement("div"));
maxbtn.className = "maxbtn";
maxbtn.addEventListener("click", function() {
isMaximized && !apf.isMac
? win.unmaximize()
: win.maximize();
});
win.on("blur", function() {
titlebar.className = titlebar.className.replace(/ focus/g, "");
});
win.on("focus", function() {
titlebar.className += " focus";
});
win.on("maximize", function() {
titlebar.className += " maximized";
isMaximized = true;
});
win.on("unmaximize", function() {
titlebar.className = titlebar.className.replace(/ maximized/g, "");
isMaximized = false;
});
var timer;
var lastScreen = util.extend({}, screen);
win.on("move", function(x, y) {
clearTimeout(timer);
timer = setTimeout(checkScreen, 500);
});
// Temporary Hack - need resolution event
setInterval(checkScreen, 2000);
function checkScreen() {
var s = lastScreen;
lastScreen = util.extend({}, screen);
if (!util.isEqual(s, lastScreen))
validateWindowGeometry(true);
}
win.on("leave-fullscreen", function() {
layout.getElement("root").setAttribute("anchors", titleHeight + " 0 0 0");
titlebar.style.display = "block";
document.body.classList.remove("fullscreen");
});
var enterFullscreen = function() {
layout.getElement("root").setAttribute("anchors", "0 0 0 0");
titlebar.style.display = "none";
document.body.classList.add("fullscreen");
};
win.on("enter-fullscreen", enterFullscreen);
if (win.isFullscreen) enterFullscreen();
var menubar = document.querySelector(".c9-menu-bar");
menubar.style.backgroundPosition = "0 -4px";
menubar.style.webkitUserSelect = "none";
}
function focusWindow() {
// To support all platforms, we need to call both show and focus
win.show();
win.focus();
}
function validateWindowGeometry(fitInScreen) {
if (settings.get("state/local/window/@maximized"))
return;
// Check if Window Position is In view
var changedSize;
var changedPos;
var width = Math.max(400, win.width);
var height = Math.max(300, win.height);
if (width > screen.availWidth) {
width = screen.availWidth;
changedSize = true;
}
if (height > screen.availHeight) {
height = screen.availHeight;
changedSize = true;
}
var left = win.x;
var top = win.y;
var minLeft = screen.width - screen.availWidth; // Guestimate
if (left < minLeft) {
left = screen.availLeft;
changedPos = true;
}
else if (left > screen.availWidth + screen.availLeft) {
left = screen.availWidth + screen.availLeft - 100;
changedPos = true;
}
if (top < screen.availTop) {
top = screen.availTop;
changedPos = true;
}
else if (top > screen.availHeight + screen.availTop) {
top = screen.availHeight + screen.availTop - 100;
changedPos = true;
}
else if (fitInScreen && height + top > screen.availTop + screen.availHeight) {
top = screen.availTop;
height = screen.availHeight;
changedPos = true;
changedSize = true;
}
if (changedPos)
win.moveTo(left, top);
if (changedSize)
win.resizeTo(width, height);
}
function setTitle(str) {
if (title)
title.textContent = str;
}
/***** Lifecycle *****/
plugin.on("load", function() {
load();
});
plugin.on("enable", function() {
});
plugin.on("disable", function() {
});
plugin.on("unload", function() {
toggleTray(false);
loaded = false;
});
/***** Register and define API *****/
/**
* Draws the file tree
* @event afterfilesave Fires after a file is saved
* @param {Object} e
* node {XMLNode} description
* oldpath {String} description
**/
plugin.freezePublicAPI({
/**
*
*/
focusWindow: focusWindow,
setTitle: setTitle
});
register(null, {
"window.frame": plugin
});
}
});