<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

Cu.import("resource://gre/modules/ctypes.jsm");

Cu.import("chrome://htitle/content/HTitleShare.jsm");
Cu.import("chrome://htitle/content/PrefPageObserver.jsm");
Cu.import("chrome://htitle/content/Libs.jsm");

var EXPORTED_SYMBOLS = ["HTitleUtils"];

var HTitlePrefObserver = {
    register: function() {
        HTitleUtils.prefs.addObserver("", this, false);
    },

    unregister: function() {
        HTitleUtils.prefs.removeObserver("", this);
    },

    observe: function(subject, topic, data) {
        if (topic != "nsPref:changed")
            return;

        switch(data) {
            case "debug":
                HTitleShare.debug = HTitleUtils.prefs.getBoolPref("debug");
                break;
            case "legacy_mode.timeout_check":
                HTitleUtils.timeoutCheck = HTitleUtils.prefs.getIntPref("legacy_mode.timeout_check");
                break;
            case "legacy_mode.timeout_between_changes":
                HTitleUtils.timeoutBetweenChanges = HTitleUtils.prefs.getIntPref("legacy_mode.timeout_between_changes");
                break;
        }
    }
}

var HTitleUtilsPrivate = {
    execute: function(path, args, needWait=true) {
        var file = Cc["@mozilla.org/file/local;1"]
                     .createInstance(Ci.nsIFile);
        file.initWithPath(path);

        var process = Cc["@mozilla.org/process/util;1"]
                        .createInstance(Ci.nsIProcess);
        try {
            process.init(file);
            process.run(needWait, args, args.length);
        }
        catch (error) {
            HTitleUtils.log(error.message, "ERROR");
            return -1;
        }

        if (needWait) {
            HTitleUtils.log("Exit value of " + path + " is \"" + process.exitValue + "\"", "DEBUG");
            return process.exitValue;
        }
        else
            return 0;
    }
}

var HTitleUtils = {
    appInfo: null,
    prefs: null,

    windowControlsLayout: null,
    titlebarActions: null,

    utils: {},

    timeoutCheck: 200, // ms
    timeoutBetweenChanges: 200, // ms

    init: function() {
        this.appInfo = Cc["@mozilla.org/xre/app-info;1"]
                         .getService(Ci.nsIXULAppInfo);

        this.prefs = Cc["@mozilla.org/preferences-service;1"]
                       .getService(Ci.nsIPrefService)
                       .getBranch("extensions.htitle.");
        HTitlePrefObserver.register();

        HTitleShare.debug = this.prefs.getBoolPref("debug");
        this.timeoutCheck = this.prefs.getIntPref("legacy_mode.timeout_check");
        this.timeoutBetweenChanges = this.prefs.getIntPref("legacy_mode.timeout_between_changes");

        HTitleShare.gtkVersion = this.getGtkVersion();
        this.windowControlsLayout = this.getWindowControlsLayout();
        this.titlebarActions = this.getTitlebarActions();
    },

    /* ::::: App info functions ::::: */

    isFirefox: function() {
        return (this.appInfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}");
    },

    isThunderbird: function() {
        return (this.appInfo.ID == "{3550f703-e582-4d05-9a08-453d09bdfdc6}");
    },

    isSeaMonkey: function() {
        return (this.appInfo.ID == "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}");
    },

    /* ::::: Change currentset attribute ::::: */

    addToCurrentset: function(node, id) {
        var currentset = node.getAttribute("currentset");
        if (!currentset)
            currentset = node.getAttribute("defaultset");
        currentset = currentset + (currentset == "" ? "" : ",") + id;
        node.setAttribute("currentset", currentset);
    },

    removeFromCurrentset: function(node, id) {
        var currentset = node.getAttribute("currentset");
        if (!currentset)
            currentset = node.getAttribute("defaultset");
        var re = new RegExp("(^|,)" + id + "($|,)");
        currentset = currentset.replace(re, "$2");
        node.setAttribute("currentset", currentset);
    },

    /* ::::: Toolkit version ::::: */

    getGtkVersion: function() {
        var widget_toolkit;
        if (this.prefs.getPrefType("widget_toolkit") == this.prefs.PREF_STRING) {
            widget_toolkit = this.prefs.getCharPref("widget_toolkit");
        }
        else {
            var xul_runtime = Cc["@mozilla.org/xre/app-info;1"]
                                .getService(Ci.nsIXULRuntime);
            widget_toolkit = xul_runtime.widgetToolkit;
        }
        return (widget_toolkit == "gtk3") ? 3 : 2;
    },

    /* ::::: Use external utilities ::::: */

    findPathToExec: function(name) {
        // Return full path or null. Works like "which $name"

        var file = Cc["@mozilla.org/file/local;1"]
                     .createInstance(Ci.nsIFile);

        var env = Cc["@mozilla.org/process/environment;1"]
                    .getService(Ci.nsIEnvironment);
        var path = env.get("PATH").split(":");

        for (var i = 0; i < path.length; i++) {
            var full_path_to_exec = path[i] + "/" + name;

            file.initWithPath(full_path_to_exec);
            if (file.exists() && file.isExecutable()) {
                this.log("Command \"" + name + "\" was found in \"" + path[i] + "\"", "DEBUG");
                return full_path_to_exec;
            }
        }

        this.log("$PATH = " + path, "DEBUG");
        this.log("Command \"" + name + "\" not found", "ERROR");

        return null;
    },

    checkUtilsAvailable: function(utils) {
        var paths = {};
        for (var i = 0; i < utils.length; i++) {
            var path;
            if (this.utils[utils[i]] === undefined) {
                path = this.findPathToExec(utils[i]);
                this.utils[utils[i]] = path;
            }
            else {
                path = this.utils[utils[i]];
            }
            if (path == null)
                return null;
            paths[utils[i]] = path;
        }
        return paths;
    },

    checkPresenceGnomeShell: function() {
        this.log("Start checking DE", "DEBUG");

        var path = this.checkUtilsAvailable(["pidof"]);

        if (path.pidof) {
            var exitValue = HTitleUtilsPrivate.execute(path.pidof, ["gnome-shell"]);
            return (exitValue == 1 ? 1 : 0);
        }
        else {
            this.log("pidof doesn't exist", "ERROR");
            return 2;
        }
    },

    /* ::::: Native window ::::: */

    changeWindowProperty: function(window, mode, action) {
        var X11 = Libs.open("X11");
        var Gdk = Libs.open("Gdk", HTitleShare.gtkVersion, X11);

        /* Get native window */
        var base_window = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation)
                                .QueryInterface(Ci.nsIDocShellTreeItem)
                                .treeOwner
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .nsIBaseWindow;
        var native_handle = base_window.nativeHandle;

        var gdk_window = new Gdk.GdkWindow.ptr(ctypes.UInt64(native_handle));
        gdk_window = Gdk.Window.get_toplevel(gdk_window);

        var gdk_display = Gdk.Display.get_default();
        var x11_display = Gdk.X11Display.get_xdisplay(gdk_display);
        if (HTitleShare.gtkVersion == 3) {
            var x11_window = Gdk.X11Window.get_xid(gdk_window);
        }
        else {
            var x11_window = Gdk.X11Window.get_xid(ctypes.cast(gdk_window, Gdk.GdkDrawable.ptr));
        }

        //Gdk.Window.hide(gdk_window);
        if (mode == "always") {
            Gdk.Window.set_decorations(gdk_window, (action == "set") ? Gdk.GDK_DECOR_BORDER : Gdk.GDK_DECOR_ALL);
        }
        else {
            if (HTitleShare.gtkVersion == 3) {
                Gdk.X11Window.set_hide_titlebar_when_maximized(gdk_window, (action == "set"));
            }
            else {
                let x11_property = Gdk.x11_get_xatom_by_name_for_display(gdk_display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED");
                if (action == "set") {
                    // let t = new Uint8Array([1]);
                    // let x11_data = ctypes.uint8_t.ptr(t);
                    let t = new Uint32Array([1]);
                    let x11_data = ctypes.uint32_t.ptr(t);
                    X11.XChangeProperty(x11_display, x11_window, x11_property, X11.XA_CARDINAL, 32, X11.PropModeReplace, x11_data, 1);
                }
                else {
                    X11.XDeleteProperty(x11_display, x11_window, x11_property);
                }
            }
        }
        //Gdk.Window.show(gdk_window);

        Libs.close(Gdk);
        Libs.close(X11);
    },

    setWindowProperty: function(window, mode) {
        try {
            this.changeWindowProperty(window, mode, "set");
        } catch (e) {
            return -1;
        }
        return 0;
    },

    removeWindowProperty: function(window, mode) {
        try {
            this.changeWindowProperty(window, mode, "remove");
        } catch (e) {
            return -1;
        }
        return 0;
    },

    lowerWindow: function(window) {
        var Gdk = Libs.open("Gdk", HTitleShare.gtkVersion);
        var base_window = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation)
                                .QueryInterface(Ci.nsIDocShellTreeItem)
                                .treeOwner
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .nsIBaseWindow;
        var native_handle = base_window.nativeHandle;
        var gdk_window = new Gdk.GdkWindow.ptr(ctypes.UInt64(native_handle));
        gdk_window = Gdk.Window.get_toplevel(gdk_window);
        Gdk.Window.lower(gdk_window);
        Libs.close(Gdk);
    },

    /* ::::: CSS stylesheets ::::: */

    loadStyle: function(name) {
        var sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
        var io = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
        var uri = io.newURI("chrome://htitle/skin/" + name + ".css", null, null);
        if (!sss.sheetRegistered(uri, sss.USER_SHEET))
            sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
    },

    unloadStyle: function(name) {
        var sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
        var io = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
        var uri = io.newURI("chrome://htitle/skin/" + name + ".css", null, null);
        if (sss.sheetRegistered(uri, sss.USER_SHEET))
            sss.unregisterSheet(uri, sss.USER_SHEET);
    },

    /* ::::: Preferences ::::: */

    getWindowControlsLayout: function() {
        var layout = ":close"; // It's default for GNOME 3

        if (!this.prefs.getBoolPref("window_controls.get_layout_by_gsettings"))
            return layout;

        try {
            let gsettings = Cc["@mozilla.org/gsettings-service;1"]
                              .getService(Ci.nsIGSettingsService)
                              .getCollectionForSchema("org.gnome.shell.overrides");
            let button_layout = gsettings.getString("button-layout");
            if (/^([a-zA-Z0-9:,]*)$/.test(button_layout)) {
                layout = button_layout;
            }
            this.log("org.gnome.shell.overrides.button-layout = '" + button_layout + "'", "DEBUG");
        } catch(e) {
            this.log("GSettings isn't available", "WARNING");
            return layout;
        }

        return layout;
    },

    getTitlebarActions: function() {
        var actions = {double: "toggle-maximize",
                       middle: "lower",
                       right:  "menu"}; // It's default for GNOME 3

        if (!this.prefs.getBoolPref("titlebar.get_actions_by_gsettings"))
            return actions;

        try {
            let gsettings = Cc["@mozilla.org/gsettings-service;1"]
                              .getService(Ci.nsIGSettingsService)
                              .getCollectionForSchema("org.gnome.desktop.wm.preferences");

            actions.double = gsettings.getString("action-double-click-titlebar");
            actions.middle = gsettings.getString("action-middle-click-titlebar");
            actions.right = gsettings.getString("action-right-click-titlebar");

            this.log("org.gnome.desktop.wm.preferences.action-double-click-titlebar = '" + actions.double + "'", "DEBUG");
            this.log("org.gnome.desktop.wm.preferences.action-middle-click-titlebar = '" + actions.middle + "'", "DEBUG");
            this.log("org.gnome.desktop.wm.preferences.action-right-click-titlebar = '" + actions.right + "'", "DEBUG");
        } catch(e) {
            this.log("GSettings isn't available", "WARNING");
            return actions;
        }

        return actions;
    },

    /* ::::: Logging ::::: */

    log: function(message, level="ERROR") {
        if (HTitleShare.debug == false && level == "DEBUG")
            return;

        var console = Cc["@mozilla.org/consoleservice;1"]
                        .getService(Ci.nsIConsoleService);

        var flag;
        switch (level) {
            case "ERROR":
                flag = 0;
                break;
            case "WARNING":
                flag = 1;
                break;
            default:
                flag = 4;
        }

        if (flag == 4) {
            console.logStringMessage("HTitle DEBUG: " + message);
        }
        else {
            var console_message = Cc["@mozilla.org/scripterror;1"]
                                    .createInstance(Ci.nsIScriptError);
            console_message.init(message, "HTitle", null, null, null, flag, null);
            console.logMessage(console_message);
        }
    },
}

