mirror of
				https://gitlab.gnome.org/julianschacher/top-bar-organizer.git
				synced 2025-10-27 23:29:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			171 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| /* exported init */
 | |
| 
 | |
| const ExtensionUtils = imports.misc.extensionUtils;
 | |
| const Me = ExtensionUtils.getCurrentExtension();
 | |
| 
 | |
| const Main = imports.ui.main;
 | |
| const Panel = imports.ui.panel;
 | |
| 
 | |
| const BoxOrderManager = Me.imports.extensionModules.BoxOrderManager;
 | |
| 
 | |
| class Extension {
 | |
|     constructor() {
 | |
|     }
 | |
| 
 | |
|     enable() {
 | |
|         this.settings = ExtensionUtils.getSettings();
 | |
| 
 | |
|         this._boxOrderManager = new BoxOrderManager.BoxOrderManager();
 | |
| 
 | |
|         // 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.
 | |
|         this._settingsHandlerIds = [];
 | |
| 
 | |
|         const addConfiguredBoxOrderChangeHandler = (box) => {
 | |
|             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, save new top bar
 | |
|                 // items.
 | |
|                 this._boxOrderManager.saveNewTopBarItems();
 | |
|             });
 | |
|             this._settingsHandlerIds.push(handlerId);
 | |
|         };
 | |
| 
 | |
|         addConfiguredBoxOrderChangeHandler("left");
 | |
|         addConfiguredBoxOrderChangeHandler("center");
 | |
|         addConfiguredBoxOrderChangeHandler("right");
 | |
| 
 | |
|         // Handle AppIndicators getting ready.
 | |
|         this._boxOrderManager.connect("appIndicatorReady", () => {
 | |
|             this._boxOrderManager.saveNewTopBarItems();
 | |
|             this.#orderTopBarItems("left");
 | |
|             this.#orderTopBarItems("center");
 | |
|             this.#orderTopBarItems("right");
 | |
|         });
 | |
| 
 | |
|     }
 | |
| 
 | |
|     disable() {
 | |
|         // Revert the overwrite of `Panel._addToPanelBox`.
 | |
|         Panel.Panel.prototype._addToPanelBox = Panel.Panel.prototype._originalAddToPanelBox;
 | |
|         // Set `Panel._originalAddToPanelBox` to `undefined`.
 | |
|         Panel._originalAddToPanelBox = undefined;
 | |
| 
 | |
|         // Disconnect signals.
 | |
|         for (const handlerId of this._settingsHandlerIds) {
 | |
|             this.settings.disconnect(handlerId);
 | |
|         }
 | |
|         this._boxOrderManager.disconnectSignals();
 | |
| 
 | |
|         this.settings = null;
 | |
|         this._boxOrderManager = null;
 | |
|     }
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////////////////////
 | |
|     /// Methods used on extension enable.                                    ///
 | |
|     ////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
|     /**
 | |
|      * An object containing a position and box overwrite.
 | |
|      * @typedef PositionAndBoxOverwrite
 | |
|      * @property {Number} position - The position overwrite.
 | |
|      * @property {string} box - The position box overwrite.
 | |
|      */
 | |
| 
 | |
|     /**
 | |
|      * Overwrite `Panel._addToPanelBox` with a custom method, which simply calls
 | |
|      * the original one and orders the top bar and handles new items afterwards.
 | |
|      */
 | |
|     #overwritePanelAddToPanelBox() {
 | |
|         // Add the original `Panel._addToPanelBox` method as
 | |
|         // `Panel._originalAddToPanelBox`.
 | |
|         Panel.Panel.prototype._originalAddToPanelBox = Panel.Panel.prototype._addToPanelBox;
 | |
| 
 | |
|         const orderTopBarAndHandleNewItems = () => {
 | |
|             this.#orderTopBarItems("left");
 | |
|             this.#orderTopBarItems("center");
 | |
|             this.#orderTopBarItems("right");
 | |
|             this._boxOrderManager.saveNewTopBarItems();
 | |
|         };
 | |
| 
 | |
|         // Overwrite `Panel._addToPanelBox`.
 | |
|         Panel.Panel.prototype._addToPanelBox = function(role, indicator, position, box) {
 | |
|             // Simply call the original `_addToPanelBox` and order the top bar
 | |
|             // and handle new items afterwards.
 | |
|             this._originalAddToPanelBox(role, indicator, position, box);
 | |
|             orderTopBarAndHandleNewItems();
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     ////////////////////////////////////////////////////////////////////////////
 | |
|     /// Helper methods holding logic needed by other methods.                ///
 | |
|     ////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
|     /**
 | |
|      * This method orders the top bar items of the specified box according to
 | |
|      * the configured box orders.
 | |
|      * @param {string} box - The box to order.
 | |
|      */
 | |
|     #orderTopBarItems(box) {
 | |
|         // Get the valid box order.
 | |
|         const validBoxOrder = this._boxOrderManager.createValidBoxOrder(box);
 | |
| 
 | |
|         // Get the relevant box of `Main.panel`.
 | |
|         let panelBox;
 | |
|         switch (box) {
 | |
|             case "left":
 | |
|                 panelBox = Main.panel._leftBox;
 | |
|                 break;
 | |
|             case "center":
 | |
|                 panelBox = Main.panel._centerBox;
 | |
|                 break;
 | |
|             case "right":
 | |
|                 panelBox = Main.panel._rightBox;
 | |
|                 break;
 | |
|         }
 | |
| 
 | |
|         /// Go through the items (or rather their roles) of the validBoxOrder
 | |
|         /// and order the panelBox accordingly.
 | |
|         for (let i = 0; i < validBoxOrder.length; i++) {
 | |
|             const role = validBoxOrder[i];
 | |
|             // Get the indicator container associated with the current role.
 | |
|             const associatedIndicatorContainer = Main.panel.statusArea[role].container;
 | |
| 
 | |
|             associatedIndicatorContainer.get_parent().remove_child(associatedIndicatorContainer);
 | |
|             if (box === "right") {
 | |
|                 // If the target panel box is the right panel box, insert the
 | |
|                 // indicator container at index `-1`, which just adds it to the
 | |
|                 // end (correct order is ensured, since `validBoxOrder` is
 | |
|                 // sorted correctly and we're looping over it in order).
 | |
|                 // This way unaccounted-for indicator containers will be at the
 | |
|                 // left, which is preferred, since the box is logically
 | |
|                 // right-to-left.
 | |
|                 // The same applies for indicator containers, which are just
 | |
|                 // temporarily unaccounted for (like for indicator containers of
 | |
|                 // not yet ready app indicators), since them being at the right
 | |
|                 // for a probably temporary stay causes all the indicator
 | |
|                 // containers to shift.
 | |
|                 panelBox.insert_child_at_index(associatedIndicatorContainer, -1);
 | |
|             } else {
 | |
|                 panelBox.insert_child_at_index(associatedIndicatorContainer, i);
 | |
|             }
 | |
|         }
 | |
|         // To handle the case, where the box order got set to a permutation
 | |
|         // of an outdated box order, it would be wise, if the caller updated the
 | |
|         // box order now to include the items present in the top bar.
 | |
|     }
 | |
| }
 | |
| 
 | |
| function init() {
 | |
|     return new Extension();
 | |
| }
 |