mirror of
				https://gitlab.gnome.org/julianschacher/top-bar-organizer.git
				synced 2025-10-27 15:19:09 +00:00 
			
		
		
		
	Feature: Add initial preferences dialog
Add an initial preferences dialog, which allows the user to easily reorder the Gnome Shell top bar items.
This commit is contained in:
		
							parent
							
								
									a3f5ad96f4
								
							
						
					
					
						commit
						b0ebe468aa
					
				| @ -13,3 +13,7 @@ trim_trailing_whitespace = true | ||||
| [*.md] | ||||
| indent_size = 4 | ||||
| trim_trailing_whitespace = false | ||||
| 
 | ||||
| [*.ui] | ||||
| indent_size = 4 | ||||
| trim_trailing_whitespace = true | ||||
|  | ||||
							
								
								
									
										40
									
								
								src/prefs-box-order-item-row.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/prefs-box-order-item-row.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|   This file is part of Top-Bar-Organizer (a Gnome Shell Extension for | ||||
|   organizing your Gnome Shell top bar). | ||||
|   Copyright (C) 2021 Julian Schacher | ||||
| 
 | ||||
|   Top-Bar-Organizer is free software: you can redistribute it and/or modify | ||||
|   it under the terms of the GNU General Public License as published by | ||||
|   the Free Software Foundation, either version 3 of the License, or | ||||
|   (at your option) any later version. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, | ||||
|   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|   GNU General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| --> | ||||
| <interface> | ||||
|     <template class="PrefsBoxOrderItemRow" parent="GtkListBoxRow"> | ||||
|         <child> | ||||
|             <object class="GtkBox"> | ||||
|                 <property name="spacing">10</property> | ||||
|                 <property name="margin-top">10</property> | ||||
|                 <property name="margin-bottom">10</property> | ||||
|                 <property name="margin-start">10</property> | ||||
|                 <property name="margin-end">10</property> | ||||
|                 <child> | ||||
|                     <object class="GtkImage"> | ||||
|                         <property name="icon-name">list-drag-handle-symbolic</property> | ||||
|                     </object> | ||||
|                 </child> | ||||
|                 <child> | ||||
|                     <object class="GtkLabel" id="item-name-display-label"/> | ||||
|                 </child> | ||||
|             </object> | ||||
|         </child> | ||||
|     </template> | ||||
| </interface> | ||||
							
								
								
									
										41
									
								
								src/prefs-box-order-list-empty-placeholder.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/prefs-box-order-list-empty-placeholder.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|   This file is part of Top-Bar-Organizer (a Gnome Shell Extension for | ||||
|   organizing your Gnome Shell top bar). | ||||
|   Copyright (C) 2021 Julian Schacher | ||||
| 
 | ||||
|   Top-Bar-Organizer is free software: you can redistribute it and/or modify | ||||
|   it under the terms of the GNU General Public License as published by | ||||
|   the Free Software Foundation, either version 3 of the License, or | ||||
|   (at your option) any later version. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, | ||||
|   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|   GNU General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| --> | ||||
| <interface> | ||||
|     <template class="PrefsBoxOrderListEmptyPlaceholder" parent="GtkBox"> | ||||
|         <child> | ||||
|             <object class="GtkBox"> | ||||
|                 <property name="spacing">10</property> | ||||
|                 <property name="margin-top">10</property> | ||||
|                 <property name="margin-bottom">10</property> | ||||
|                 <property name="margin-start">10</property> | ||||
|                 <property name="margin-end">10</property> | ||||
|                 <child> | ||||
|                     <object class="GtkLabel"> | ||||
|                         <property name="label">Drop items onto here to add them to this box.</property> | ||||
|                         <property name="halign">start</property> | ||||
|                         <style> | ||||
|                             <class name="dim-label"/> | ||||
|                         </style> | ||||
|                     </object> | ||||
|                 </child> | ||||
|             </object> | ||||
|         </child> | ||||
|     </template> | ||||
| </interface> | ||||
							
								
								
									
										101
									
								
								src/prefs-widget.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/prefs-widget.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- | ||||
