🔧 Use libadwaita for the settings dialog

This commit is contained in:
Simon Schneegans
2022-02-18 17:43:40 +01:00
parent 0886007e98
commit 41fcaf04ff
6 changed files with 461 additions and 402 deletions
+126 -4
View File
@@ -16,6 +16,14 @@
const {Gio, Gtk, Gdk, GLib, GObject} = imports.gi; const {Gio, Gtk, Gdk, GLib, GObject} = imports.gi;
const ByteArray = imports.byteArray; const ByteArray = imports.byteArray;
// libadwaita is available starting with GNOME Shell 42.
let Adw = null;
try {
Adw = imports.gi.Adw;
} catch (e) {
// Nothing to do.
}
const _ = imports.gettext.domain('burn-my-windows').gettext; const _ = imports.gettext.domain('burn-my-windows').gettext;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
@@ -86,13 +94,105 @@ var PreferencesDialog = class PreferencesDialog {
// Bind general options properties. // Bind general options properties.
this.bindSwitch('destroy-dialogs'); this.bindSwitch('destroy-dialogs');
// Starting with GNOME Shell 42, the settings dialog uses libadwaita. We have to use a
// different layout, as the stack sidebar looks pretty ugly with the included
// Adw.Clamp...
if (utils.shellVersionIsAtLeast(42, 'beta')) {
// This is our top-level widget which we will return later.
this._widget = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL});
// Add the general options page to the settings dialog.
const generalPrefs = this._builder.get_object('general-prefs');
this.gtkBoxAppend(this._widget, generalPrefs);
// Then add a preferences group with action rows to open the effect subpages.
const group = new Adw.PreferencesGroup({title: _('Effect Options')});
this.gtkBoxAppend(this._widget, group);
ALL_EFFECTS.forEach(Effect => {
const [minMajor, minMinor] = Effect.getMinShellVersion();
if (utils.shellVersionIsAtLeast(minMajor, minMinor)) {
const row = new Adw.ActionRow({title: Effect.getLabel(), activatable: true});
row.add_suffix(new Gtk.Image({icon_name: 'go-next-symbolic'}));
// Open a subpage with the effect's settings.
row.connect('activated', () => {
const page = new BurnMyWindowsEffectPage(Effect, this);
page.valign = Gtk.Align.CENTER;
page.margin_top = 10;
page.margin_bottom = 10;
page.margin_start = 10;
page.margin_end = 10;
// Add the Effect's preferences (if any).
const preferences = Effect.getPreferences(this);
if (preferences) {
this.gtkBoxAppend(page, preferences);
}
// Add a button for back navigation.
const backButton = new Gtk.Button({
halign: Gtk.Align.CENTER,
label: _('Go Back'),
});
backButton.add_css_class('suggested-action');
backButton.add_css_class('pill-button');
backButton.connect('clicked', () => {
row.get_root().close_subpage();
});
this.gtkBoxAppend(page, backButton);
// Wrap the preferences group in an Adw.Clamp.
const clamp = new Adw.Clamp({
child: page,
maximum_size: 600,
tightening_threshold: 400,
});
// Open the subpage on click.
row.get_root().present_subpage(clamp);
});
group.add(row);
}
});
}
// On older GNOME versions, we use a StackSidebar.
else {
// This is our top-level widget which we will return later.
this._widget = new Gtk.Box({
orientation: Gtk.Orientation.HORIZONTAL,
margin_start: 50,
margin_end: 50,
});
const stack = new Gtk.Stack({
transition_type: Gtk.StackTransitionType.SLIDE_UP_DOWN,
});
// Add the general options page.
stack.add_titled(
this._builder.get_object('general-prefs'), 'general', _('General Options'));
this.gtkBoxAppend(this._widget, new Gtk.StackSidebar({stack: stack}));
this.gtkBoxAppend(this._widget, stack);
// Add all other effect pages. // Add all other effect pages.
const stack = this._builder.get_object('main-stack');
ALL_EFFECTS.forEach(Effect => { ALL_EFFECTS.forEach(Effect => {
const [minMajor, minMinor] = Effect.getMinShellVersion(); const [minMajor, minMinor] = Effect.getMinShellVersion();
if (utils.shellVersionIsAtLeast(minMajor, minMinor)) { if (utils.shellVersionIsAtLeast(minMajor, minMinor)) {
const page = new BurnMyWindowsEffectPage(Effect, this); const page = new BurnMyWindowsEffectPage(Effect, this);
page.margin_start = 60;
page.margin_end = 60;
page.margin_top = 60;
page.margin_bottom = 60;
// Add the Effect's preferences (if any). // Add the Effect's preferences (if any).
const preferences = Effect.getPreferences(this); const preferences = Effect.getPreferences(this);
@@ -103,9 +203,7 @@ var PreferencesDialog = class PreferencesDialog {
stack.add_titled(page, Effect.getNick(), Effect.getLabel()); stack.add_titled(page, Effect.getNick(), Effect.getLabel());
} }
}); });
}
// This is our top-level widget which we will return later.
this._widget = this._builder.get_object('settings-widget');
// Some things can only be done once the widget is shown as we do not have access to // Some things can only be done once the widget is shown as we do not have access to
// the toplevel widget before. // the toplevel widget before.
@@ -119,7 +217,18 @@ var PreferencesDialog = class PreferencesDialog {
{ {
// Add the menu button to the title bar. // Add the menu button to the title bar.
const menu = this._builder.get_object('menu-button'); const menu = this._builder.get_object('menu-button');
// Starting with GNOME Shell 42, we have to hack our way through the widget tree
// of the Adw.PreferencesWindow...
if (utils.shellVersionIsAtLeast(42, 'beta')) {
const header = this._findWidgetByType(window.get_content(), Adw.HeaderBar);
header.pack_end(menu);
// Allow closing of the sub pages.
window.can_navigate_back = true;
} else {
window.get_titlebar().pack_end(menu); window.get_titlebar().pack_end(menu);
}
// Populate the menu with actions. // Populate the menu with actions.
const group = Gio.SimpleActionGroup.new(); const group = Gio.SimpleActionGroup.new();
@@ -353,6 +462,19 @@ var PreferencesDialog = class PreferencesDialog {
return JSON.parse(string); return JSON.parse(string);
} }
// This traverses the widget tree below the given parent recursively and returns the
// first widget of the given type.
_findWidgetByType(parent, type) {
for (const child of [...parent]) {
if (child instanceof type) return child;
const match = this._findWidgetByType(child, type);
if (match) return match;
}
return null;
}
// Initializes template widgets used by the preferences dialog. // Initializes template widgets used by the preferences dialog.
_registerCustomClasses() { _registerCustomClasses() {
+1 -5
View File
@@ -4,10 +4,6 @@
<template class="BurnMyWindowsEffectPage" parent="GtkBox"> <template class="BurnMyWindowsEffectPage" parent="GtkBox">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="margin-top">60</property>
<property name="margin-bottom">60</property>
<property name="margin-start">60</property>
<property name="margin-end">60</property>
<property name="hexpand">1</property> <property name="hexpand">1</property>
<property name="spacing">10</property> <property name="spacing">10</property>
@@ -44,8 +40,8 @@
</object> </object>
</child> </child>
<style> <style>
<class name="suggested-action" />
<class name="pill-button" /> <class name="pill-button" />
<class name="flat" />
</style> </style>
</object> </object>
</child> </child>
-27
View File
@@ -17,22 +17,8 @@
</child> </child>
</object> </object>
<object class="GtkBox" id="settings-widget">
<child>
<object class="GtkStackSidebar">
<property name="stack">main-stack</property>
</object>
</child>
<child>
<object class="GtkStack" id="main-stack">
<property name="transition-type">slide-up-down</property>
<property name="hexpand">1</property>
<child>
<object class="GtkBox" id="general-prefs"> <object class="GtkBox" id="general-prefs">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="margin-start">60</property>
<property name="margin-end">60</property>
<property name="margin-top">30</property> <property name="margin-top">30</property>
<property name="margin-bottom">30</property> <property name="margin-bottom">30</property>
@@ -246,18 +232,5 @@
</object> </object>
</child> </child>
</object> </object>
<packing>
<property name="name">general</property>
<property name="title" translatable="yes">General Options</property>
</packing>
</child>
<!-- Stack pages are inserted here -->
</object>
</child>
</object>
</interface> </interface>
+1 -5
View File
@@ -4,10 +4,6 @@
<template class="BurnMyWindowsEffectPage" parent="GtkBox"> <template class="BurnMyWindowsEffectPage" parent="GtkBox">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="margin-top">60</property>
<property name="margin-bottom">60</property>
<property name="margin-start">60</property>
<property name="margin-end">60</property>
<property name="hexpand">1</property> <property name="hexpand">1</property>
<property name="spacing">10</property> <property name="spacing">10</property>
@@ -44,8 +40,8 @@
</object> </object>
</property> </property>
<style> <style>
<class name="suggested-action" />
<class name="pill-button" /> <class name="pill-button" />
<class name="flat" />
</style> </style>
</object> </object>
</child> </child>
-28
View File
@@ -10,27 +10,8 @@
<property name="icon-name">open-menu-symbolic</property> <property name="icon-name">open-menu-symbolic</property>
</object> </object>
<object class="GtkBox" id="settings-widget">
<child>
<object class="GtkStackSidebar">
<property name="stack">main-stack</property>
</object>
</child>
<child>
<object class="GtkStack" id="main-stack">
<property name="transition-type">slide-up-down</property>
<property name="hexpand">1</property>
<child>
<object class="GtkStackPage">
<property name="name">general</property>
<property name="title" translatable="yes">General Options</property>
<property name="child">
<object class="GtkBox" id="general-prefs"> <object class="GtkBox" id="general-prefs">
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<property name="margin-start">60</property>
<property name="margin-end">60</property>
<property name="margin-top">60</property> <property name="margin-top">60</property>
<property name="margin-bottom">60</property> <property name="margin-bottom">60</property>
@@ -199,14 +180,5 @@
</child> </child>
</object> </object>
</property>
</object>
</child>
<!-- Stack pages are inserted here -->
</object>
</child>
</object>
</interface> </interface>
+1 -1
View File
@@ -124,7 +124,7 @@ var Fire = class Fire {
// This populates the preset dropdown menu for the fire options. // This populates the preset dropdown menu for the fire options.
static _createFirePresets(dialog) { static _createFirePresets(dialog) {
dialog.getBuilder().get_object('settings-widget').connect('realize', (widget) => { dialog.getBuilder().get_object('fire-prefs').connect('realize', (widget) => {
const presets = [ const presets = [
{ {
name: _('Default Fire'), name: _('Default Fire'),