diff --git a/src/extension.js b/src/extension.js index 5ab5ef2..7545134 100644 --- a/src/extension.js +++ b/src/extension.js @@ -8,7 +8,7 @@ const Main = imports.ui.main; const Panel = imports.ui.panel; const AppIndicatorKStatusNotifierItemManager = Me.imports.extensionModules.AppIndicatorKStatusNotifierItemManager; -const BoxOrderCreator = Me.imports.extensionModules.BoxOrderCreator; +const BoxOrderManager = Me.imports.extensionModules.BoxOrderManager; class Extension { constructor() { @@ -21,12 +21,13 @@ class Extension { // handle AppIndicator/KStatusNotifierItem items. this._appIndicatorKStatusNotifierItemManager = new AppIndicatorKStatusNotifierItemManager.AppIndicatorKStatusNotifierItemManager(); - // Create an instance of BoxOrderCreator for the creation of special box - // orders. - this._boxOrderCreator = new BoxOrderCreator.BoxOrderCreator(this._appIndicatorKStatusNotifierItemManager); + this._boxOrderManager = new BoxOrderManager.BoxOrderManager(this._appIndicatorKStatusNotifierItemManager); - this.#addNewItemsToBoxOrders(); - this.#orderTopBarItemsOfAllBoxes(); + // Stuff to do on startup(extension enable). + this._boxOrderManager.saveNewTopBarItems(); + this.#orderTopBarItems("left"); + this.#orderTopBarItems("center"); + this.#orderTopBarItems("right"); this.#overwritePanelAddToPanelBox(); // Handle changes of configured box orders. @@ -36,27 +37,10 @@ class Extension { let handlerId = this.settings.connect(`changed::${box}-box-order`, () => { this.#orderTopBarItems(box); - /// For the case, where the currently saved box order is based - /// on a permutation of an outdated box order, get an updated - /// box order and save it, if needed. - let updatedBoxOrder; - switch (box) { - case "left": - updatedBoxOrder = this.#createUpdatedBoxOrders().left; - break; - case "center": - updatedBoxOrder = this.#createUpdatedBoxOrders().center; - break; - case "right": - updatedBoxOrder = this.#createUpdatedBoxOrders().right; - break; - } - // Only save the updated box order to settings, if it is - // different, to avoid looping. - const currentBoxOrder = this.settings.get_strv(`${box}-box-order`); - if (JSON.stringify(currentBoxOrder) !== JSON.stringify(updatedBoxOrder)) { - this.settings.set_strv(`${box}-box-order`, updatedBoxOrder); - } + // For the case, where the currently saved box order is based on + // a permutation of an outdated box order, save new top bar + // items. + this._boxOrderManager.saveNewTopBarItems(); }); this._settingsHandlerIds.push(handlerId); }; @@ -84,27 +68,6 @@ class Extension { /// Methods used on extension enable. /// //////////////////////////////////////////////////////////////////////////// - /** - * This method adds all new items currently present in the Gnome Shell top - * bar to the box orders. - */ - #addNewItemsToBoxOrders() { - const boxOrders = this.#createUpdatedBoxOrders(); - this.settings.set_strv("left-box-order", boxOrders.left); - this.settings.set_strv("center-box-order", boxOrders.center); - this.settings.set_strv("right-box-order", boxOrders.right); - } - - /** - * This methods orders the top bar items of all boxes according to the - * configred box orders using `this.#orderTopBarItems`. - */ - #orderTopBarItemsOfAllBoxes() { - this.#orderTopBarItems("left"); - this.#orderTopBarItems("center"); - this.#orderTopBarItems("right"); - } - /** * An object containing a position and box overwrite. * @typedef PositionAndBoxOverwrite @@ -170,7 +133,7 @@ class Extension { right: this._appIndicatorKStatusNotifierItemManager.createResolvedBoxOrder(this.settings.get_strv("right-box-order")), }; // Also get the restricted valid box order of the target box. - const restrictedValidBoxOrderOfTargetBox = this._boxOrderCreator.createRestrictedValidBoxOrder(box); + const restrictedValidBoxOrderOfTargetBox = this._boxOrderManager.createRestrictedValidBoxOrder(box); // Get the index of the role for each box order. const indices = { @@ -239,21 +202,21 @@ class Extension { if (indices.left !== -1) { return { - position: determineInsertionIndex(indices.left, this._boxOrderCreator.createRestrictedValidBoxOrder("left"), resolvedBoxOrders.left), + position: determineInsertionIndex(indices.left, this._boxOrderManager.createRestrictedValidBoxOrder("left"), resolvedBoxOrders.left), box: "left" }; } if (indices.center !== -1) { return { - position: determineInsertionIndex(indices.center, this._boxOrderCreator.createRestrictedValidBoxOrder("center"), resolvedBoxOrders.center), + position: determineInsertionIndex(indices.center, this._boxOrderManager.createRestrictedValidBoxOrder("center"), resolvedBoxOrders.center), box: "center" }; } if (indices.right !== -1) { return { - position: determineInsertionIndex(indices.right, this._boxOrderCreator.createRestrictedValidBoxOrder("right"), resolvedBoxOrders.right), + position: determineInsertionIndex(indices.right, this._boxOrderManager.createRestrictedValidBoxOrder("right"), resolvedBoxOrders.right), box: "right" }; } @@ -305,75 +268,6 @@ class Extension { * @property {string[]} right - The box order for the right top bar box. */ - /** - * This method adds all new items currently present in the Gnome Shell top - * bar to the correct box order and returns the new box orders. - * @returns {BoxOrders} - The updated box orders. - */ - #createUpdatedBoxOrders() { - // Load the configured box orders from settings. - const boxOrders = { - left: this.settings.get_strv("left-box-order"), - center: this.settings.get_strv("center-box-order"), - right: this.settings.get_strv("right-box-order"), - }; - - // Get items (or rather their roles) currently present in the Gnome - // Shell top bar and index them using their associated indicator - // container. - let indicatorContainerRoleMap = new Map(); - for (const role in Main.panel.statusArea) { - indicatorContainerRoleMap.set(Main.panel.statusArea[role].container, role); - } - - // Get the indicator containers (of the items) currently present in the - // Gnome Shell top bar boxes. - const boxOrderIndicatorContainers = { - left: Main.panel._leftBox.get_children(), - center: Main.panel._centerBox.get_children(), - // Reverse this array, since the items in the left and center box - // are logically LTR, while the items in the right box are RTL. - right: Main.panel._rightBox.get_children().reverse() - }; - - // This function goes through the items (or rather their indicator - // containers) of the given box and adds new items (or rather their - // roles) to the box order. - const addNewItemsToBoxOrder = (boxIndicatorContainers, boxOrder, box) => { - for (const indicatorContainer of boxIndicatorContainers) { - // First get the role associated with the current indicator - // container. - const associatedRole = indicatorContainerRoleMap.get(indicatorContainer); - if (!associatedRole) continue; - - // Handle an AppIndicator/KStatusNotifierItem item differently. - if (associatedRole.startsWith("appindicator-")) { - this._appIndicatorKStatusNotifierItemManager.handleAppIndicatorKStatusNotifierItemItem(indicatorContainer, associatedRole, boxOrder, boxOrders, box === "right"); - continue; - } - - // Add the role to the box order, if it isn't in in one already. - if (!boxOrders.left.includes(associatedRole) - && !boxOrders.center.includes(associatedRole) - && !boxOrders.right.includes(associatedRole)) { - if (box === "right") { - // Add the items to the beginning for this array, since - // its RTL. - boxOrder.unshift(associatedRole); - } else { - boxOrder.push(associatedRole); - } - } - } - }; - - addNewItemsToBoxOrder(boxOrderIndicatorContainers.left, boxOrders.left, "left"); - addNewItemsToBoxOrder(boxOrderIndicatorContainers.center, boxOrders.center, "center"); - addNewItemsToBoxOrder(boxOrderIndicatorContainers.right, boxOrders.right, "right"); - - return boxOrders; - } - /** * This method orders the top bar items of the specified box according to * the configured box orders. @@ -381,7 +275,7 @@ class Extension { */ #orderTopBarItems(box) { // Get the valid box order. - const validBoxOrder = this._boxOrderCreator.createValidBoxOrder(box); + const validBoxOrder = this._boxOrderManager.createValidBoxOrder(box); // Get the relevant box of `Main.panel`. let panelBox; diff --git a/src/extensionModules/BoxOrderCreator.js b/src/extensionModules/BoxOrderCreator.js deleted file mode 100644 index db5df28..0000000 --- a/src/extensionModules/BoxOrderCreator.js +++ /dev/null @@ -1,119 +0,0 @@ -"use strict"; -/* exported BoxOrderCreator */ - -const ExtensionUtils = imports.misc.extensionUtils; - -const Main = imports.ui.main; - -/** - * A class exposing methods, which create special box orders. - */ -var BoxOrderCreator = class BoxOrderCreator { - /** - * @param {AppIndicatorKStatusNotifierItemManager} - * appIndicatorKStatusNotifierItemManager - An instance of - * AppIndicatorKStatusNotifierItemManager to be used in the methods of - * `this`. - */ - constructor(appIndicatorKStatusNotifierItemManager) { - this._appIndicatorKStatusNotifierItemManager = appIndicatorKStatusNotifierItemManager; - - this._settings = ExtensionUtils.getSettings(); - } - - /** - * This function creates a valid box order for the given box. - * This means it returns a box order for the box, where only roles are - * included, which have their associated indicator container already in some - * box of the Gnome Shell top bar. - * @param {string} box - The box to return the valid box order for. - * Must be one of the following values: - * - "left" - * - "center" - * - "right" - * @returns {string[]} - The valid box order. - */ - createValidBoxOrder(box) { - // Get a resolved box order. - let boxOrder = this._appIndicatorKStatusNotifierItemManager.createResolvedBoxOrder(this._settings.get_strv(`${box}-box-order`)); - - // Get the indicator containers (of the items) currently present in the - // Gnome Shell top bar. - const boxIndicatorContainers = [ ]; - - const addIndicatorContainersOfBox = (panelBox) => { - for (const indicatorContainer of panelBox.get_children()) { - boxIndicatorContainers.push(indicatorContainer); - } - }; - - addIndicatorContainersOfBox(Main.panel._leftBox); - addIndicatorContainersOfBox(Main.panel._centerBox); - addIndicatorContainersOfBox(Main.panel._rightBox); - - // Create an indicator containers set from the indicator containers for - // fast easy access. - const boxIndicatorContainersSet = new Set(boxIndicatorContainers); - - // Go through the box order and only add items to the valid box order, - // where their indicator is present in the Gnome Shell top bar - // currently. - let validBoxOrder = [ ]; - for (const role of boxOrder) { - // Get the indicator container associated with the current role. - const associatedIndicatorContainer = Main.panel.statusArea[role]?.container; - - if (boxIndicatorContainersSet.has(associatedIndicatorContainer)) validBoxOrder.push(role); - } - - return validBoxOrder; - } - - /** - * This function creates a restricted valid box order for the given box. - * This means it returns a box order for the box, where only roles are - * included, which have their associated indicator container already in the - * specified box. - * @param {string} box - The box to return the valid box order for. - * Must be one of the following values: - * - "left" - * - "center" - * - "right" - * @returns {string[]} - The restricted valid box order. - */ - createRestrictedValidBoxOrder(box) { - // Get a resolved box order and get the indicator containers (of the - // items) which are currently present in the Gnome Shell top bar in the - // specified box. - let boxOrder = this._appIndicatorKStatusNotifierItemManager.createResolvedBoxOrder(this._settings.get_strv(`${box}-box-order`)); - let boxIndicatorContainers; - switch (box) { - case "left": - boxIndicatorContainers = Main.panel._leftBox.get_children(); - break; - case "center": - boxIndicatorContainers = Main.panel._centerBox.get_children(); - break; - case "right": - boxIndicatorContainers = Main.panel._rightBox.get_children(); - break; - } - - // Create an indicator containers set from the indicator containers for - // fast easy access. - const boxIndicatorContainersSet = new Set(boxIndicatorContainers); - - // Go through the box order and only add items to the restricted valid - // box order, where their indicator is present in the Gnome Shell top - // bar in the specified box currently. - let restrictedValidBoxOrder = [ ]; - for (const role of boxOrder) { - // Get the indicator container associated with the current role. - const associatedIndicatorContainer = Main.panel.statusArea[role]?.container; - - if (boxIndicatorContainersSet.has(associatedIndicatorContainer)) restrictedValidBoxOrder.push(role); - } - - return restrictedValidBoxOrder; - } -}; diff --git a/src/extensionModules/BoxOrderManager.js b/src/extensionModules/BoxOrderManager.js new file mode 100644 index 0000000..6ad30eb --- /dev/null +++ b/src/extensionModules/BoxOrderManager.js @@ -0,0 +1,205 @@ +"use strict"; +/* exported BoxOrderManager */ + +const ExtensionUtils = imports.misc.extensionUtils; + +const Main = imports.ui.main; + +/** + * An object containing a box order for the left, center and right top bar + * box. + * @typedef {Object} BoxOrders + * @property {string[]} left - The box order for the left top bar box. + * @property {string[]} center - The box order for the center top bar box. + * @property {string[]} right - The box order for the right top bar box. + */ + +/** + * This class provides methods get, set and interact with box orders, while + * taking over the work of translating between what is stored in settings and + * what is really useable by the other extension code. + * It's basically a heavy wrapper around the box orders stored in the settings. + */ +var BoxOrderManager = class BoxOrderManager { + /** + * @param {AppIndicatorKStatusNotifierItemManager} + * appIndicatorKStatusNotifierItemManager - An instance of + * AppIndicatorKStatusNotifierItemManager to be used in the methods of + * `this`. + */ + constructor(appIndicatorKStatusNotifierItemManager) { + this._appIndicatorKStatusNotifierItemManager = appIndicatorKStatusNotifierItemManager; + + this._settings = ExtensionUtils.getSettings(); + } + + /** + * This method returns a valid box order for the given top bar box. + * This means it returns a box order, where only roles are included, which + * have their associated indicator container already in some box of the + * Gnome Shell top bar. + * @param {string} box - The top bar box to return the valid box order for. + * Must be one of the following values: + * - "left" + * - "center" + * - "right" + * @returns {string[]} - The valid box order. + */ + createValidBoxOrder(box) { + // Get a resolved box order. + let boxOrder = this._appIndicatorKStatusNotifierItemManager.createResolvedBoxOrder(this._settings.get_strv(`${box}-box-order`)); + + // ToDo: simplify. + // Get the indicator containers (of the items) currently present in the + // Gnome Shell top bar. + const indicatorContainers = [ + Main.panel._leftBox.get_children(), + Main.panel._centerBox.get_children(), + Main.panel._rightBox.get_children() + ].flat(); + + // Create an indicator containers set from the indicator containers for + // fast easy access. + const indicatorContainerSet = new Set(indicatorContainers); + + // Go through the box order and only add items to the valid box order, + // where their indicator is present in the Gnome Shell top bar + // currently. + let validBoxOrder = [ ]; + for (const role of boxOrder) { + // Get the indicator container associated with the current role. + const associatedIndicatorContainer = Main.panel.statusArea[role]?.container; + + if (indicatorContainerSet.has(associatedIndicatorContainer)) validBoxOrder.push(role); + } + + return validBoxOrder; + } + + /** + * This method returns a restricted valid box order for the given top bar + * box. + * This means it returns a box order, where only roles are included, which + * have their associated indicator container already in the specified box. + * @param {string} box - The box to return the valid box order for. + * Must be one of the following values: + * - "left" + * - "center" + * - "right" + * @returns {string[]} - The restricted valid box order. + */ + createRestrictedValidBoxOrder(box) { + // Get a resolved box order. + let boxOrder = this._appIndicatorKStatusNotifierItemManager.createResolvedBoxOrder(this._settings.get_strv(`${box}-box-order`)); + + // Get the indicator containers (of the items), which are currently + // present the in specified Gnome Shell top bar box. + let indicatorContainers; + switch (box) { + case "left": + indicatorContainers = Main.panel._leftBox.get_children(); + break; + case "center": + indicatorContainers = Main.panel._centerBox.get_children(); + break; + case "right": + indicatorContainers = Main.panel._rightBox.get_children(); + break; + } + + // Create an indicator container set from the indicator containers for + // fast easy access. + const indicatorContainerSet = new Set(indicatorContainers); + + // Go through the box order and only add items to the restricted valid + // box order, where their indicator is present in the specified Gnome + // Shell top bar box. + let restrictedValidBoxOrder = [ ]; + for (const role of boxOrder) { + // Get the indicator container associated with the current role. + const associatedIndicatorContainer = Main.panel.statusArea[role]?.container; + + if (indicatorContainerSet.has(associatedIndicatorContainer)) restrictedValidBoxOrder.push(role); + } + + return restrictedValidBoxOrder; + } + + /** + * This method saves all new items currently present in the Gnome Shell top + * bar to the correct box orders. + */ + saveNewTopBarItems() { + // Load the configured box orders from settings. + const boxOrders = { + left: this._settings.get_strv("left-box-order"), + center: this._settings.get_strv("center-box-order"), + right: this._settings.get_strv("right-box-order"), + }; + + // Get roles (of items) currently present in the Gnome Shell top bar and + // index them using their associated indicator container. + let indicatorContainerRoleMap = new Map(); + for (const role in Main.panel.statusArea) { + indicatorContainerRoleMap.set(Main.panel.statusArea[role].container, role); + } + + // Get the indicator containers (of the items) currently present in the + // Gnome Shell top bar boxes. + const boxIndicatorContainers = { + left: Main.panel._leftBox.get_children(), + center: Main.panel._centerBox.get_children(), + // Reverse this array, since the items in the left and center box + // are logically LTR, while the items in the right box are RTL. + right: Main.panel._rightBox.get_children().reverse() + }; + + // This function goes through the indicator containers of the given box + // and adds roles of new items to the box order. + const addNewItemsToBoxOrder = (indicatorContainers, boxOrder, box) => { + for (const indicatorContainer of indicatorContainers) { + // First get the role associated with the current indicator + // container. + const role = indicatorContainerRoleMap.get(indicatorContainer); + if (!role) continue; + + // Handle an AppIndicator/KStatusNotifierItem item differently. + if (role.startsWith("appindicator-")) { + this._appIndicatorKStatusNotifierItemManager.handleAppIndicatorKStatusNotifierItemItem(indicatorContainer, role, boxOrder, boxOrders, box === "right"); + continue; + } + + // Add the role to the box order, if it isn't in in one already. + if (!boxOrders.left.includes(role) + && !boxOrders.center.includes(role) + && !boxOrders.right.includes(role)) { + if (box === "right") { + // Add the items to the beginning for this array, since + // its RTL. + boxOrder.unshift(role); + } else { + boxOrder.push(role); + } + } + } + }; + + addNewItemsToBoxOrder(boxIndicatorContainers.left, boxOrders.left, "left"); + addNewItemsToBoxOrder(boxIndicatorContainers.center, boxOrders.center, "center"); + addNewItemsToBoxOrder(boxIndicatorContainers.right, boxOrders.right, "right"); + + // This function saves the given box order to settings. + const saveBoxOrderToSettings = (boxOrder, box) => { + const currentBoxOrder = this._settings.get_strv(`${box}-box-order`); + // Only save the updated box order to settings, if it is different, + // to avoid loops, when listening on settings changes. + if (JSON.stringify(currentBoxOrder) !== JSON.stringify(boxOrder)) { + this._settings.set_strv(`${box}-box-order`, boxOrder); + } + }; + + saveBoxOrderToSettings(boxOrders.left, "left"); + saveBoxOrderToSettings(boxOrders.center, "center"); + saveBoxOrderToSettings(boxOrders.right, "right"); + } +};