HTitleUtils.init();
<commit_msg>Add "org.gnome.desktop.wm.preferences.button_layout" usage (GNOME 3.14)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;

Cu.import("resource://gre/modules/ctypes.jsm");

Cu.import("chrome://htitle/content/HTitleShare.jsm");
Cu.import("chrome://htitle/content/PrefPageObserver.jsm");
Cu.import("chrome://htitle/content/Libs.jsm");

var EXPORTED_SYMBOLS = ["HTitleUtils"];

var HTitlePrefObserver = {
    register: function() {
        HTitleUtils.prefs.addObserver("", this, false);
    },

    unregister: function() {
        HTitleUtils.prefs.removeObserver("", this);
    },

    observe: function(subject, topic, data) {
        if (topic != "nsPref:changed")
            return;

        switch(data) {
            case "debug":
                HTitleShare.debug = HTitleUtils.prefs.getBoolPref("debug");
                break;
            case "legacy_mode.timeout_check":
                HTitleUtils.timeoutCheck = HTitleUtils.prefs.getIntPref("legacy_mode.timeout_check");
                break;
            case "legacy_mode.timeout_between_changes":
                HTitleUtils.timeoutBetweenChanges = HTitleUtils.prefs.getIntPref("legacy_mode.timeout_between_changes");
                break;
        }
    }
}

var HTitleUtilsPrivate = {
    execute: function(path, args, needWait=true) {
        var file = Cc["@mozilla.org/file/local;1"]
                     .createInstance(Ci.nsIFile);
        file.initWithPath(path);

        var process = Cc["@mozilla.org/process/util;1"]
                        .createInstance(Ci.nsIProcess);
        try {
            process.init(file);
            process.run(needWait, args, args.length);
        }
        catch (error) {
            HTitleUtils.log(error.message, "ERROR");
            return -1;
        }

        if (needWait) {
            HTitleUtils.log("Exit value of " + path + " is \"" + process.exitValue + "\"", "DEBUG");
            return process.exitValue;
        }
        else
            return 0;
    }
}

var HTitleUtils = {
    appInfo: null,
    prefs: null,

    windowControlsLayout: null,
    titlebarActions: null,

    utils: {},

    timeoutCheck: 200, // ms
    timeoutBetweenChanges: 200, // ms

    init: function() {
        this.appInfo = Cc["@mozilla.org/xre/app-info;1"]
                         .getService(Ci.nsIXULAppInfo);

        this.prefs = Cc["@mozilla.org/preferences-service;1"]
                       .getService(Ci.nsIPrefService)
                       .getBranch("extensions.htitle.");
        HTitlePrefObserver.register();

        HTitleShare.debug = this.prefs.getBoolPref("debug");
        this.timeoutCheck = this.prefs.getIntPref("legacy_mode.timeout_check");
        this.timeoutBetweenChanges = this.prefs.getIntPref("legacy_mode.timeout_between_changes");

        HTitleShare.gtkVersion = this.getGtkVersion();
        this.windowControlsLayout = this.getWindowControlsLayout();
        this.titlebarActions = this.getTitlebarActions();
    },

    /* ::::: App info functions ::::: */

    isFirefox: function() {
        return (this.appInfo.ID == "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}");
    },

    isThunderbird: function() {
        return (this.appInfo.ID == "{3550f703-e582-4d05-9a08-453d09bdfdc6}");
    },

    isSeaMonkey: function() {
        return (this.appInfo.ID == "{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}");
    },

    /* ::::: Change currentset attribute ::::: */

    addToCurrentset: function(node, id) {
        var currentset = node.getAttribute("currentset");
        if (!currentset)
            currentset = node.getAttribute("defaultset");
        currentset = currentset + (currentset == "" ? "" : ",") + id;
        node.setAttribute("currentset", currentset);
    },

    removeFromCurrentset: function(node, id) {
        var currentset = node.getAttribute("currentset");
        if (!currentset)
            currentset = node.getAttribute("defaultset");
        var re = new RegExp("(^|,)" + id + "($|,)");
        currentset = currentset.replace(re, "$2");
        node.setAttribute("currentset", currentset);
    },

    /* ::::: Toolkit version ::::: */

    getGtkVersion: function() {
        var widget_toolkit;
        if (this.prefs.getPrefType("widget_toolkit") == this.prefs.PREF_STRING) {
            widget_toolkit = this.prefs.getCharPref("widget_toolkit");
        }
        else {
            var xul_runtime = Cc["@mozilla.org/xre/app-info;1"]
                                .getService(Ci.nsIXULRuntime);
            widget_toolkit = xul_runtime.widgetToolkit;
        }
        return (widget_toolkit == "gtk3") ? 3 : 2;
    },

    /* ::::: Use external utilities ::::: */

    findPathToExec: function(name) {
        // Return full path or null. Works like "which $name"

        var file = Cc["@mozilla.org/file/local;1"]
                     .createInstance(Ci.nsIFile);

        var env = Cc["@mozilla.org/process/environment;1"]
                    .getService(Ci.nsIEnvironment);
        var path = env.get("PATH").split(":");

        for (var i = 0; i < path.length; i++) {
            var full_path_to_exec = path[i] + "/" + name;

            file.initWithPath(full_path_to_exec);
            if (file.exists() && file.isExecutable()) {
                this.log("Command \"" + name + "\" was found in \"" + path[i] + "\"", "DEBUG");
                return full_path_to_exec;
            }
        }

        this.log("$PATH = " + path, "DEBUG");
        this.log("Command \"" + name + "\" not found", "ERROR");

        return null;
    },

    checkUtilsAvailable: function(utils) {
        var paths = {};
        for (var i = 0; i < utils.length; i++) {
            var path;
            if (this.utils[utils[i]] === undefined) {
                path = this.findPathToExec(utils[i]);
                this.utils[utils[i]] = path;
            }
            else {
                path = this.utils[utils[i]];
            }
            if (path == null)
                return null;
            paths[utils[i]] = path;
        }
        return paths;
    },

    checkPresenceGnomeShell: function() {
        this.log("Start checking DE", "DEBUG");

        var path = this.checkUtilsAvailable(["pidof"]);

        if (path.pidof) {
            var exitValue = HTitleUtilsPrivate.execute(path.pidof, ["gnome-shell"]);
            return (exitValue == 1 ? 1 : 0);
        }
        else {
            this.log("pidof doesn't exist", "ERROR");
            return 2;
        }
    },

    /* ::::: Native window ::::: */

    changeWindowProperty: function(window, mode, action) {
        var X11 = Libs.open("X11");
        var Gdk = Libs.open("Gdk", HTitleShare.gtkVersion, X11);

        /* Get native window */
        var base_window = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation)
                                .QueryInterface(Ci.nsIDocShellTreeItem)
                                .treeOwner
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .nsIBaseWindow;
        var native_handle = base_window.nativeHandle;

        var gdk_window = new Gdk.GdkWindow.ptr(ctypes.UInt64(native_handle));
        gdk_window = Gdk.Window.get_toplevel(gdk_window);

        var gdk_display = Gdk.Display.get_default();
        var x11_display = Gdk.X11Display.get_xdisplay(gdk_display);
        if (HTitleShare.gtkVersion == 3) {
            var x11_window = Gdk.X11Window.get_xid(gdk_window);
        }
        else {
            var x11_window = Gdk.X11Window.get_xid(ctypes.cast(gdk_window, Gdk.GdkDrawable.ptr));
        }

        //Gdk.Window.hide(gdk_window);
        if (mode == "always") {
            Gdk.Window.set_decorations(gdk_window, (action == "set") ? Gdk.GDK_DECOR_BORDER : Gdk.GDK_DECOR_ALL);
        }
        else {
            if (HTitleShare.gtkVersion == 3) {
                Gdk.X11Window.set_hide_titlebar_when_maximized(gdk_window, (action == "set"));
            }
            else {
                let x11_property = Gdk.x11_get_xatom_by_name_for_display(gdk_display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED");
                if (action == "set") {
                    // let t = new Uint8Array([1]);
                    // let x11_data = ctypes.uint8_t.ptr(t);
                    let t = new Uint32Array([1]);
                    let x11_data = ctypes.uint32_t.ptr(t);
                    X11.XChangeProperty(x11_display, x11_window, x11_property, X11.XA_CARDINAL, 32, X11.PropModeReplace, x11_data, 1);
                }
                else {
                    X11.XDeleteProperty(x11_display, x11_window, x11_property);
                }
            }
        }
        //Gdk.Window.show(gdk_window);

        Libs.close(Gdk);
        Libs.close(X11);
    },

    setWindowProperty: function(window, mode) {
        try {
            this.changeWindowProperty(window, mode, "set");
        } catch (e) {
            return -1;
        }
        return 0;
    },

    removeWindowProperty: function(window, mode) {
        try {
            this.changeWindowProperty(window, mode, "remove");
        } catch (e) {
            return -1;
        }
        return 0;
    },

    lowerWindow: function(window) {
        var Gdk = Libs.open("Gdk", HTitleShare.gtkVersion);
        var base_window = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation)
                                .QueryInterface(Ci.nsIDocShellTreeItem)
                                .treeOwner
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .nsIBaseWindow;
        var native_handle = base_window.nativeHandle;
        var gdk_window = new Gdk.GdkWindow.ptr(ctypes.UInt64(native_handle));
        gdk_window = Gdk.Window.get_toplevel(gdk_window);
        Gdk.Window.lower(gdk_window);
        Libs.close(Gdk);
    },

    /* ::::: CSS stylesheets ::::: */

    loadStyle: function(name) {
        var sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
        var io = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
        var uri = io.newURI("chrome://htitle/skin/" + name + ".css", null, null);
        if (!sss.sheetRegistered(uri, sss.USER_SHEET))
            sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
    },

    unloadStyle: function(name) {
        var sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
        var io = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);
        var uri = io.newURI("chrome://htitle/skin/" + name + ".css", null, null);
        if (sss.sheetRegistered(uri, sss.USER_SHEET))
            sss.unregisterSheet(uri, sss.USER_SHEET);
    },

    /* ::::: Preferences ::::: */

    getWindowControlsLayout: function() {
        var layout = ":close"; // It's default for GNOME 3

        if (!this.prefs.getBoolPref("window_controls.get_layout_by_gsettings"))
            return layout;

        try {
            var gsettings = Cc["@mozilla.org/gsettings-service;1"]
                              .getService(Ci.nsIGSettingsService);
        } catch(e) {
            this.log("GSettings isn't available", "WARNING");
            return layout;
        }

        var button_layout;
        var keys = ["org.gnome.shell.overrides", "org.gnome.desktop.wm.preferences"];
        for (let i=0; i<keys.length; i++) {
            try {
                button_layout = gsettings.getCollectionForSchema(keys[i])
                                         .getString("button-layout");
                this.log(keys[i] + ".button-layout = '" + button_layout + "'", "DEBUG");
                break;
            } catch(e) {
                continue;
            }
        }

        if (!button_layout) {
            this.log("Cann't get value from GSettings", "WARNING");
            return layout;
        }
        else if (/^([a-zA-Z0-9:,]*)$/.test(button_layout)) {
            layout = button_layout;
        }
        return layout;
    },

    getTitlebarActions: function() {
        var actions = {double: "toggle-maximize",
                       middle: "lower",
                       right:  "menu"}; // It's default for GNOME 3

        if (!this.prefs.getBoolPref("titlebar.get_actions_by_gsettings"))
            return actions;

        try {
            let gsettings = Cc["@mozilla.org/gsettings-service;1"]
                              .getService(Ci.nsIGSettingsService)
                              .getCollectionForSchema("org.gnome.desktop.wm.preferences");

            actions.double = gsettings.getString("action-double-click-titlebar");
            actions.middle = gsettings.getString("action-middle-click-titlebar");
            actions.right = gsettings.getString("action-right-click-titlebar");

            this.log("org.gnome.desktop.wm.preferences.action-double-click-titlebar = '" + actions.double + "'", "DEBUG");
            this.log("org.gnome.desktop.wm.preferences.action-middle-click-titlebar = '" + actions.middle + "'", "DEBUG");
            this.log("org.gnome.desktop.wm.preferences.action-right-click-titlebar = '" + actions.right + "'", "DEBUG");
        } catch(e) {
            this.log("GSettings isn't available", "WARNING");
            return actions;
        }

        return actions;
    },

    /* ::::: Logging ::::: */

    log: function(message, level="ERROR") {
        if (HTitleShare.debug == false && level == "DEBUG")
            return;

        var console = Cc["@mozilla.org/consoleservice;1"]
                        .getService(Ci.nsIConsoleService);

        var flag;
        switch (level) {
            case "ERROR":
                flag = 0;
                break;
            case "WARNING":
                flag = 1;
                break;
            default:
                flag = 4;
        }

        if (flag == 4) {
            console.logStringMessage("HTitle DEBUG: " + message);
        }
        else {
            var console_message = Cc["@mozilla.org/scripterror;1"]
                                    .createInstance(Ci.nsIScriptError);
            console_message.init(message, "HTitle", null, null, null, flag, null);
            console.logMessage(console_message);
        }
    },
}

