mirror of
				https://gitlab.gnome.org/julianschacher/top-bar-organizer.git
				synced 2025-10-27 15:19:09 +00:00 
			
		
		
		
	Update: Scroll preferences window content on Drag-and-Drop
Scroll the content of the preferences window on Drag-and-Drop, when the mouse is in the upper or lower part of the content of the preferences window. This helps a user, who has e.g. a lot of items, but the preferences window with a low height, to easily move any item to any position.
This commit is contained in:
		
							parent
							
								
									a4ea0c630a
								
							
						
					
					
						commit
						edfa50f254
					
				
							
								
								
									
										24
									
								
								src/prefs.js
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/prefs.js
									
									
									
									
									
								
							| @ -27,6 +27,7 @@ const Me = ExtensionUtils.getCurrentExtension(); | ||||
| 
 | ||||
| const PrefsBoxOrderListEmptyPlaceholder = Me.imports.prefsModules.PrefsBoxOrderListEmptyPlaceholder; | ||||
| const PrefsBoxOrderItemRow = Me.imports.prefsModules.PrefsBoxOrderItemRow; | ||||
| const ScrollManager = Me.imports.prefsModules.ScrollManager; | ||||
| 
 | ||||
| var PrefsWidget = GObject.registerClass({ | ||||
|     GTypeName: "PrefsWidget", | ||||
| @ -63,12 +64,33 @@ var PrefsWidget = GObject.registerClass({ | ||||
|             window.default_height = 750; | ||||
|         }); | ||||
| 
 | ||||
|         // Scroll up or down, when a Drag-and-Drop operation is in progress and
 | ||||
|         // the user has their cursor either in the upper or lower 10% of this
 | ||||
|         // widget respectively.
 | ||||
|         this._scrollManager = new ScrollManager.ScrollManager(this); | ||||
|         let controller = new Gtk.DropControllerMotion(); | ||||
|         controller.connect("motion", (_, x, y) => { | ||||
|             // If the pointer is currently in the upper ten percent of this
 | ||||
|             // widget, then scroll up.
 | ||||
|             if (y <= this.get_allocated_height() * 0.1) this._scrollManager.startScrollUp(); | ||||
|             // If the pointer is currently in the lower ten percent of this
 | ||||
|             // widget, then scroll down.
 | ||||
|             else if (y >= this.get_allocated_height() * 0.9) this._scrollManager.startScrollDown(); | ||||
|             // Otherwise stop scrolling.
 | ||||
|             else this._scrollManager.stopScrollAll(); | ||||
|         }); | ||||
|         controller.connect("leave", () => { | ||||
|             // Stop scrolling on leave.
 | ||||
|             this._scrollManager.stopScrollAll(); | ||||
|         }); | ||||
|         this.add_controller(controller); | ||||
| 
 | ||||
|         // 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.PrefsBoxOrderItemRow(); | ||||
|                 const listBoxRow = new PrefsBoxOrderItemRow.PrefsBoxOrderItemRow({}, this._scrollManager); | ||||
| 
 | ||||
|                 listBoxRow.item = item; | ||||
|                 if (item.startsWith("appindicator-kstatusnotifieritem-")) { | ||||
|  | ||||
| @ -31,7 +31,7 @@ var PrefsBoxOrderItemRow = GObject.registerClass({ | ||||
|     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 = {}) { | ||||
|     _init(params = {}, scrollManager) { | ||||
|         super._init(params); | ||||
| 
 | ||||
|         // Make `this` draggable by creating a drag source and adding it to
 | ||||
| @ -41,6 +41,10 @@ var PrefsBoxOrderItemRow = GObject.registerClass({ | ||||
|         dragSource.connect("prepare", () => { | ||||
|             return Gdk.ContentProvider.new_for_value(this); | ||||
|         }); | ||||
|         // Stop all scrolling, which is due to this DND operation.
 | ||||
|         dragSource.connect("drag-end", () => { | ||||
|             scrollManager.stopScrollAll(); | ||||
|         }); | ||||
|         this.add_controller(dragSource); | ||||
| 
 | ||||
|         /// Make `this` accept drops by creating a drop target and adding it to
 | ||||
|  | ||||
							
								
								
									
										99
									
								
								src/prefsModules/ScrollManager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/prefsModules/ScrollManager.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| "use strict"; | ||||
| /* | ||||
|  * 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 ScrollManager */ | ||||
| const GLib = imports.gi.GLib; | ||||
| 
 | ||||
| var ScrollManager = class ScrollManager { | ||||
|     /** | ||||
|      * @param {Gtk.ScrolledWindow} gtkScrolledWindow | ||||
|      */ | ||||
|     constructor(gtkScrolledWindow) { | ||||
|         this._gtkScrolledWindow = gtkScrolledWindow; | ||||
| 
 | ||||
|         this._scrollUp = false; | ||||
|         this._scrollDown = false; | ||||
|     } | ||||
| 
 | ||||
|     startScrollUp() { | ||||
|         // If the scroll up is already started, don't do anything.
 | ||||
|         if (this._scrollUp) return; | ||||
| 
 | ||||
|         // Make sure scroll down is stopped.
 | ||||
|         this.stopScrollDown(); | ||||
| 
 | ||||
|         this._scrollUp = true; | ||||
| 
 | ||||
|         GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => { | ||||
|             // Set the new vadjustment value to either the current value minus a
 | ||||
|             // step increment or to 0.
 | ||||
|             const newVAdjustementValue = Math.max(this._gtkScrolledWindow.vadjustment.get_value() - this._gtkScrolledWindow.vadjustment.get_step_increment(), 0); | ||||
| 
 | ||||
|             // If the new value is the old one, return and stop this interval.
 | ||||
|             if (newVAdjustementValue === this._gtkScrolledWindow.vadjustment.get_value()) { | ||||
|                 this._scrollUp = false; | ||||
|                 return this._scrollUp; | ||||
|             } | ||||
|             // Otherwise, update the value.
 | ||||
|             this._gtkScrolledWindow.vadjustment.set_value(newVAdjustementValue); | ||||
|             return this._scrollUp; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     startScrollDown() { | ||||
|         // If the scroll down is already started, don't do anything.
 | ||||
|         if (this._scrollDown) return; | ||||
| 
 | ||||
|         // Make sure scroll up is stopped.
 | ||||
|         this.stopScrollUp(); | ||||
| 
 | ||||
|         this._scrollDown = true; | ||||
| 
 | ||||
|         GLib.timeout_add(GLib.PRIORITY_DEFAULT, 200, () => { | ||||
|             // Set the new vadjusment value either to the curent value plus a
 | ||||
|             // step increment or to the upper value minus the page size.
 | ||||
|             const newVAdjustementValue = Math.min( | ||||
|                 this._gtkScrolledWindow.vadjustment.get_value() + this._gtkScrolledWindow.vadjustment.get_step_increment(), | ||||
|                 this._gtkScrolledWindow.vadjustment.get_upper() - this._gtkScrolledWindow.vadjustment.get_page_size() | ||||
|             ); | ||||
| 
 | ||||
|             // If the new value is the old one, return and stop this interval.
 | ||||
|             if (newVAdjustementValue === this._gtkScrolledWindow.vadjustment.get_value()) { | ||||
|                 this._scrollDown = false; | ||||
|                 return this._scrollDown; | ||||
|             } | ||||
|             // Otherwise, update the value.
 | ||||
|             this._gtkScrolledWindow.vadjustment.set_value(newVAdjustementValue); | ||||
|             return this._scrollDown; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     stopScrollUp() { | ||||
|         this._scrollUp = false; | ||||
|     } | ||||
| 
 | ||||
|     stopScrollDown() { | ||||
|         this._scrollDown = false; | ||||
|     } | ||||
| 
 | ||||
|     stopScrollAll() { | ||||
|         this.stopScrollUp(); | ||||
|         this.stopScrollDown(); | ||||
|     } | ||||
| }; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user