mirror of
https://gitlab.gnome.org/june/top-bar-organizer.git
synced 2026-01-10 00:12:55 +01:00
Aside from introducing a bunch of type annotations and other code adjustments, also add explicit type checking where necessary. Inline #associateItem into the constructor in PrefsBoxOrderItemRow as the method sets this.item and: > Note that the field needs to be initialized in the constructor itself. > TypeScript does not analyze methods you invoke from the constructor to > detect initializations, because a derived class might override those > methods and fail to initialize the members. https://www.typescriptlang.org/docs/handbook/2/classes.html Explicitly ensure we actually have a Gdk.Drag in #setupDNDScroll in PrefsPage and explicitly only scroll when a DND operation is properly set up. Even tho previously not having a Gdk.Drag in #setupDNDScroll would probably just error out the callback and probably be just fine then, handling this explicitly is at least nicer. Also see the guide on using TypeScript for GNOME Shell Extensions, which was followed for this work to some degree: https://gjs.guide/extensions/development/typescript.html
152 lines
5.1 KiB
TypeScript
152 lines
5.1 KiB
TypeScript
"use strict";
|
|
|
|
import Gtk from "gi://Gtk";
|
|
import GObject from "gi://GObject";
|
|
import GLib from "gi://GLib";
|
|
import type Gio from "gi://Gio";
|
|
|
|
import { ExtensionPreferences } from "resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js";
|
|
|
|
import PrefsBoxOrderItemRow from "./PrefsBoxOrderItemRow.js";
|
|
import PrefsBoxOrderListEmptyPlaceholder from "./PrefsBoxOrderListEmptyPlaceholder.js";
|
|
|
|
export default class PrefsBoxOrderListBox extends Gtk.ListBox {
|
|
static {
|
|
GObject.registerClass({
|
|
GTypeName: "PrefsBoxOrderListBox",
|
|
Template: GLib.uri_resolve_relative(import.meta.url, "../ui/prefs-box-order-list-box.ui", GLib.UriFlags.NONE),
|
|
Properties: {
|
|
BoxOrder: GObject.ParamSpec.string(
|
|
"box-order",
|
|
"Box Order",
|
|
"The box order this PrefsBoxOrderListBox is associated with.",
|
|
GObject.ParamFlags.READWRITE,
|
|
""
|
|
),
|
|
},
|
|
Signals: {
|
|
"row-move": {
|
|
param_types: [PrefsBoxOrderItemRow.$gtype, GObject.TYPE_STRING],
|
|
},
|
|
},
|
|
}, this);
|
|
}
|
|
|
|
_boxOrder!: string;
|
|
#settings: Gio.Settings;
|
|
#rowSignalHandlerIds = new Map<PrefsBoxOrderItemRow, number[]>();
|
|
|
|
/**
|
|
* @param {Object} params
|
|
*/
|
|
constructor(params = {}) {
|
|
super(params);
|
|
|
|
// Load the settings.
|
|
this.#settings = ExtensionPreferences.lookupByURL(import.meta.url)!.getSettings();
|
|
|
|
// Add a placeholder widget for the case, where no GtkListBoxRows are
|
|
// present.
|
|
this.set_placeholder(new PrefsBoxOrderListEmptyPlaceholder());
|
|
}
|
|
|
|
get boxOrder(): string {
|
|
return this._boxOrder;
|
|
}
|
|
|
|
set boxOrder(value: string) {
|
|
this._boxOrder = value;
|
|
|
|
// Get the actual box order for the given box order name from settings.
|
|
const boxOrder = this.#settings.get_strv(this._boxOrder);
|
|
// Populate this GtkListBox with GtkListBoxRows for the items of the
|
|
// given configured box order.
|
|
for (const item of boxOrder) {
|
|
const row = new PrefsBoxOrderItemRow({}, item);
|
|
this.insertRow(row, -1);
|
|
}
|
|
|
|
this.determineRowMoveActionEnable();
|
|
this.notify("box-order");
|
|
}
|
|
|
|
/**
|
|
* Inserts the given PrefsBoxOrderItemRow to this list box at the given
|
|
* position.
|
|
* Also handles stuff like connecting signals.
|
|
*/
|
|
insertRow(row: PrefsBoxOrderItemRow, position: number): void {
|
|
this.insert(row, position);
|
|
|
|
const signalHandlerIds: number[] = [];
|
|
signalHandlerIds.push(row.connect("move", (row, direction) => {
|
|
this.emit("row-move", row, direction);
|
|
}));
|
|
|
|
this.#rowSignalHandlerIds.set(row, signalHandlerIds);
|
|
}
|
|
|
|
/**
|
|
* Removes the given PrefsBoxOrderItemRow from this list box.
|
|
* Also handles stuff like disconnecting signals.
|
|
*/
|
|
removeRow(row: PrefsBoxOrderItemRow): void {
|
|
const signalHandlerIds = this.#rowSignalHandlerIds.get(row) ?? [];
|
|
|
|
for (const id of signalHandlerIds) {
|
|
row.disconnect(id);
|
|
}
|
|
|
|
this.remove(row);
|
|
}
|
|
|
|
/**
|
|
* Saves the box order represented by `this` (and its
|
|
* `PrefsBoxOrderItemRows`) to settings.
|
|
*/
|
|
saveBoxOrderToSettings(): void {
|
|
let currentBoxOrder: string[] = [];
|
|
for (let potentialPrefsBoxOrderItemRow of this) {
|
|
// Only process PrefsBoxOrderItemRows.
|
|
if (!(potentialPrefsBoxOrderItemRow instanceof PrefsBoxOrderItemRow)) {
|
|
continue;
|
|
}
|
|
|
|
const item = potentialPrefsBoxOrderItemRow.item;
|
|
currentBoxOrder.push(item);
|
|
}
|
|
this.#settings.set_strv(this.boxOrder, currentBoxOrder);
|
|
}
|
|
|
|
/**
|
|
* Determines whether or not each move action of each PrefsBoxOrderItemRow
|
|
* should be enabled or disabled.
|
|
*/
|
|
determineRowMoveActionEnable(): void {
|
|
for (let potentialPrefsBoxOrderItemRow of this) {
|
|
// Only process PrefsBoxOrderItemRows.
|
|
if (!(potentialPrefsBoxOrderItemRow instanceof PrefsBoxOrderItemRow)) {
|
|
continue;
|
|
}
|
|
|
|
const row = potentialPrefsBoxOrderItemRow;
|
|
|
|
// If the current row is the topmost row in the topmost list box,
|
|
// then disable the move-up action.
|
|
if (row.get_index() === 0 && this.boxOrder === "left-box-order") {
|
|
row.action_set_enabled("row.move-up", false);
|
|
} else { // Else enable it.
|
|
row.action_set_enabled("row.move-up", true);
|
|
}
|
|
|
|
// If the current row is the bottommost row in the bottommost list
|
|
// box, then disable the move-down action.
|
|
const rowNextSibling = row.get_next_sibling();
|
|
if ((rowNextSibling instanceof PrefsBoxOrderListEmptyPlaceholder || rowNextSibling === null) && this.boxOrder === "right-box-order") {
|
|
row.action_set_enabled("row.move-down", false);
|
|
} else { // Else enable it.
|
|
row.action_set_enabled("row.move-down", true);
|
|
}
|
|
}
|
|
}
|
|
}
|