HTitleUtils.init();
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

// ************************************************************************************************
// Constants

const CLASS_ID = Components.ID("{9589DC0D-9709-4578-883E-D393452B3611}");
const CLASS_NAME = "Firebug Annotation Service";
const CONTRACT_ID = "@joehewitt.com/firebug-annotation-service;1";

var EXPORTED_SYMBOLS = ["annotationService"];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);

// ************************************************************************************************
// Annotation service implementation

var FBTrace = null;

/**
 * @class Represents an internal Firebug annotation service. This service is used to
 * annotate sites with an info whether Firebug should be activated for them or not.
 */

var annotationService =
{
    annotations: [],

    setPageAnnotation: function(uri, value)
    {
        if (FBTrace.DBG_ANNOTATIONS)
            FBTrace.sysout("AnnotationService.setPageAnnotation; " + value + ", " + uri.spec);

        this.annotations[uri.spec] = value;
    },

    getPageAnnotation: function(uri)
    {
        return this.annotations[uri.spec];
    },

    pageHasAnnotation: function(uri)
    {
        return this.annotations[uri.spec] ? true : false;
    },

    removePageAnnotation: function(uri)
    {
        if (FBTrace.DBG_ANNOTATIONS)
            FBTrace.sysout("AnnotationService.removePageAnnotation; " + uri.spec);

        delete this.annotations[uri.spec];
    },

    getAnnotations: function()
    {
        return this.annotations;
    },

    clear: function()
    {
        this.annotations = [];
    },

    initialize: function()
    {
        Components.utils.import("resource://firebug/firebug-trace-service.js");
        FBTrace = traceConsoleService.getTracer("extensions.firebug");

        // Get annotation file stored within the profile directory.
        this.file = dirService.get("ProfD", Ci.nsIFile);
        this.file.append("firebug");
        this.file.append("annotations.json");

        // Load annotations.
        this.loadAnnotations();
    },

    // Persistence
    loadAnnotations: function()
    {
        try
        {
            this.clear();

            if (!this.file.exists())
            {
                this.file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
                if (FBTrace.DBG_ANNOTATIONS)
                    FBTrace.sysout("AnnotationService.loadAnnotations; Annotations file created " +
                        this.file.path);
                return;
            }

            var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
                .createInstance(Ci.nsIFileInputStream);
            var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
                .createInstance(Ci.nsIConverterInputStream);

            // loadAnnotations input stream.
            inputStream.init(this.file, 0x01 | 0x08, 0666, 0); // read, create
            cstream.init(inputStream, "UTF-8", 0, 0);

            // Load annotations.
            var json = "";
            var data = {};
            while (cstream.readString(-1, data) != 0)
                json += data.value;

            if (!json.length)
                return;

            var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
            var arr = nativeJSON.decode(json);
            if (!arr)
                return;

            // Convert to map for faster lookup.
            for (var i=0; i<arr.length; i++)
                this.annotations[arr[i].uri] = arr[i].value;

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.loadAnnotations; Annotations loaded from " +
                    this.file.path, arr);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.loadAnnotations; EXCEPTION", err);
        }
    },

    flush: function()
    {
        try
        {
            // Initialize output stream.
            var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
                .createInstance(Ci.nsIFileOutputStream);
            outputStream.init(this.file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate

            // Convert data to JSON.
            var arr = [];
            for (var uri in this.annotations)
                arr.push({
                    uri: uri,
                    value: this.annotations[uri]
                });

            var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
            var jsonString = nativeJSON.encode(arr);

            // Store annotations.
            outputStream.write(jsonString, jsonString.length);
            outputStream.close();

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.loadAnnotations; Annotations stored to " +
                    this.file.path, jsonString);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.flush; EXCEPTION", err);
        }
    },

    /* nsISupports */
    QueryInterface: function(iid)
    {
        if (iid.equals(Ci.nsISupports))
            return this;

        throw Cr.NS_ERROR_NO_INTERFACE;
    }
};

annotationService.initialize();<commit_msg>Issue 4058: 	clear All Annotations does not persist<commit_after>/* See license.txt for terms of usage */

// ************************************************************************************************
// Constants

const CLASS_ID = Components.ID("{9589DC0D-9709-4578-883E-D393452B3611}");
const CLASS_NAME = "Firebug Annotation Service";
const CONTRACT_ID = "@joehewitt.com/firebug-annotation-service;1";

var EXPORTED_SYMBOLS = ["annotationService"];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const dirService = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);

// ************************************************************************************************
// Annotation service implementation

var FBTrace = null;

/**
 * @class Represents an internal Firebug annotation service. This service is used to
 * annotate sites with an info whether Firebug should be activated for them or not.
 */

