extensions: Make ExtensionPreferences more flexible

Extensions must now export a class with a fillPreferencesWindow()
method in their prefs. That is less convenient for extensions
with simple preferences than the old buildPrefsWidget() hook, as
they must wrap their widget in page/group widgets.

Address this by adding a default fillPreferencesWindow() implementation
that calls a getPreferencesWidget() method and wraps it as necessary.

This is flexible enough to support different cases fairly conveniently,
from simple single-widget prefs over tweaking the window to complex
multi-page prefs:

```js
class SimplePreferences extends ExtensionPreferences {
    getPreferencesWidget() {
        return new SimplePrefsWidget();
    }
}

class TinkerPreferences extends ExtensionPreferences {
    getPreferencesWidget() {
        return new SimplePrefsWidget();
    }

    fillPreferencesWindow(window) {
        super.fillPreferencesWindow(window);

        window.set_default_size(123, 456);
    }
}

class FullPreferences extends ExtensionPreferences {
    fillPreferencesWindow(window) {
        const page1 = new GeneralPage();
        window.add(page1);

        const page2 = new FoobarPage();
        window.add(page2);
    }
}
```

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2838>
This commit is contained in:
Florian Müllner 2023-07-10 05:53:45 +02:00
parent 0483dd31f0
commit 797df4f52f

View File

@ -1,3 +1,4 @@
import Adw from 'gi://Adw';
import GObject from 'gi://GObject'; import GObject from 'gi://GObject';
import {ExtensionBase, GettextWrapper} from './sharedInternals.js'; import {ExtensionBase, GettextWrapper} from './sharedInternals.js';
@ -13,13 +14,45 @@ export class ExtensionPreferences extends ExtensionBase {
return wrapper.defineTranslationFunctions(); return wrapper.defineTranslationFunctions();
} }
/**
* Get the single widget that implements
* the extension's preferences.
*
* @returns {Gtk.Widget}
*/
getPreferencesWidget() {
throw new GObject.NotImplementedError();
}
/** /**
* Fill the preferences window with preferences. * Fill the preferences window with preferences.
* *
* @param {Adw.PreferencesWindow} _window - the preferences window * The default implementation adds the widget
* returned by getPreferencesWidget().
*
* @param {Adw.PreferencesWindow} window - the preferences window
*/ */
fillPreferencesWindow(_window) { fillPreferencesWindow(window) {
throw new GObject.NotImplementedError(); const widget = this.getPreferencesWidget();
const page = this._wrapWidget(widget);
window.add(page);
}
_wrapWidget(widget) {
if (widget instanceof Adw.PreferencesPage)
return widget;
const page = new Adw.PreferencesPage();
if (widget instanceof Adw.PreferencesGroup) {
page.add(widget);
return page;
}
const group = new Adw.PreferencesGroup();
group.add(widget);
page.add(group);
return page;
} }
} }