|   This file is part of Top-Bar-Organizer (a Gnome Shell Extension for | ||||
|   organizing your Gnome Shell top bar). | ||||
|   Copyright (C) 2021 Julian Schacher | ||||
| 
 | ||||
|   Top-Bar-Organizer is free software: you can redistribute it and/or modify | ||||
|   it under the terms of the GNU General Public License as published by | ||||
|   the Free Software Foundation, either version 3 of the License, or | ||||
|   (at your option) any later version. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, | ||||
|   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|   GNU General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| --> | ||||
| <interface> | ||||
|     <template class="PrefsWidget" parent="GtkBox"> | ||||
|         <property name="orientation">vertical</property> | ||||
|         <property name="spacing">24</property> | ||||
|         <property name="margin-top">36</property> | ||||
|         <property name="margin-bottom">36</property> | ||||
|         <property name="margin-start">36</property> | ||||
|         <property name="margin-end">36</property> | ||||
|         <child> | ||||
|             <object class="GtkLabel"> | ||||
|                 <property name="label">Simply use drag and drop to order the items any way you want.</property> | ||||
|                 <property name="halign">start</property> | ||||
|                 <style> | ||||
|                     <class name="dim-label"/> | ||||
|                 </style> | ||||
|             </object> | ||||
|         </child> | ||||
|         <child> | ||||
|             <object class="GtkBox"> | ||||
|                 <property name="orientation">vertical</property> | ||||
|                 <child> | ||||
|                     <object class="GtkLabel"> | ||||
|                         <property name="label">Left Top Bar Box</property> | ||||
|                         <property name="halign">start</property> | ||||
|                         <property name="margin-bottom">12</property> | ||||
|                         <attributes> | ||||
|                             <attribute name="weight" value="bold"/> | ||||
|                         </attributes> | ||||
|                     </object> | ||||
|                 </child> | ||||
|                 <child> | ||||
|                     <object class="GtkListBox" id="left-box-order"> | ||||
|                         <property name="selection-mode">none</property> | ||||
|                         <property name="show-separators">True</property> | ||||
|                     </object> | ||||
|                 </child> | ||||
|             </object> | ||||
|         </child> | ||||
|         <child> | ||||
|             <object class="GtkBox"> | ||||
|                 <property name="orientation">vertical</property> | ||||
|                 <child> | ||||
|                     <object class="GtkLabel"> | ||||
|                         <property name="label">Center Top Bar Box</property> | ||||
|                         <property name="halign">start</property> | ||||
|                         <property name="margin-bottom">12</property> | ||||
|                         <attributes> | ||||
|                             <attribute name="weight" value="bold"/> | ||||
|                         </attributes> | ||||
|                     </object> | ||||
|                 </child> | ||||
|                 <child> | ||||
|                     <object class="GtkListBox" id="center-box-order"> | ||||
|                         <property name="selection-mode">none</property> | ||||
|                         <property name="show-separators">True</property> | ||||
|                     </object> | ||||
|                 </child> | ||||
|             </object> | ||||
|         </child> | ||||
|         <child> | ||||
|             <object class="GtkBox"> | ||||
|                 <property name="orientation">vertical</property> | ||||
|                 <child> | ||||
|                     <object class="GtkLabel"> | ||||
|                         <property name="label">Right Top Bar Box</property> | ||||
|                         <property name="halign">start</property> | ||||
|                         <property name="margin-bottom">12</property> | ||||
|                         <attributes> | ||||
|                             <attribute name="weight" value="bold"/> | ||||
|                         </attributes> | ||||
|                     </object> | ||||
|                 </child> | ||||
|                 <child> | ||||
|                     <object class="GtkListBox" id="right-box-order"> | ||||
|                         <property name="selection-mode">none</property> | ||||
|                         <property name="show-separators">True</property> | ||||
|                     </object> | ||||
|                 </child> | ||||
|             </object> | ||||
|         </child> | ||||
|     </template> | ||||
| </interface> | ||||
							
								
								
									
										238
									
								
								src/prefs.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								src/prefs.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,238 @@ | ||||