var annotationService =
{
    annotations: [],

    setPageAnnotation: function(uri, value)
    {
        if (FBTrace.DBG_ANNOTATIONS)
            FBTrace.sysout("AnnotationService.setPageAnnotation; " + value + ", " + uri.spec);

        this.annotations[uri.spec] = value;
    },

    getPageAnnotation: function(uri)
    {
        return this.annotations[uri.spec];
    },

    pageHasAnnotation: function(uri)
    {
        return this.annotations[uri.spec] ? true : false;
    },

    removePageAnnotation: function(uri)
    {
        if (FBTrace.DBG_ANNOTATIONS)
            FBTrace.sysout("AnnotationService.removePageAnnotation; " + uri.spec);

        delete this.annotations[uri.spec];
    },

    getAnnotations: function()
    {
        return this.annotations;
    },

    clear: function()
    {
        this.annotations = [];
        this.flush();
    },

    initialize: function()
    {
        Components.utils.import("resource://firebug/firebug-trace-service.js");
        FBTrace = traceConsoleService.getTracer("extensions.firebug");

        // Get annotation file stored within the profile directory.
        this.file = dirService.get("ProfD", Ci.nsIFile);
        this.file.append("firebug");
        this.file.append("annotations.json");

        // Load annotations.
        this.loadAnnotations();
    },

    // Persistence
    loadAnnotations: function()
    {
        try
        {
            this.clear();

            if (!this.file.exists())
            {
                this.file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
                if (FBTrace.DBG_ANNOTATIONS)
                    FBTrace.sysout("AnnotationService.loadAnnotations; Annotations file created " +
                        this.file.path);
                return;
            }

            var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]
                .createInstance(Ci.nsIFileInputStream);
            var cstream = Cc["@mozilla.org/intl/converter-input-stream;1"]
                .createInstance(Ci.nsIConverterInputStream);

            // loadAnnotations input stream.
            inputStream.init(this.file, 0x01 | 0x08, 0666, 0); // read, create
            cstream.init(inputStream, "UTF-8", 0, 0);

            // Load annotations.
            var json = "";
            var data = {};
            while (cstream.readString(-1, data) != 0)
                json += data.value;

            if (!json.length)
                return;

            var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
            var arr = nativeJSON.decode(json);
            if (!arr)
                return;

            // Convert to map for faster lookup.
            for (var i=0; i<arr.length; i++)
                this.annotations[arr[i].uri] = arr[i].value;

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.loadAnnotations; Annotations loaded from " +
                    this.file.path, arr);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.loadAnnotations; EXCEPTION", err);
        }
    },

    flush: function()
    {
        try
        {
            // Initialize output stream.
            var outputStream = Cc["@mozilla.org/network/file-output-stream;1"]
                .createInstance(Ci.nsIFileOutputStream);
            outputStream.init(this.file, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate

            // Convert data to JSON.
            var arr = [];
            for (var uri in this.annotations)
                arr.push({
                    uri: uri,
                    value: this.annotations[uri]
                });

            var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
            var jsonString = nativeJSON.encode(arr);

            // Store annotations.
            outputStream.write(jsonString, jsonString.length);
            outputStream.close();

            if (FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.loadAnnotations; Annotations stored to " +
                    this.file.path, jsonString);
        }
        catch (err)
        {
            if (FBTrace.DBG_ERRORS || FBTrace.DBG_ANNOTATIONS)
                FBTrace.sysout("AnnotationService.flush; EXCEPTION", err);
        }
    },

    /* nsISupports */
    QueryInterface: function(iid)
    {
        if (iid.equals(Ci.nsISupports))
            return this;

        throw Cr.NS_ERROR_NO_INTERFACE;
    }
};

annotationService.initialize();<|endoftext|>


<commit_before>/**
 * Copyright (c), 2013-2014 IMD - International Institute for Management Development, Switzerland.
 *
 * See the file license.txt for copying permission.
 */

define([
    'Underscore',
    'jquery',
    'ui/Mask',
    'util/Event',
    'util/ViewportRelative',
    'text!resources/menu.tpl'
], function (_, $, Mask, Event, ViewportRelative, menuTpl) {
    'use strict';

    var menuTplFunc = _.template(menuTpl);

    var PopupMenu = function (menuDef, callback, stateFunc, isMultiSelect) {
        this.menuDef = menuDef;
        this.callback = callback;
        this.stateFunc = stateFunc;
        this.isMultiSelect = isMultiSelect;
        this.state = [];
    };

    PopupMenu.prototype.MENU_ITEM_SELECTOR = '.qk_popup_menu_item';
    PopupMenu.prototype.HIDDEN_CSS = 'qk_invisible';

    PopupMenu.prototype.updateUiState = function (markup, state) {
        if (state) {
            markup.find('.qk_popup_menu_item[data-value="' + state + '"] .qk_popup_menu_item_state').toggleClass(this.HIDDEN_CSS);
        }
    };

    PopupMenu.prototype.updateState = function (state, newValue) {
        var index = state.indexOf(newValue),
            result = {};
        if (index >= 0) {
            state.splice(index, 1);
            result.deselected = newValue;
        } else {
            if (this.isMultiSelect) {
                state.push(newValue);
            } else {
                result.deselected = state[0];
                state[0] = newValue;
            }
            result.selected = newValue;
        }
        return result;
    };

    PopupMenu.prototype.onSelect = function (event) {
        var menuItem = $(event.target).closest(this.MENU_ITEM_SELECTOR),
            id = menuItem.attr('data-value'),
            selectedDef = _.find(this.menuDef, function (def) {
                return def.value === id;
            }),
            newValue = selectedDef.value,
            delta = {};
        event.preventDefault(); // stops the menu being focused
        if (newValue !== 'close') {
            delta = this.updateState(this.state, newValue);
            this.updateUiState(this.menu, delta.selected);
            this.updateUiState(this.menu, delta.deselected);
        }
        this.callback(delta.selected, delta.deselected, this.state);
        if (!this.isMultiSelect || newValue === 'close') {
            this.hide();
        }
    };

    PopupMenu.prototype.applyState = function (markup, menuState) {
        var HIDDEN_CSS = this.HIDDEN_CSS;
        markup.find('.qk_popup_menu_item').each(function () {
            var itemEl = $(this),
                stateEl = itemEl.find('.qk_popup_menu_item_state'),
                id = itemEl.attr('data-value'),
                func = menuState.indexOf(id) >= 0 ? stateEl.removeClass : stateEl.addClass;
            func.call(stateEl, HIDDEN_CSS);
        });
    };

    PopupMenu.prototype.createMenu = function (def) {
        var markup = $(menuTplFunc({options: def}));
        markup.on(Event.eventName('start'), this.MENU_ITEM_SELECTOR, this.onSelect.bind(this));
        markup.find('.qk_popup_menu_item_state').addClass(this.HIDDEN_CSS);
        return markup;
    };

    PopupMenu.prototype.doShowMenu = function (menu, x, y) {
        var vpRight = document.documentElement.clientWidth || window.innerWidth || 0,
            vpBottom = document.documentElement.clientHeight || window.height || 0,
            hScroll = document.documentElement.scrollLeft || document.body.scrollLeft || 0,
            vScroll = document.documentElement.scrollTop || document.body.scrollTop || 0;
        menu.css({
            top: -500,
            left: -500
        });
        menu.removeClass('qk_hidden'); // so that the menu has a width
        if (x + menu.outerWidth() > vpRight + hScroll) {
            x -= menu.outerWidth();
        }
        if (y + menu.outerHeight() > vpBottom + vScroll) {
            y -= menu.outerHeight();
        }
        menu.css({
            top: y,
            left: x
        });
        this.vpMenu.adjust();
    };

    PopupMenu.prototype.show = function (x, y) {
        var menu = this.menu;
        if (!menu) {
            this.menu = this.createMenu(this.menuDef);
            menu = this.menu;
            this.mask = Mask.create(this.hide.bind(this), 0);
            menu.appendTo('body');
            this.vpMenu = ViewportRelative.create(menu, {
                top: y
            });
        }
        this.state = (this.stateFunc && this.stateFunc(this.menuDef)) || this.state;
        this.applyState(menu, this.state);
        this.mask.show();
        this.doShowMenu(menu, x, y);
    };

    PopupMenu.prototype.hide = function () {
        this.menu.addClass('qk_hidden');
        this.mask.hide();
        this.state = [];
    };

    PopupMenu.prototype.destroy = function () {
        this.menu.remove();
    };

    function create(menuDef, callback, stateFunc, isMultiSelect) {
        return new PopupMenu(menuDef, callback, stateFunc, isMultiSelect);
    }

    return {
        create: create
    };
});
<commit_msg>Pass the menu definitions to the onSelect callback. Useful for cases where a simple function isn't enough to handle the onSelect.<commit_after>/**
 * Copyright (c), 2013-2014 IMD - International Institute for Management Development, Switzerland.
 *
 * See the file license.txt for copying permission.
 */

define([
    'Underscore',
    'jquery',
    'ui/Mask',
    'util/Event',
    'util/ViewportRelative',
    'text!resources/menu.tpl'
], function (_, $, Mask, Event, ViewportRelative, menuTpl) {
    'use strict';

    var menuTplFunc = _.template(menuTpl);

    var PopupMenu = function (menuDef, callback, stateFunc, isMultiSelect) {
        this.menuDef = menuDef;
        this.callback = callback;
        this.stateFunc = stateFunc;
        this.isMultiSelect = isMultiSelect;
        this.state = [];
    };

    PopupMenu.prototype.MENU_ITEM_SELECTOR = '.qk_popup_menu_item';
    PopupMenu.prototype.HIDDEN_CSS = 'qk_invisible';

    PopupMenu.prototype.updateUiState = function (markup, state) {
        if (state) {
            markup.find('.qk_popup_menu_item[data-value="' + state + '"] .qk_popup_menu_item_state').toggleClass(this.HIDDEN_CSS);
        }
    };

    PopupMenu.prototype.updateState = function (state, newValue) {
        var index = state.indexOf(newValue),
            result = {};
        if (index >= 0) {
            state.splice(index, 1);
            result.deselected = newValue;
        } else {
            if (this.isMultiSelect) {
                state.push(newValue);
            } else {
                result.deselected = state[0];
                state[0] = newValue;
            }
            result.selected = newValue;
        }
        return result;
    };

    PopupMenu.prototype.onSelect = function (event) {
        var menuItem = $(event.target).closest(this.MENU_ITEM_SELECTOR),
            id = menuItem.attr('data-value'),
            selectedDef = _.find(this.menuDef, function (def) {
                return def.value === id;
            }),
            newValue = selectedDef.value,
            delta = {};
        event.preventDefault(); // stops the menu being focused
        if (newValue !== 'close') {
            delta = this.updateState(this.state, newValue);
            this.updateUiState(this.menu, delta.selected);
            this.updateUiState(this.menu, delta.deselected);
        }
        this.callback(delta.selected, delta.deselected, this.state, this.menuDef);
        if (!this.isMultiSelect || newValue === 'close') {
            this.hide();
        }
    };

    PopupMenu.prototype.applyState = function (markup, menuState) {
        var HIDDEN_CSS = this.HIDDEN_CSS;
        markup.find('.qk_popup_menu_item').each(function () {
            var itemEl = $(this),
                stateEl = itemEl.find('.qk_popup_menu_item_state'),
                id = itemEl.attr('data-value'),
                func = menuState.indexOf(id) >= 0 ? stateEl.removeClass : stateEl.addClass;
            func.call(stateEl, HIDDEN_CSS);
        });
    };

    PopupMenu.prototype.createMenu = function (def) {
        var markup = $(menuTplFunc({options: def}));
        markup.on(Event.eventName('start'), this.MENU_ITEM_SELECTOR, this.onSelect.bind(this));
        markup.find('.qk_popup_menu_item_state').addClass(this.HIDDEN_CSS);
        return markup;
    };

    PopupMenu.prototype.doShowMenu = function (menu, x, y) {
        var vpRight = document.documentElement.clientWidth || window.innerWidth || 0,
            vpBottom = document.documentElement.clientHeight || window.height || 0,
            hScroll = document.documentElement.scrollLeft || document.body.scrollLeft || 0,
            vScroll = document.documentElement.scrollTop || document.body.scrollTop || 0;
        menu.css({
            top: -500,
            left: -500
        });
        menu.removeClass('qk_hidden'); // so that the menu has a width
        if (x + menu.outerWidth() > vpRight + hScroll) {
            x -= menu.outerWidth();
        }
        if (y + menu.outerHeight() > vpBottom + vScroll) {
            y -= menu.outerHeight();
        }
        menu.css({
            top: y,
            left: x
        });
        this.vpMenu.adjust();
    };

    PopupMenu.prototype.show = function (x, y) {
        var menu = this.menu;
        if (!menu) {
            this.menu = this.createMenu(this.menuDef);
            menu = this.menu;
            this.mask = Mask.create(this.hide.bind(this), 0);
            menu.appendTo('body');
            this.vpMenu = ViewportRelative.create(menu, {
                top: y
            });
        }
        this.state = (this.stateFunc && this.stateFunc(this.menuDef)) || this.state;
        this.applyState(menu, this.state);
        this.mask.show();
        this.doShowMenu(menu, x, y);
    };

    PopupMenu.prototype.hide = function () {
        this.menu.addClass('qk_hidden');
        this.mask.hide();
        this.state = [];
    };

    PopupMenu.prototype.destroy = function () {
        this.menu.remove();
    };

    function create(menuDef, callback, stateFunc, isMultiSelect) {
        return new PopupMenu(menuDef, callback, stateFunc, isMultiSelect);
    }

    return {
        create: create
    };
});
<|endoftext|>


<commit_before>module.exports = function (grunt) {

    var amberc = require('../lib/amberc');

    /**
     A full example entry for a Gruntfile.js is available below.
     Please note that the verbose level is either specified globally
     or on a target specific level.
     However, it can additionally be triggered on the commandline by
     adding the '-v' or '--verbose' flag.

     Example Gruntfile.js entry:

     amberc: {
       options: {
         amber_dir: process.cwd(),                // REQUIRED
         verbose: true                            // optional
       },
       helloWorld: {
         // this 'options' object is optional as well as all parameters inside it
         // they can be used to override the global 'options'
         options: {
           verbose: true
         },
         src: ['projects/HelloWorld/src/HelloWorld.st'], // REQUIRED
         outputDir: 'projects/HelloWorld/src',  // optional
         libraries: 'Web',                       // optional
         jsGlobals: ['global1', 'global2'],     // optional
         amdNamespace: 'MyNamespace',          // optional (default: 'amber')
       },
     },

     */
    grunt.registerMultiTask('amberc', 'Compile Smalltalk files with the amberc compiler', function () {
        // mark task as async task
        var done = this.async();

        var options = this.options({
            amber_dir: undefined,
            library_dirs: [],
            verbose: grunt.option('verbose') || false
        });
        this.data.verbose = options.verbose;
        this.data.library_dirs = options.library_dirs;

        // mark required properties
        this.requiresConfig('amberc.options.amber_dir');
        // raise error on missing source files
        if (this.filesSrc.length === 0) {
            grunt.fail.fatal('No source files to compile or link.');
        }

        // create and initialize amberc
        var compiler = new amberc.Compiler(grunt.config('amberc.options.amber_dir'));

        // generate the amberc configuration out of the given target properties
        var configuration = generateCompilerConfiguration(this.data, this.filesSrc);

        // run the compiler and call the async callback once finished
        var self = this;
        compiler.main(configuration, function () {
            // signal that task has finished
            done();
        });
    });

    function generateCompilerConfiguration(data, sourceFiles) {
        var configuration = amberc.createDefaultConfiguration();

        if (data.libraries != null) {
            configuration.load = data.libraries;
        }
        if (sourceFiles != null) {
            configuration.stFiles = sourceFiles;
        }
        if (data.amd_namespace != null) {
            configuration.amdNamespace = data.amd_namespace;
        }
        if (data.output_dir != null) {
            configuration.outputDir = data.output_dir;
        }
        if (data.jsGlobals != null) {
            configuration.jsGlobals.push.apply(configuration.jsGlobals, data.jsGlobals);
        }
        if (data.verbose != null) {
            configuration.verbose = data.verbose;
        }
        return configuration;
    }
};
<commit_msg>devkit: fix example in amberc grunt task<commit_after>module.exports = function (grunt) {

    var amberc = require('../lib/amberc');

    /**
     A full example entry for a Gruntfile.js is available below.
     Please note that the verbose level is either specified globally
     or on a target specific level.
     However, it can additionally be triggered on the commandline by
     adding the '-v' or '--verbose' flag.

     Example Gruntfile.js entry:

     amberc: {
       options: {
         amber_dir: process.cwd(),                // REQUIRED
         verbose: true                            // optional
       },
       helloWorld: {
         // this 'options' object is optional as well as all parameters inside it
         // they can be used to override the global 'options'
         options: {
           verbose: true
         },
         src: ['projects/HelloWorld/src/HelloWorld.st'], // REQUIRED
         output_dir: 'projects/HelloWorld/src',  // optional
         libraries: 'Web',                       // optional
         jsGlobals: ['global1', 'global2'],     // optional
         amd_namespace: 'MyNamespace',          // optional (default: 'amber')
       },
     },

     */
    grunt.registerMultiTask('amberc', 'Compile Smalltalk files with the amberc compiler', function () {
        // mark task as async task
        var done = this.async();

        var options = this.options({
            amber_dir: undefined,
            library_dirs: [],
            verbose: grunt.option('verbose') || false
        });
        this.data.verbose = options.verbose;
        this.data.library_dirs = options.library_dirs;

        // mark required properties
        this.requiresConfig('amberc.options.amber_dir');
        // raise error on missing source files
        if (this.filesSrc.length === 0) {
            grunt.fail.fatal('No source files to compile or link.');
        }

        // create and initialize amberc
        var compiler = new amberc.Compiler(grunt.config('amberc.options.amber_dir'));

        // generate the amberc configuration out of the given target properties
        var configuration = generateCompilerConfiguration(this.data, this.filesSrc);

        // run the compiler and call the async callback once finished
        var self = this;
        compiler.main(configuration, function () {
            // signal that task has finished
            done();
        });
    });

    function generateCompilerConfiguration(data, sourceFiles) {
        var configuration = amberc.createDefaultConfiguration();

        if (data.libraries != null) {
            configuration.load = data.libraries;
        }
        if (sourceFiles != null) {
            configuration.stFiles = sourceFiles;
        }
        if (data.amd_namespace != null) {
            configuration.amdNamespace = data.amd_namespace;
        }
        if (data.output_dir != null) {
            configuration.outputDir = data.output_dir;
        }
        if (data.jsGlobals != null) {
            configuration.jsGlobals.push.apply(configuration.jsGlobals, data.jsGlobals);
        }
        if (data.verbose != null) {
            configuration.verbose = data.verbose;
        }
        return configuration;
    }
};
<|endoftext|>