| /* | ||||
|  * This file is part of Top-Bar-Organizer (a Gnome Shell Extension for | ||||
|  * organizing your Gnome Shell top bar). | ||||
|  * Copyright (C) 2021 Julian Schacher | ||||
|  * | ||||
|  * Top-Bar-Organizer is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| /* exported buildPrefsWidget, init */ | ||||
| "use strict"; | ||||
| 
 | ||||
| const Gtk = imports.gi.Gtk; | ||||
| const Gdk = imports.gi.Gdk; | ||||
| const GObject = imports.gi.GObject; | ||||
| 
 | ||||
| const ExtensionUtils = imports.misc.extensionUtils; | ||||
| const Me = ExtensionUtils.getCurrentExtension(); | ||||
| 
 | ||||
| var PrefsBoxOrderListEmptyPlaceholder = GObject.registerClass({ | ||||
|     GTypeName: "PrefsBoxOrderListEmptyPlaceholder", | ||||
|     Template: Me.dir.get_child("prefs-box-order-list-empty-placeholder.ui").get_uri() | ||||
| }, class PrefsBoxOrderListEmptyPlaceholder extends Gtk.Box { | ||||
|     _init(params = {}) { | ||||
|         super._init(params); | ||||
| 
 | ||||
|         /// Make `this` accept drops by creating a drop target and adding it to
 | ||||
|         /// `this`.
 | ||||
|         let dropTarget = new Gtk.DropTarget(); | ||||
|         dropTarget.set_gtypes([GObject.type_from_name("PrefsBoxOrderItemRow")]); | ||||
|         dropTarget.set_actions(Gdk.DragAction.MOVE); | ||||
|         // Handle a new drop on `this` properly.
 | ||||
|         // `value` is the thing getting dropped.
 | ||||
|         dropTarget.connect("drop", (target, value) => { | ||||
|             // Get the GtkListBoxes of `this` and the drop value.
 | ||||
|             const ownListBox = this.get_parent(); | ||||
|             const valueListBox = value.get_parent(); | ||||
| 
 | ||||
|             // Remove the drop value from its list box.
 | ||||
|             valueListBox.remove(value); | ||||
| 
 | ||||
|             // Insert the drop value into the list box of `this`.
 | ||||
|             ownListBox.insert(value, 0); | ||||
| 
 | ||||
|             /// Finally save the box orders to settings.
 | ||||
|             const settings = ExtensionUtils.getSettings(); | ||||
| 
 | ||||
|             settings.set_strv(ownListBox.boxOrder, [value.item]); | ||||
| 
 | ||||
|             let updatedBoxOrder = [ ]; | ||||
|             for (let potentialListBoxRow of valueListBox) { | ||||
|                 // Only process PrefsBoxOrderItemRows.
 | ||||
|                 if (potentialListBoxRow.constructor.$gtype.name !== "PrefsBoxOrderItemRow") { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 const item = potentialListBoxRow.item; | ||||
|                 updatedBoxOrder.push(item); | ||||
|             } | ||||
|             settings.set_strv(valueListBox.boxOrder, updatedBoxOrder); | ||||
|         }); | ||||
|         this.add_controller(dropTarget); | ||||
|     } | ||||
| }); | ||||
| 
 | ||||
| var PrefsBoxOrderItemRow = GObject.registerClass({ | ||||
|     GTypeName: "PrefsBoxOrderItemRow", | ||||
|     Template: Me.dir.get_child("prefs-box-order-item-row.ui").get_uri(), | ||||
|     Children: ["item-name-display-label"] | ||||
| }, class PrefsBoxOrderItemRow extends Gtk.ListBoxRow { | ||||
|     _init(params = {}) { | ||||
|         super._init(params); | ||||
| 
 | ||||
|         // Make `this` draggable by creating a drag source and adding it to
 | ||||
|         // `this`.
 | ||||
|         let dragSource = new Gtk.DragSource(); | ||||
|         dragSource.set_actions(Gdk.DragAction.MOVE); | ||||
|         dragSource.connect("prepare", () => { | ||||
|             return Gdk.ContentProvider.new_for_value(this); | ||||
|         }); | ||||
|         this.add_controller(dragSource); | ||||
| 
 | ||||
|         /// Make `this` accept drops by creating a drop target and adding it to
 | ||||
|         /// `this`.
 | ||||
|         let dropTarget = new Gtk.DropTarget(); | ||||
|         dropTarget.set_gtypes([this.constructor.$gtype]); | ||||
|         dropTarget.set_actions(Gdk.DragAction.MOVE); | ||||
|         // Handle a new drop on `this` properly.
 | ||||
|         // `value` is the thing getting dropped.
 | ||||
|         dropTarget.connect("drop", (target, value) => { | ||||
|             // If `this` got dropped onto itself, do nothing.
 | ||||
|             if (value === this) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             // Get the GtkListBoxes of `this` and the drop value.
 | ||||
|             const ownListBox = this.get_parent(); | ||||
|             const valueListBox = value.get_parent(); | ||||
| 
 | ||||
|             // Get the position of `this` and the drop value.
 | ||||
|             const ownPosition = this.get_index(); | ||||
|             const valuePosition = value.get_index(); | ||||
| 
 | ||||
|             // Remove the drop value from its list box.
 | ||||
|             valueListBox.remove(value); | ||||
| 
 | ||||
|             // Since an element got potentially removed from the list of `this`,
 | ||||
|             // get the position of `this` again.
 | ||||
|             const updatedOwnPosition = this.get_index(); | ||||
| 
 | ||||
|             if (ownListBox !== valueListBox) { | ||||
|                 // First handle the case where `this` and the drop value are in
 | ||||
|                 // different list boxes.
 | ||||
|                 if ((ownListBox.boxOrder === "right-box-order" && valueListBox.boxOrder === "left-box-order") | ||||
|                     || (ownListBox.boxOrder === "right-box-order" && valueListBox.boxOrder === "center-box-order") | ||||
|                     || (ownListBox.boxOrder === "center-box-order" && valueListBox.boxOrder === "left-box-order")) { | ||||
|                     // If the list box of the drop value comes before the list
 | ||||
|                     // box of `this`, add the drop value after `this`.
 | ||||
|                     ownListBox.insert(value, updatedOwnPosition + 1); | ||||
|                 } else { | ||||
|                     // Otherwise, add the drop value where `this` currently is.
 | ||||
|                     ownListBox.insert(value, updatedOwnPosition); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (valuePosition < ownPosition) { | ||||
|                     // If the drop value was before `this`, add the drop value
 | ||||
|                     // after `this`.
 | ||||
|                     ownListBox.insert(value, updatedOwnPosition + 1); | ||||
|                 } else { | ||||
|                     // Otherwise, add the drop value where `this` currently is.
 | ||||
|                     ownListBox.insert(value, updatedOwnPosition); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             /// Finally save the box orders to settings.
 | ||||
|             const settings = ExtensionUtils.getSettings(); | ||||
| 
 | ||||
|             let updatedBoxOrder = [ ]; | ||||
|             for (let potentialListBoxRow of ownListBox) { | ||||
|                 // Only process PrefsBoxOrderItemRows.
 | ||||
|                 if (potentialListBoxRow.constructor.$gtype.name !== "PrefsBoxOrderItemRow") { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 const item = potentialListBoxRow.item; | ||||
|                 updatedBoxOrder.push(item); | ||||
|             } | ||||
|             settings.set_strv(ownListBox.boxOrder, updatedBoxOrder); | ||||
| 
 | ||||
|             // If the list boxes of `this` and the drop value were different,
 | ||||
|             // save an updated box order for the list were the drop value was in
 | ||||
|             // as well.
 | ||||
|             if (ownListBox !== valueListBox) { | ||||
|                 let updatedBoxOrder = [ ]; | ||||
|                 for (let potentialListBoxRow of valueListBox) { | ||||
|                     // Only process PrefsBoxOrderItemRows.
 | ||||
|                     if (potentialListBoxRow.constructor.$gtype.name !== "PrefsBoxOrderItemRow") { | ||||
|                         continue; | ||||
|                     } | ||||
| 
 | ||||
|                     const item = potentialListBoxRow.item; | ||||
|                     updatedBoxOrder.push(item); | ||||
|                 } | ||||
|                 settings.set_strv(valueListBox.boxOrder, updatedBoxOrder); | ||||
|             } | ||||
|         }); | ||||
|         this.add_controller(dropTarget); | ||||
|     } | ||||
| }); | ||||
| 
 | ||||
| var PrefsWidget = GObject.registerClass({ | ||||
|     GTypeName: "PrefsWidget", | ||||
|     Template: Me.dir.get_child("prefs-widget.ui").get_uri(), | ||||
|     InternalChildren: [ | ||||
|         "left-box-order", | ||||
|         "center-box-order", | ||||
|         "right-box-order" | ||||
|     ] | ||||
| }, class PrefsWidget extends Gtk.Box { | ||||
|     _init(params = {}) { | ||||
|         super._init(params); | ||||
| 
 | ||||
|         this._settings = ExtensionUtils.getSettings(); | ||||
| 
 | ||||
|         // Initialize the given `gtkListBox`.
 | ||||
|         const initializeGtkListBox = (boxOrder, gtkListBox) => { | ||||
|             // Add the items of the given configured box order as
 | ||||
|             // GtkListBoxRows.
 | ||||
|             for (const item of boxOrder) { | ||||
|                 const listBoxRow = new PrefsBoxOrderItemRow(); | ||||
| 
 | ||||
|                 listBoxRow.item = item; | ||||
|                 if (item.startsWith("appindicator-kstatusnotifieritem-")) { | ||||
|                     // Set `item_name_display_label` of the `listBoxRow` to
 | ||||
|                     // something nicer, if the associated item is an
 | ||||
|                     // AppIndicator/KStatusNotifierItem item.
 | ||||
|                     listBoxRow.item_name_display_label.set_label(item.replace("appindicator-kstatusnotifieritem-", "")); | ||||
|                 } else { | ||||
|                     // Otherwise just set the `item_name_display_label` of the
 | ||||
|                     // `listBoxRow` to `item`.
 | ||||
|                     listBoxRow.item_name_display_label.set_label(item); | ||||
|                 } | ||||
|                 gtkListBox.append(listBoxRow); | ||||
|             } | ||||
| 
 | ||||
|             // Add a placeholder widget for the case, where `gtkListBox` doesn't
 | ||||
|             // have any GtkListBoxRows.
 | ||||
|             gtkListBox.set_placeholder(new PrefsBoxOrderListEmptyPlaceholder()); | ||||
|         }; | ||||
| 
 | ||||
|         initializeGtkListBox(this._settings.get_strv("left-box-order"), this._left_box_order); | ||||
|         initializeGtkListBox(this._settings.get_strv("center-box-order"), this._center_box_order); | ||||
|         initializeGtkListBox(this._settings.get_strv("right-box-order"), this._right_box_order); | ||||
| 
 | ||||
|         // Set the box order each GtkListBox is associated with.
 | ||||
|         // This is needed by the reordering of the GtkListBoxRows, so that the
 | ||||
|         // updated box orders can be saved.
 | ||||
|         this._left_box_order.boxOrder = "left-box-order"; | ||||
|         this._center_box_order.boxOrder = "center-box-order"; | ||||
|         this._right_box_order.boxOrder = "right-box-order"; | ||||
|     } | ||||
| }); | ||||
| 
 | ||||
| function buildPrefsWidget() { | ||||
|     return new PrefsWidget(); | ||||
| } | ||||
| 
 | ||||
| function init() { | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user