<commit_before>(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "Plugins": {
        "DistinctMenu": DistinctMenu
       }
    }
  });
  function DistinctMenu(options){
    var _grid;
    var _self = this;
    var _handler = new Slick.EventHandler();
    var _defaults = {
      command: 'filter',            //headerMenuItem command key
      headerMenu: false,            //headerMenuPlugin instance
      columns: [],                  //columns object which was used in headerMenuPlugin
      url: '/items',                //default url for query distinct arrays (JSON format)
      urlParameters: null,          //extra parameters for url string
      exclude: [],                  //exclude column id's
      doUrl: doUrl,                 //function that generate url.        f(field, condition)
      doCondition: doCondition,     //function that generate conditions. f(field, value){
      doFilter: doFilter,           //function that fetch data           f(field, condition)
      onReady: onReady,             //function when menus are ready      f(columns) -> grid.setColumns(columns); grid.render();
      selectIcon: "/js/vendor/SlickGrid/images/tick.png",
      condition: {$and: []}         //internal condition
    };

    function init(grid) {
      //Init plugin
      options = $.extend(true, {}, _defaults, options);
      _grid = grid;
      condition(false);
      options.headerMenu.onCommand.subscribe(onCommand);
      console.log('distinctMenu initialized');
    }

    // Condition handler
    function condition(field, condition, or){
      var obj = {}
      if( field === false ){
        options.condition['$and'] = [];
        for (var i=1;i<=options.columns.length;i++){
          options.condition['$and'].push({});
        }
      } else if(field && condition ) {
        var col = getColumnIndexByField(field);
        if( or ) {
          if( !options.condition['$and'][col]['$or'] ){
            var org = JSON.stringify(options.condition['$and'][col]);
            options.condition['$and'][col] = {};
            options.condition['$and'][col]['$or'] = [ JSON.parse(org) ];
          }
          options.condition['$and'][col]['$or'].push( condition );
        } else {
          options.condition['$and'][col] = condition;
        }
      }
      function cleanCondition(myObjects)
      {
        return {'$and': myObjects['$and'].filter(function (val) {
            return Object.keys(val).length!=0;
        })};
      }
      return cleanCondition(options.condition);
    }
    function getColumnIndexByField(field)
    {
      var i;
      for(i=0;i<options.columns.length;i++){
        if( options.columns[i].field == field ) return i;
      } return;
    }
    function onCommand(e, args) {

      if( args.command == options.command ){
        //options.exclude = args.column.field
        setSelection(args.column, args.item, e.ctrlKey);
        condition(args.column.field, args.item.condition, e.ctrlKey);
        options.doFilter( args.column.field, condition() );
      } else if( value.command == 'filter' ) {
        setSelection(args.column, args.item, e.ctrlKey);
        condition(args.column.field, args.item.condition, e.ctrlKey);
        options.doFilter( args.column.field, condition() );
      }
    }
    function destroy() {
      _handler.unsubscribeAll();
      console.log('distinctMenu destroyed');
    }
    function setSelection(column, item, or){
      $.extend(true, column, {header: {menu: {items: []}}})
      var items = column.header.menu.items;
      items.forEach( function( value ) {
        if( value.command == options.command ){
          //belong to distinct menus
          if( value.title === item.title ){
            value.iconImage = options.selectIcon;
          } else if(!or){
            value.iconImage = false;
          }
        }
      });
    }
    function onReady(columns){
      _grid.setColumns(columns);
      _grid.render();
      console.log('ready');
    }
    function doUrl(field, condition){
      if( typeof(condition)=='object'){
        condition = JSON.stringify(condition);
      }
      var url = options.url+'?t=distinct&f='+field;
      if( condition ) url +='&q='+condition;
      return url;
    }

    function doCondition(field, value){
      var cond = {}
      cond[field] = value;
      return cond;
    }

    var updateDistinct = function(items, i, callback){

      if( i < items.length ) {
        if( options.exclude.indexOf(items[i].id)>=0 || items[i].name[0]==='<' ) {
          updateDistinct(items, i+1, callback);
          return;
        }
        var url = false;
        if( typeof(options.doUrl)=='function'){
          url = options.doUrl(items[i].field, options.condition);
        }else {
          console.error('doUrl function missing!');
          //doError({error: 'doUrl function missing!');
          return;
        }
        console.log(url); //debug print
        $.getJSON( url, $.extend({json: true}, options.urlParameters)
        ).done(function( json  ) {
            if( json.length ){
              setColumnMenuFilters(i, items[i], json);
            } else {
              console.error('invalid response format');
            }
            updateDistinct(items, i+1, callback);
        }).fail(function(jqxhr, textStatus, error) {
          var err = textStatus + ", " + error;
          console.error( "Request Failed: " + err );
          updateDistinct(items, i+1, callback);
        });
      } else {
        callback(options.columns);
      }
    }
    function updateMenus(){
      updateDistinct(options.columns, 0, options.onReady);
    }
    function doFilter(field, condition){
      console.log('Filteringing with condition: '+JSON.stringify(condition) );
    }
    function removeFunction (myObjects,prop,valu)
    {
      return myObjects.filter(function (val) {
          return val[prop] !== valu;
      });
    }
    function setColumnMenuFilters(coll, item, distinct){
      console.log('setColumnMenuFilters: '+distinct);
      $.extend(true, options.columns[coll], {header: {menu: {items: []}}})

      //remove old items (only where command is "distinct")
      var items = options.columns[coll].header.menu.items;
      options.columns[coll].header.menu.items = removeFunction(items, 'command', options.command);
      var items = options.columns[coll].header.menu.items;
      //push "all" button
      items.push( {
        command: options.command,
        title: 'All',
        condition: {},
        iconImage: options.selectIcon,
      });
      //push individual items
      distinct.forEach( function( value ) {
        console.log('addItem: '+value);
        items.push({
          command: options.command,
          title: value,
          condition: options.doCondition(item.field, value),
        });
      });

    }
    $.extend(this, {
      "init": init,
      "destroy": destroy,
      "update": updateMenus,
      //"onBeforeMenuShow": new Slick.Event(),
      //"onCommand": new Slick.Event()
    });
  }
})(jQuery);
<commit_msg>bugfix related to filter -command<commit_after>(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "Plugins": {
        "DistinctMenu": DistinctMenu
       }
    }
  });
  function DistinctMenu(options){
    var _grid;
    var _self = this;
    var _handler = new Slick.EventHandler();
    var _defaults = {
      command: 'filter',            //headerMenuItem command key
      headerMenu: false,            //headerMenuPlugin instance
      columns: [],                  //columns object which was used in headerMenuPlugin
      url: '/items',                //default url for query distinct arrays (JSON format)
      urlParameters: null,          //extra parameters for url string
      exclude: [],                  //exclude column id's
      doUrl: doUrl,                 //function that generate url.        f(field, condition)
      doCondition: doCondition,     //function that generate conditions. f(field, value){
      doFilter: doFilter,           //function that fetch data           f(field, condition)
      onReady: onReady,             //function when menus are ready      f(columns) -> grid.setColumns(columns); grid.render();
      selectIcon: "/js/vendor/SlickGrid/images/tick.png",
      condition: {$and: []}         //internal condition
    };

    function init(grid) {
      //Init plugin
      options = $.extend(true, {}, _defaults, options);
      _grid = grid;
      condition(false);
      options.headerMenu.onCommand.subscribe(onCommand);
      console.log('distinctMenu initialized');
    }

    // Condition handler
    function condition(field, condition, or){
      var obj = {}
      if( field === false ){
        options.condition['$and'] = [];
        for (var i=1;i<=options.columns.length;i++){
          options.condition['$and'].push({});
        }
      } else if(field && condition ) {
        var col = getColumnIndexByField(field);
        if( or ) {
          if( !options.condition['$and'][col]['$or'] ){
            var org = JSON.stringify(options.condition['$and'][col]);
            options.condition['$and'][col] = {};
            options.condition['$and'][col]['$or'] = [ JSON.parse(org) ];
          }
          options.condition['$and'][col]['$or'].push( condition );
        } else {
          options.condition['$and'][col] = condition;
        }
      }
      function cleanCondition(myObjects)
      {
        return {'$and': myObjects['$and'].filter(function (val) {
            return Object.keys(val).length!=0;
        })};
      }
      return cleanCondition(options.condition);
    }
    function getColumnIndexByField(field)
    {
      var i;
      for(i=0;i<options.columns.length;i++){
        if( options.columns[i].field == field ) return i;
      } return;
    }
    function onCommand(e, args) {

      if( args.command == options.command ){
        //options.exclude = args.column.field
        setSelection(args.column, args.item, e.ctrlKey);
        condition(args.column.field, args.item.condition, e.ctrlKey);
        options.doFilter( args.column.field, condition() );
      } else if( args.command == 'filter' ) {
        setSelection(args.column, args.item, e.ctrlKey);
        condition(args.column.field, args.item.condition, e.ctrlKey);
        options.doFilter( args.column.field, condition() );
      }
    }
    function destroy() {
      _handler.unsubscribeAll();
      console.log('distinctMenu destroyed');
    }
    function setSelection(column, item, or){
      $.extend(true, column, {header: {menu: {items: []}}})
      var items = column.header.menu.items;
      items.forEach( function( value ) {
        if( value.command == options.command ){
          //belong to distinct menus
          if( value.title === item.title ){
            value.iconImage = options.selectIcon;
          } else if(!or){
            value.iconImage = false;
          }
        }
      });
    }
    function onReady(columns){
      _grid.setColumns(columns);
      _grid.render();
      console.log('ready');
    }
    function doUrl(field, condition){
      if( typeof(condition)=='object'){
        condition = JSON.stringify(condition);
      }
      var url = options.url+'?t=distinct&f='+field;
      if( condition ) url +='&q='+condition;
      return url;
    }

    function doCondition(field, value){
      var cond = {}
      cond[field] = value;
      return cond;
    }

    var updateDistinct = function(items, i, callback){

      if( i < items.length ) {
        if( options.exclude.indexOf(items[i].id)>=0 || items[i].name[0]==='<' ) {
          updateDistinct(items, i+1, callback);
          return;
        }
        var url = false;
        if( typeof(options.doUrl)=='function'){
          url = options.doUrl(items[i].field, options.condition);
        }else {
          console.error('doUrl function missing!');
          //doError({error: 'doUrl function missing!');
          return;
        }
        console.log(url); //debug print
        $.getJSON( url, $.extend({json: true}, options.urlParameters)
        ).done(function( json  ) {
            if( json.length ){
              setColumnMenuFilters(i, items[i], json);
            } else {
              console.error('invalid response format');
            }
            updateDistinct(items, i+1, callback);
        }).fail(function(jqxhr, textStatus, error) {
          var err = textStatus + ", " + error;
          console.error( "Request Failed: " + err );
          updateDistinct(items, i+1, callback);
        });
      } else {
        callback(options.columns);
      }
    }
    function updateMenus(){
      updateDistinct(options.columns, 0, options.onReady);
    }
    function doFilter(field, condition){
      console.log('Filteringing with condition: '+JSON.stringify(condition) );
    }
    function removeFunction (myObjects,prop,valu)
    {
      return myObjects.filter(function (val) {
          return val[prop] !== valu;
      });
    }
    function setColumnMenuFilters(coll, item, distinct){
      console.log('setColumnMenuFilters: '+distinct);
      $.extend(true, options.columns[coll], {header: {menu: {items: []}}})

      //remove old items (only where command is "distinct")
      var items = options.columns[coll].header.menu.items;
      options.columns[coll].header.menu.items = removeFunction(items, 'command', options.command);
      var items = options.columns[coll].header.menu.items;
      //push "all" button
      items.push( {
        command: options.command,
        title: 'All',
        condition: {},
        iconImage: options.selectIcon,
      });
      //push individual items
      distinct.forEach( function( value ) {
        console.log('addItem: '+value);
        items.push({
          command: options.command,
          title: value,
          condition: options.doCondition(item.field, value),
        });
      });

    }
    $.extend(this, {
      "init": init,
      "destroy": destroy,
      "update": updateMenus,
      //"onBeforeMenuShow": new Slick.Event(),
      //"onCommand": new Slick.Event()
    });
  }
})(jQuery);   <|endoftext|>


<commit_before>/* global window */

window.deprecationWorkflow = window.deprecationWorkflow || {};
window.deprecationWorkflow.config = {
  workflow: [
    { handler: 'silence', matchId: 'manager-capabilities.modifiers-3-13' }, //https://github.com/emberjs/ember-render-modifiers/issues/32
  ],
};
<commit_msg>Silence super noisy ember global deprecation<commit_after>/* global window */

window.deprecationWorkflow = window.deprecationWorkflow || {};
window.deprecationWorkflow.config = {
  workflow: [
    { handler: 'silence', matchId: 'manager-capabilities.modifiers-3-13' }, //https://github.com/emberjs/ember-render-modifiers/issues/32
    { handler: 'silence', matchId: 'ember-global' },
  ],
};
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var Schema = mongoose.Schema;

var Pending = new Schema({
    fileName  : String
  , Uploader  : String
  , hash      : String
});

var UserSchema = new Schema({
    mac        		: ObjectId
  , ip     			: String
  , nick      		: String
  , spaceAllocated 	: Number
  , state 			: Boolean
  , pending  		: [Pending]
  , dataUploaded 	: Number
  , dataDownloaded 	: Number
});

var Files = new Schema({
    hash	: ObjectId
  , name    : String
  , size    : String
  , users 	: [Users]
  , meta    : {
      keyword : String
  }
});

var User = mongoose.model('User', UserSchema);
var File = mongoose.model('File', FileSchema);

exports.User = User;
exports.File = File;
<commit_msg>updated schema<commit_after>var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var Schema = mongoose.Schema;

var Pending = new Schema({
    fileName  : String
  , Uploader  : String
  , hash      : String
  , transferID: Number
});

var UserSchema = new Schema({
    mac        		: ObjectId
  , ip     			: String
  , nick      		: String
  , spaceAllocated 	: Number
  , state 			: Boolean
  , pending  		: [Pending]
  , dataUploaded 	: Number
  , dataDownloaded 	: Number
});

var Files = new Schema({
    hash	: ObjectId
  , name    : String
  , size    : String
  , users 	: [Users]
  , meta    : {
      keyword : String
  }
});

var User = mongoose.model('User', UserSchema);
var File = mongoose.model('File', FileSchema);

exports.User = User;
exports.File = File;
<|endoftext|>


<commit_before>const Endless = imports.gi.Endless;
const EosKnowledge = imports.gi.EosKnowledge;
const Gio = imports.gi.Gio;

const TESTDIR = Endless.getCurrentFileDir() + '/..';
const MOCK_ARTICLE_PATH = TESTDIR + '/test-content/mexico.jsonld';

describe('Article Presenter', function () {
    let presenter;
    let view;
    let mockArticleData;
    let articleObject;
    let engine;
    let webview;

    beforeEach(function (done) {

        let file = Gio.file_new_for_path(MOCK_ARTICLE_PATH);

        let [success, data] = file.load_contents(null);
        mockArticleData = JSON.parse(data);

        articleObject = new EosKnowledge.ArticleObjectModel.new_from_json_ld(mockArticleData);

        view = new EosKnowledge.ArticlePage();
        view.connect_after('new-view-transitioned', done);

        engine = new EosKnowledge.Engine();

        presenter = new EosKnowledge.ArticlePresenter({
            article_view: view,
            engine: engine
        });
        presenter.load_article(articleObject, EosKnowledge.LoadingAnimationType.NONE);
    });

    it('can be constructed', function () {});

    it('can set title and subtitle on view', function () {
        expect(view.title).toBe(articleObject.title);

    });

    xit('can set toc section list', function () {
        let labels = [];
        for (let obj of mockArticleData['tableOfContents']) {
            if (!('hasParent' in obj)) {
                labels.push(obj['hasLabel']);
            }
        }
        expect(view.toc.section_list).toEqual(labels);
    });

    xit('emits signal when webview navigates to media object', function (done) {
        let redirect_page = '<meta http-equiv="refresh" content="0;url=media://my_media_url.jpg">';
        presenter.connect('media-object-clicked', function (widget, media_object_id) {
            expect(media_object_id).toEqual('my_media_url.jpg');
            done();
        }.bind());
        webview.load_html(redirect_page, null);
    });
});
<commit_msg>Disable the article presenter tests<commit_after>const Endless = imports.gi.Endless;
const EosKnowledge = imports.gi.EosKnowledge;
const Gio = imports.gi.Gio;

const TESTDIR = Endless.getCurrentFileDir() + '/..';
const MOCK_ARTICLE_PATH = TESTDIR + '/test-content/mexico.jsonld';

describe('Article Presenter', function () {
    let presenter;
    let view;
    let mockArticleData;
    let articleObject;
    let engine;
    let webview;

    beforeEach(function (done) {

        let file = Gio.file_new_for_path(MOCK_ARTICLE_PATH);

        let [success, data] = file.load_contents(null);
        mockArticleData = JSON.parse(data);

        articleObject = new EosKnowledge.ArticleObjectModel.new_from_json_ld(mockArticleData);

        view = new EosKnowledge.ArticlePage();
        view.connect_after('new-view-transitioned', done);

        engine = new EosKnowledge.Engine();

        presenter = new EosKnowledge.ArticlePresenter({
            article_view: view,
            engine: engine
        });
        presenter.load_article(articleObject, EosKnowledge.LoadingAnimationType.NONE);
    });

    xit('can be constructed', function () {});

    xit('can set title and subtitle on view', function () {
        expect(view.title).toBe(articleObject.title);

    });

    xit('can set toc section list', function () {
        let labels = [];
        for (let obj of mockArticleData['tableOfContents']) {
            if (!('hasParent' in obj)) {
                labels.push(obj['hasLabel']);
            }
        }
        expect(view.toc.section_list).toEqual(labels);
    });

    xit('emits signal when webview navigates to media object', function (done) {
        let redirect_page = '<meta http-equiv="refresh" content="0;url=media://my_media_url.jpg">';
        presenter.connect('media-object-clicked', function (widget, media_object_id) {
            expect(media_object_id).toEqual('my_media_url.jpg');
            done();
        }.bind());
        webview.load_html(redirect_page, null);
    });
});
<|endoftext|>


<commit_before>// More info https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
  controls: true,
  progress: true,
  history: true,
  center: true,

  transition: 'slide', // none/fade/slide/convex/concave/zoom

  // More info https://github.com/hakimel/reveal.js#dependencies
  dependencies: [
    { src: '../RevealJS/lib/js/classList.js', condition: function() { return !document.body.classList; } },
    { src: '../RevealJS/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
    { src: '../RevealJS/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
    { src: '../RevealJS/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
    { src: '../RevealJS/plugin/zoom-js/zoom.js', async: true },
    { src: '../RevealJS/plugin/notes/notes.js', async: true }
  ]
});
<commit_msg>Somehow this got lost?<commit_after>// More info https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
  controls: true,
  progress: true,
  history: true,
  center: true,

  transition: 'slide', // none/fade/slide/convex/concave/zoom

  // More info https://github.com/hakimel/reveal.js#dependencies
  dependencies: [
    { src: '../RevealJS/lib/js/classList.js', condition: function() { return !document.body.classList; } },
    { src: '../RevealJS/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
    { src: '../RevealJS/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
    { src: '../RevealJS/plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
    { src: '../RevealJS/plugin/zoom-js/zoom.js', async: true },
    { src: '../RevealJS/plugin/notes/notes.js', async: true },
    { src: '../RevealJS/plugin/math/math.js', async: true }
  ]
});
<|endoftext|>


<commit_before>import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import {
  assertTooltipRendered,
  assertTooltipContent,
  findTooltipTarget,
} from 'ember-tooltips/test-support';

module('Integration | Component | title', function(hooks) {
  setupRenderingTest(hooks);

  test(`ember-tooltip uses text instead of parent's title attribute`, async function(assert) {
    assert.expect(3);

    await render(hbs`

        {{ember-tooltip text='Here is more info' isShown=true}}

    `);

    assertTooltipRendered(assert);

    assertTooltipContent(assert, {
      contentString: 'Here is more info',
    });

    assert.equal(findTooltipTarget().attr('title'), 'Hover for more info',
      'The target should have the original title');
  });
});
<commit_msg>Added test coverage for title when hiding and showing tooltip<commit_after>import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, triggerEvent } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import {
  assertTooltipContent,
  assertTooltipNotVisible,
  assertTooltipVisible,
  findTooltipTarget,
} from 'ember-tooltips/test-support';

module('Integration | Component | title', function(hooks) {
  setupRenderingTest(hooks);

  test(`ember-tooltip uses text instead of parent's title attribute`, async function(assert) {
    assert.expect(5);

    await render(hbs`

        {{ember-tooltip text='Here is more info'}}

    `);

    const [ target ] = findTooltipTarget();

    await triggerEvent(target, 'mouseenter');

    assertTooltipVisible(assert);

    assertTooltipContent(assert, {
      contentString: 'Here is more info',
    });

    /* Reshow the tooltip and check it's content is still correct */

    await triggerEvent(target, 'mouseleave');

    assertTooltipNotVisible(assert);

    await triggerEvent(target, 'mouseenter');

    assertTooltipContent(assert, {
      contentString: 'Here is more info',
    });

    assert.equal(target.title, 'Hover for more info',
      'The target should have the original title');
  });
});
<|endoftext|>


<commit_before>/*
 * Appcelerator Titanium Mobile
 * Copyright (c) 2011-Present by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
/* eslint-env mocha */
/* global Ti */
/* eslint no-unused-expressions: "off" */
'use strict';
const should = require('./utilities/assertions'); // eslint-disable-line no-unused-vars

// skipping many test on Windows due to lack of event firing, see https://jira.appcelerator.org/browse/TIMOB-26690
describe('Titanium.UI.TabGroup', () => {
	let tabGroup;
	let tab;

	afterEach(() => {
		if (tabGroup) {
			if (tab) {
				tabGroup.removeTab(tab);
			}
			tabGroup.close();
			tabGroup = null;
		}
		tab = null;
	});

	it.windowsBroken('add Map.View to TabGroup', function (finish) {
		this.timeout(10000);

		const map = require('ti.map');
		const mapView = map.createView({ top: 0, height: '80%' });
		mapView.addEventListener('complete', () => finish());

		const win = Ti.UI.createWindow();
		win.add(mapView);

		tabGroup = Ti.UI.createTabGroup();
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		tabGroup.open();
	});

	it.ios('.tabs', () => {
		var win = Ti.UI.createWindow();
		tabGroup = Ti.UI.createTabGroup();
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		should(tabGroup.tabs.length).eql(1);
		tabGroup.removeTab(tab);
		should(tabGroup.tabs.length).eql(0);
	});

	it.ios('.allowUserCustomization', () => {
		var win = Ti.UI.createWindow();
		tabGroup = Ti.UI.createTabGroup({
			allowUserCustomization: true
		});
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		should(tabGroup.allowUserCustomization).eql(true);
		tabGroup.setAllowUserCustomization(false);
		should(tabGroup.allowUserCustomization).eql(false);
	});

	it.ios('.tabsTranslucent', () => {
		var win = Ti.UI.createWindow();
		tabGroup = Ti.UI.createTabGroup({
			tabsTranslucent: true
		});
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		should(tabGroup.tabsTranslucent).eql(true);
		tabGroup.setTabsTranslucent(false);
		should(tabGroup.tabsTranslucent).eql(false);
	});

	it('#setTabs()', () => {
		const winA = Ti.UI.createWindow(),
			tabA = Ti.UI.createTab({
				title: 'Tab A',
				window: winA
			}),
			winB = Ti.UI.createWindow(),
			tabB = Ti.UI.createTab({
				title: 'Tab B',
				window: winB
			});
		tabGroup = Ti.UI.createTabGroup();

		tabGroup.setTabs([ tabA, tabB ]);
		should(tabGroup.getTabs()).eql([ tabA, tabB ]);
	});

	it.windowsBroken('#setActiveTab()', finish => {
		const winA = Ti.UI.createWindow(),
			tabA = Ti.UI.createTab({
				title: 'Tab A',
				window: winA
			}),
			winB = Ti.UI.createWindow(),
			tabB = Ti.UI.createTab({
				title: 'Tab B',
				window: winB
			});
		tabGroup = Ti.UI.createTabGroup();

		// Does windows fire this event?
		// Can we test this without even opening tab group?
		tabGroup.addEventListener('open', () => {
			try {
				tabGroup.setActiveTab(tabB);
				should(tabGroup.getActiveTab().title).be.a.String;
				should(tabGroup.getActiveTab().title).eql('Tab B');
				finish();
			} catch (err) {
				finish(err);
			} finally {
				tabGroup.removeTab(tabA);
				tabGroup.removeTab(tabB);
			}
		});

		tabGroup.addTab(tabA);
		tabGroup.addTab(tabB);
		tabGroup.open();
	});

	it.android('#disableTabNavigation()', finish => {
		var winA = Ti.UI.createWindow(),
			tabA = Ti.UI.createTab({
				title: 'Tab A',
				window: winA
			}),
			winB = Ti.UI.createWindow(),
			tabB = Ti.UI.createTab({
				title: 'Tab B',
				window: winB
			});
		tabGroup = Ti.UI.createTabGroup();

		// does windows fire this event?
		tabGroup.addEventListener('open', () => {
			try {
				tabGroup.disableTabNavigation(true);
				tabGroup.setActiveTab(tabB);
				should(tabGroup.getActiveTab().title).be.a.String;
				should(tabGroup.getActiveTab().title).eql('Tab A');
				tabGroup.disableTabNavigation(false);
				tabGroup.setActiveTab(tabB);
				should(tabGroup.getActiveTab().title).be.a.String;
				should(tabGroup.getActiveTab().title).eql('Tab B');
				finish();
			} catch (err) {
				finish(err);
			} finally {
				tabGroup.removeTab(tabA);
				tabGroup.removeTab(tabB);
			}
		});

		tabGroup.addTab(tabA);
		tabGroup.addTab(tabB);
		tabGroup.open();
	});

	it('.title', () => {
		tabGroup = Ti.UI.createTabGroup({
			title: 'My title'
		});

		should(tabGroup.getTitle()).be.a.String;
		should(tabGroup.getTitle()).eql('My title');
	});

	describe('events', function () {
		this.timeout(5000);

		// FIXME Windows doesn't fire open/close events
		it.windowsMissing('close', finish => {
			var win = Ti.UI.createWindow();
			tabGroup = Ti.UI.createTabGroup();
			tab = Ti.UI.createTab({
				title: 'Tab',
				window: win
			});

			tabGroup.addEventListener('open', () => {
				setTimeout(() => tabGroup.close(), 1);
			});
			tabGroup.addEventListener('close', () => finish());

			tabGroup.addTab(tab);
			tabGroup.open();
		});

		// times out, presumably doesn't fire event?
		// intermittently times out on Android
		it.windowsBroken('focus', finish => {
			var win = Ti.UI.createWindow();
			tabGroup = Ti.UI.createTabGroup();
			tab = Ti.UI.createTab({
				window: win,
				title: 'Tab'
			});

			tabGroup.addEventListener('focus', () => finish());

			tabGroup.addTab(tab);
			tabGroup.open();
		});

		// times out, presumably doesn't fire event?
		it.windowsBroken('blur', finish => {
			var win = Ti.UI.createWindow();
			tabGroup = Ti.UI.createTabGroup();
			tab = Ti.UI.createTab({
				title: 'Tab',
				window: win
			});

			tabGroup.addEventListener('blur', () => finish());
			tab.addEventListener('open', () => {
				setTimeout(() => tabGroup.close(), 1);
			});

			tabGroup.addTab(tab);
			tabGroup.open();
		});
	});
});
<commit_msg>test: increase timeout on disableTabNavigation<commit_after>/*
 * Appcelerator Titanium Mobile
 * Copyright (c) 2011-Present by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Apache Public License
 * Please see the LICENSE included with this distribution for details.
 */
/* eslint-env mocha */
/* global Ti */
/* eslint no-unused-expressions: "off" */
'use strict';
const should = require('./utilities/assertions'); // eslint-disable-line no-unused-vars

// skipping many test on Windows due to lack of event firing, see https://jira.appcelerator.org/browse/TIMOB-26690
describe('Titanium.UI.TabGroup', () => {
	let tabGroup;
	let tab;

	afterEach(() => {
		if (tabGroup) {
			if (tab) {
				tabGroup.removeTab(tab);
			}
			tabGroup.close();
			tabGroup = null;
		}
		tab = null;
	});

	it.windowsBroken('add Map.View to TabGroup', function (finish) {
		this.timeout(10000);

		const map = require('ti.map');
		const mapView = map.createView({ top: 0, height: '80%' });
		mapView.addEventListener('complete', () => finish());

		const win = Ti.UI.createWindow();
		win.add(mapView);

		tabGroup = Ti.UI.createTabGroup();
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		tabGroup.open();
	});

	it.ios('.tabs', () => {
		var win = Ti.UI.createWindow();
		tabGroup = Ti.UI.createTabGroup();
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		should(tabGroup.tabs.length).eql(1);
		tabGroup.removeTab(tab);
		should(tabGroup.tabs.length).eql(0);
	});

	it.ios('.allowUserCustomization', () => {
		var win = Ti.UI.createWindow();
		tabGroup = Ti.UI.createTabGroup({
			allowUserCustomization: true
		});
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		should(tabGroup.allowUserCustomization).eql(true);
		tabGroup.setAllowUserCustomization(false);
		should(tabGroup.allowUserCustomization).eql(false);
	});

	it.ios('.tabsTranslucent', () => {
		var win = Ti.UI.createWindow();
		tabGroup = Ti.UI.createTabGroup({
			tabsTranslucent: true
		});
		tab = Ti.UI.createTab({
			title: 'Tab',
			window: win
		});

		tabGroup.addTab(tab);
		should(tabGroup.tabsTranslucent).eql(true);
		tabGroup.setTabsTranslucent(false);
		should(tabGroup.tabsTranslucent).eql(false);
	});

	it('#setTabs()', () => {
		const winA = Ti.UI.createWindow(),
			tabA = Ti.UI.createTab({
				title: 'Tab A',
				window: winA
			}),
			winB = Ti.UI.createWindow(),
			tabB = Ti.UI.createTab({
				title: 'Tab B',
				window: winB
			});
		tabGroup = Ti.UI.createTabGroup();

		tabGroup.setTabs([ tabA, tabB ]);
		should(tabGroup.getTabs()).eql([ tabA, tabB ]);
	});

	it.windowsBroken('#setActiveTab()', finish => {
		const winA = Ti.UI.createWindow(),
			tabA = Ti.UI.createTab({
				title: 'Tab A',
				window: winA
			}),
			winB = Ti.UI.createWindow(),
			tabB = Ti.UI.createTab({
				title: 'Tab B',
				window: winB
			});
		tabGroup = Ti.UI.createTabGroup();

		// Does windows fire this event?
		// Can we test this without even opening tab group?
		tabGroup.addEventListener('open', () => {
			try {
				tabGroup.setActiveTab(tabB);
				should(tabGroup.getActiveTab().title).be.a.String;
				should(tabGroup.getActiveTab().title).eql('Tab B');
				finish();
			} catch (err) {
				finish(err);
			} finally {
				tabGroup.removeTab(tabA);
				tabGroup.removeTab(tabB);
			}
		});

		tabGroup.addTab(tabA);
		tabGroup.addTab(tabB);
		tabGroup.open();
	});

	it.android('#disableTabNavigation()', function (finish) {
		var winA = Ti.UI.createWindow(),
			tabA = Ti.UI.createTab({
				title: 'Tab A',
				window: winA
			}),
			winB = Ti.UI.createWindow(),
			tabB = Ti.UI.createTab({
				title: 'Tab B',
				window: winB
			});
		this.timeout(5000);
		tabGroup = Ti.UI.createTabGroup();

		// does windows fire this event?
		tabGroup.addEventListener('open', () => {
			try {
				tabGroup.disableTabNavigation(true);
				tabGroup.setActiveTab(tabB);
				should(tabGroup.getActiveTab().title).be.a.String;
				should(tabGroup.getActiveTab().title).eql('Tab A');
				tabGroup.disableTabNavigation(false);
				tabGroup.setActiveTab(tabB);
				should(tabGroup.getActiveTab().title).be.a.String;
				should(tabGroup.getActiveTab().title).eql('Tab B');
				finish();
			} catch (err) {
				finish(err);
			} finally {
				tabGroup.removeTab(tabA);
				tabGroup.removeTab(tabB);
			}
		});

		tabGroup.addTab(tabA);
		tabGroup.addTab(tabB);
		tabGroup.open();
	});

	it('.title', () => {
		tabGroup = Ti.UI.createTabGroup({
			title: 'My title'
		});

		should(tabGroup.getTitle()).be.a.String;
		should(tabGroup.getTitle()).eql('My title');
	});

	describe('events', function () {
		this.timeout(5000);

		// FIXME Windows doesn't fire open/close events
		it.windowsMissing('close', finish => {
			var win = Ti.UI.createWindow();
			tabGroup = Ti.UI.createTabGroup();
			tab = Ti.UI.createTab({
				title: 'Tab',
				window: win
			});

			tabGroup.addEventListener('open', () => {
				setTimeout(() => tabGroup.close(), 1);
			});
			tabGroup.addEventListener('close', () => finish());

			tabGroup.addTab(tab);
			tabGroup.open();
		});

		// times out, presumably doesn't fire event?
		// intermittently times out on Android
		it.windowsBroken('focus', finish => {
			var win = Ti.UI.createWindow();
			tabGroup = Ti.UI.createTabGroup();
			tab = Ti.UI.createTab({
				window: win,
				title: 'Tab'
			});

			tabGroup.addEventListener('focus', () => finish());

			tabGroup.addTab(tab);
			tabGroup.open();
		});

		// times out, presumably doesn't fire event?
		it.windowsBroken('blur', finish => {
			var win = Ti.UI.createWindow();
			tabGroup = Ti.UI.createTabGroup();
			tab = Ti.UI.createTab({
				title: 'Tab',
				window: win
			});

			tabGroup.addEventListener('blur', () => finish());
			tab.addEventListener('open', () => {
				setTimeout(() => tabGroup.close(), 1);
			});

			tabGroup.addTab(tab);
			tabGroup.open();
		});
	});
});
<|endoftext|>