diff --git a/prefs.js b/prefs.js index 74a03be..933837c 100644 --- a/prefs.js +++ b/prefs.js @@ -31,9 +31,6 @@ const Me = imports.misc.extensionUtils.getCurrentExtension(); const utils = Me.imports.src.utils; const ProfileManager = Me.imports.src.ProfileManager.ProfileManager; -// This template widget class is defined at the bottom of this file. -var BurnMyWindowsEffectPage = null; - ////////////////////////////////////////////////////////////////////////////////////////// // The preferences dialog is organized in pages, each of which is loaded from a // // separate ui file. There's one page with general options, all other paged are loaded // @@ -48,26 +45,26 @@ var PreferencesDialog = class PreferencesDialog { // New effects must be registered here and in extension.js. this._ALL_EFFECTS = [ - new Me.imports.src.effects.Apparition.Apparition(), - new Me.imports.src.effects.BrokenGlass.BrokenGlass(), - new Me.imports.src.effects.Doom.Doom(), - new Me.imports.src.effects.EnergizeA.EnergizeA(), - new Me.imports.src.effects.EnergizeB.EnergizeB(), - new Me.imports.src.effects.Fire.Fire(), - new Me.imports.src.effects.Glide.Glide(), - new Me.imports.src.effects.Glitch.Glitch(), - new Me.imports.src.effects.Hexagon.Hexagon(), - new Me.imports.src.effects.Incinerate.Incinerate(), - new Me.imports.src.effects.Matrix.Matrix(), - new Me.imports.src.effects.Pixelate.Pixelate(), - new Me.imports.src.effects.PixelWheel.PixelWheel(), - new Me.imports.src.effects.PixelWipe.PixelWipe(), - new Me.imports.src.effects.Portal.Portal(), - new Me.imports.src.effects.SnapOfDisintegration.SnapOfDisintegration(), - new Me.imports.src.effects.TRexAttack.TRexAttack(), - new Me.imports.src.effects.TVEffect.TVEffect(), - new Me.imports.src.effects.TVGlitch.TVGlitch(), - new Me.imports.src.effects.Wisps.Wisps(), + // new Me.imports.src.effects.Apparition.Apparition(), + // new Me.imports.src.effects.BrokenGlass.BrokenGlass(), + // new Me.imports.src.effects.Doom.Doom(), + // new Me.imports.src.effects.EnergizeA.EnergizeA(), + // new Me.imports.src.effects.EnergizeB.EnergizeB(), + // new Me.imports.src.effects.Fire.Fire(), + // new Me.imports.src.effects.Glide.Glide(), + // new Me.imports.src.effects.Glitch.Glitch(), + // new Me.imports.src.effects.Hexagon.Hexagon(), + // new Me.imports.src.effects.Incinerate.Incinerate(), + // new Me.imports.src.effects.Matrix.Matrix(), + // new Me.imports.src.effects.Pixelate.Pixelate(), + // new Me.imports.src.effects.PixelWheel.PixelWheel(), + // new Me.imports.src.effects.PixelWipe.PixelWipe(), + // new Me.imports.src.effects.Portal.Portal(), + // new Me.imports.src.effects.SnapOfDisintegration.SnapOfDisintegration(), + // new Me.imports.src.effects.TRexAttack.TRexAttack(), + // new Me.imports.src.effects.TVEffect.TVEffect(), + // new Me.imports.src.effects.TVGlitch.TVGlitch(), + // new Me.imports.src.effects.Wisps.Wisps(), ]; // Load all of our resources. @@ -92,9 +89,6 @@ var PreferencesDialog = class PreferencesDialog { Gtk.IconTheme.get_default().add_resource_path('/img'); } - // Register the template widgets used in the settings dialog. - this._registerCustomClasses(); - // Load the general user interface files. this._builder = new Gtk.Builder(); this._builder.add_from_resource(`/ui/common/menus.ui`); @@ -129,12 +123,19 @@ var PreferencesDialog = class PreferencesDialog { // Maybe the service is masked... } - this._builder.get_object('profile-power-profile').set_visible(hasPowerProfiles); + let powerProfileRow = this._builder.get_object('profile-power-profile'); + if (!utils.isADW()) { + powerProfileRow = powerProfileRow.get_parent().get_parent(); + } + powerProfileRow.set_visible(hasPowerProfiles); // The global color scheme is only available starting with GNOME Shell 42. We hide the // corresponding settings row on older versions. - this._builder.get_object('profile-color-scheme') - .set_visible(utils.shellVersionIsAtLeast(42, 0)); + let colorSchemeRow = this._builder.get_object('profile-color-scheme'); + if (!utils.isADW()) { + colorSchemeRow = colorSchemeRow.get_parent().get_parent(); + } + colorSchemeRow.set_visible(utils.shellVersionIsAtLeast(42, 0)); this._builder.get_object('profile-choose-app-button').connect('clicked', () => { Gio.DBus.session.call('org.gnome.Shell', @@ -154,138 +155,82 @@ var PreferencesDialog = class PreferencesDialog { } }); - // Starting with GNOME Shell 42, the settings dialog uses libadwaita. We use this to - // create a completely different layout for the settings dialog. - if (utils.isADW()) { + // This is our top-level widget which we will return later. + this._widget = this._builder.get_object('general-prefs'); - // This is our top-level widget which we will return later. - this._widget = this._builder.get_object('general-prefs'); + // Then add a preferences group for the effect expander rows. + const group = this._builder.get_object('effects-group'); - // Then add a preferences group for the effect expander rows. - const group = this._builder.get_object('effects-group'); + // This stores all expander rows for the effects. We use this to implement the + // accordion-like behavior of the effect settings. + this._effectRows = []; - // This stores all expander rows for the effects. We use this to implement the - // accordion-functionality of the effect settings. - this._effectRows = []; + // Now add all the rows. + this._ALL_EFFECTS.forEach(effect => { + const [minMajor, minMinor] = effect.getMinShellVersion(); + if (utils.shellVersionIsAtLeast(minMajor, minMinor)) { - // Now add all the rows. - this._ALL_EFFECTS.forEach(effect => { - const [minMajor, minMinor] = effect.getMinShellVersion(); - if (utils.shellVersionIsAtLeast(minMajor, minMinor)) { + const uiFile = `/ui/${utils.getUIDir()}/${effect.getNick()}.ui`; + const [hasPrefs] = Gio.resources_get_info(uiFile, 0); - const uiFile = `/ui/${utils.getUIDir()}/${effect.getNick()}.ui`; - const [hasPrefs] = Gio.resources_get_info(uiFile, 0); + let row; + if (hasPrefs) { + // Add the settings page to the builder. + this._builder.add_from_resource(uiFile); - let row; - if (hasPrefs) { - // Add the settings page to the builder. - this._builder.add_from_resource(uiFile); - - // Add the effect's preferences (if any). - row = this._builder.get_object(`${effect.getNick()}-prefs`); - } else { - row = Adw.ActionRow.new(); - } - - // On older versions of Adw (e.g. on GNOME Shell <43), the set_use_markup() does - // not yet exist. - if (row.set_use_markup) { - row.set_title('' + effect.getLabel() + ''); - row.set_use_markup(true); - } else { - row.set_title(effect.getLabel()); - } - - // Un-expand any previously expanded effect row. This way we ensure that there - // is only one expanded row at any time. - if (hasPrefs) { - row.connect('notify::expanded', currentRow => { - if (currentRow.get_expanded()) { - this._effectRows.forEach(row => { - if (row != currentRow && row.set_expanded) { - row.set_expanded(false); - } - }); - } - }); - } - - // The preview button. - const previewButton = Gtk.Button.new_from_icon_name('bmw-preview-symbolic'); - previewButton.add_css_class('circular'); - previewButton.add_css_class('flat'); - previewButton.set_tooltip_text(_('Preview this effect')); - previewButton.set_valign(Gtk.Align.CENTER); - row.add_action(previewButton); - - previewButton.connect('clicked', () => { - this._previewEffect(effect); - }); - - // Now add the toggle button for enabling and disabling the effect. - const button = Gtk.Switch.new(); - button.set_tooltip_text(_('Use this effect')); - button.set_valign(Gtk.Align.CENTER); - this._builder.expose_object(`${effect.getNick()}-enable-effect`, button); - - row.add_prefix(button); - group.add(row); - - this._effectRows.push(row); + // Add the effect's preferences (if any). + row = this._builder.get_object(`${effect.getNick()}-prefs`); + } else { + row = Adw.ActionRow.new(); } - }); - } - // On older GNOME versions, we use a StackSidebar. The code below works on GTK3 and - // GTK4. - else { - // This is our top-level widget which we will return later. - this._widget = new Gtk.Box({ - orientation: Gtk.Orientation.HORIZONTAL, - }); + // On older versions of Adw (e.g. on GNOME Shell <43), the set_use_markup() does + // not yet exist. + if (row.set_use_markup) { + row.set_title('' + effect.getLabel() + ''); + row.set_use_markup(true); + } else { + row.set_title(effect.getLabel()); + } - const stack = new Gtk.Stack({ - transition_type: Gtk.StackTransitionType.SLIDE_UP_DOWN, - }); - - // Add the general options page. - const generalPage = this._builder.get_object('general-prefs'); - generalPage.margin_start = 60; - generalPage.margin_end = 60; - stack.add_titled(generalPage, 'general', _('General Options')); - - this.gtkBoxAppend(this._widget, new Gtk.StackSidebar({stack: stack})); - this.gtkBoxAppend(this._widget, stack); - - // Add all other effect pages. - this._ALL_EFFECTS.forEach(effect => { - const [minMajor, minMinor] = effect.getMinShellVersion(); - if (utils.shellVersionIsAtLeast(minMajor, minMinor)) { - - const page = new BurnMyWindowsEffectPage(effect, this); - page.margin_start = 60; - page.margin_end = 60; - page.margin_top = 60; - page.margin_bottom = 60; - - const uiFile = `/ui/${utils.getUIDir()}/${effect.getNick()}.ui`; - const [hasPrefs] = Gio.resources_get_info(uiFile); - if (hasPrefs) { - - // Add the settings page to the builder. - this._builder.add_from_resource(uiFile); - - // Add the effect's preferences (if any). - const prefs = this._builder.get_object(`${effect.getNick()}-prefs`); - if (prefs) { - this.gtkBoxAppend(page, prefs); + // Un-expand any previously expanded effect row. This way we ensure that there + // is only one expanded row at any time. + if (hasPrefs) { + row.connect('notify::expanded', currentRow => { + if (currentRow.get_expanded()) { + this._effectRows.forEach(row => { + if (row != currentRow && row.set_expanded) { + row.set_expanded(false); + } + }); } - } - - stack.add_titled(page, effect.getNick(), effect.getLabel()); + }); } - }); - } + + // The preview button. + const previewButton = Gtk.Button.new_from_icon_name('bmw-preview-symbolic'); + previewButton.add_css_class('circular'); + previewButton.add_css_class('flat'); + previewButton.set_tooltip_text(_('Preview this effect')); + previewButton.set_valign(Gtk.Align.CENTER); + row.add_action(previewButton); + + previewButton.connect('clicked', () => { + this._previewEffect(effect); + }); + + // Now add the toggle button for enabling and disabling the effect. + const button = Gtk.Switch.new(); + button.set_tooltip_text(_('Use this effect')); + button.set_valign(Gtk.Align.CENTER); + this._builder.expose_object(`${effect.getNick()}-enable-effect`, button); + + row.add_prefix(button); + group.add(row); + + this._effectRows.push(row); + } + }); // Some things can only be done once the widget is shown as we do not have access to // the toplevel widget before. @@ -309,7 +254,7 @@ var PreferencesDialog = class PreferencesDialog { // Starting with GNOME Shell 42, we have to hack our way through the widget tree // of the Adw.PreferencesWindow... - if (Adw && utils.shellVersionIsAtLeast(42, 'beta')) { + if (utils.isADW()) { const header = this._findWidgetByType(window.get_content(), Adw.HeaderBar); header.pack_start(menu); header.set_title_widget(this._builder.get_object('profile-button')); @@ -330,6 +275,7 @@ var PreferencesDialog = class PreferencesDialog { } else { window.get_titlebar().pack_start(menu); + window.get_titlebar().set_title_widget(this._builder.get_object('profile-button')); } const addURIAction = (name, uri) => { @@ -473,7 +419,7 @@ var PreferencesDialog = class PreferencesDialog { const dialogTitle = _('Delete this Profile?'); const dialogSubtitle = _('The current effect profile will be permanently lost.'); - if (Adw.MessageDialog) { + if (utils.isADW() && Adw.MessageDialog) { deleteProfileDialog = new Adw.MessageDialog({heading: dialogTitle, body: dialogSubtitle}); deleteProfileDialog.add_response('cancel', _('Cancel')); @@ -495,7 +441,7 @@ var PreferencesDialog = class PreferencesDialog { deleteProfileDialog.set_hide_on_close(true); deleteProfileDialog.set_transient_for(window); - deleteProfileDialog.connect('response', (d, response) => { + deleteProfileDialog.connect('response', (dialog, response) => { if (response == 'delete' || response == Gtk.ResponseType.OK) { // Stop editing the current profile. this._builder.get_object('edit-profile-button').active = false; @@ -512,7 +458,7 @@ var PreferencesDialog = class PreferencesDialog { this._updateProfileMenu(); } - d.hide(); + dialog.hide(); }); const deleteProfileAction = Gio.SimpleAction.new('profile-delete', null); @@ -557,10 +503,16 @@ var PreferencesDialog = class PreferencesDialog { return this._widget; } - // Connects a Gtk.ComboBox (or anything else which has an 'selected' property) to a + // Connects an Adw.ComboRow (or anything else which has an 'selected' property) to a + // settings key. It also binds the corresponding reset button. + bindComboRow(settingsKey) { + this._bind(settingsKey, 'selected'); + } + + // Connects a Gtk.ComboBox (or anything else which has an 'active' property) to a // settings key. It also binds the corresponding reset button. bindComboBox(settingsKey) { - this._bind(settingsKey, 'selected'); + this._bind(settingsKey, 'active'); } // Connects a Gtk.Entry (or anything else which has an 'text' property) to a @@ -664,11 +616,20 @@ var PreferencesDialog = class PreferencesDialog { updateProfileButtonMenuIfChanged('profile-power-profile'); this.bindEntry('profile-app'); - this.bindComboBox('profile-animation-type'); - this.bindComboBox('profile-window-type'); - this.bindComboBox('profile-color-scheme'); - this.bindComboBox('profile-power-mode'); - this.bindComboBox('profile-power-profile'); + + if (utils.isADW()) { + this.bindComboRow('profile-animation-type'); + this.bindComboRow('profile-window-type'); + this.bindComboRow('profile-color-scheme'); + this.bindComboRow('profile-power-mode'); + this.bindComboRow('profile-power-profile'); + } else { + this.bindComboBox('profile-animation-type'); + this.bindComboBox('profile-window-type'); + this.bindComboBox('profile-color-scheme'); + this.bindComboBox('profile-power-mode'); + this.bindComboBox('profile-power-profile'); + } this.bindSwitch('profile-high-priority'); // Connect all effect settings. @@ -826,34 +787,6 @@ var PreferencesDialog = class PreferencesDialog { window.show_all(); } } - - // Initializes template widgets used by the preferences dialog. - _registerCustomClasses() { - - // If we are not using libadwaita, each effect page is based on a template widget. - // This template contains the title and the preview button. - if (!utils.isADW() && GObject.type_from_name('BurnMyWindowsEffectPage') == null) { - BurnMyWindowsEffectPage = GObject.registerClass( - { - GTypeName: 'BurnMyWindowsEffectPage', - Template: `resource:///ui/${utils.getUIDir()}/effectPage.ui`, - InternalChildren: ['label', 'button'], - }, - class BurnMyWindowsEffectPage extends Gtk.Box { // ------------------------------ - _init(effect, dialog) { - super._init(); - - // Set the effect's name as label. - this._label.label = effect.getLabel(); - - // Open the preview window once the preview button is clicked. - this._button.connect('clicked', () => { - dialog._previewEffect(effect); - }); - } - }); - } - } } // This is used for setting up the translations. diff --git a/resources/ui/gtk4/effectPage.ui b/resources/ui/gtk4/effectPage.ui deleted file mode 100644 index 6241b13..0000000 --- a/resources/ui/gtk4/effectPage.ui +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/resources/ui/gtk4/prefs.ui b/resources/ui/gtk4/prefs.ui index a20ade9..6836ff0 100644 --- a/resources/ui/gtk4/prefs.ui +++ b/resources/ui/gtk4/prefs.ui @@ -8,201 +8,395 @@ SPDX-License-Identifier: GPL-3.0-or-later - - + main-menu heart-filled-symbolic + + + center + + + profile-menu + + + + + bmw-edit-profile-symbolic + center + + + profile-editor-revealer + + + + + + vertical - 60 - 60 - + + + + edit-profile-button + + + + + vertical + 20 + 20 + 20 + 20 + 5 + + + + Effect Profile Constraints + start + + + + + + + Define when the current effect settings should be used. + start + + + + + + 5 + 15 + + + none + 1 + + + + + 0 + + + + + Application Name + 0 + start + center + 1 + + + + + + center + + + + + 200 + + + + + + bmw-select-app-symbolic + center + + + + + + + + + + + + 0 + + + + + Animation Type + 0 + start + center + 1 + + + + + 200 + + Any + Opening Windows + Closing Windows + + + + + + + + + + + 0 + + + + + Window Type + 0 + start + center + 1 + + + + + 200 + + Any + Normal Windows + Dialog Windows + + + + + + + + + + + 0 + + + + + Color Scheme + 0 + start + center + 1 + + + + + 200 + + Any + Default Color Scheme + Dark Color Scheme + + + + + + + + + + + 0 + + + + + Power Mode + 0 + start + center + 1 + + + + + 200 + + Any + On Battery + Plugged In + + + + + + + + + + + 0 + + + + + Power Profile + 0 + start + center + 1 + + + + + 200 + + Any + Power-Saver Mode + Balanced Mode + Performance Mode + Power Saver or Balanced + Balanced or Performance + + + + + + + + + + + + + + + + Advanced Profile Options + start + + + + + + + 5 + 15 + + + none + 1 + + + + + 0 + + + + + vertical + 3 + + + High Priority + 0 + start + center + 1 + + + + + Force using this profile even if it has less constraints than another matching profile. + 0 + start + center + 1 + end + + + + + + + + center + + + + + + + + + + + + + + + prefs.profile-delete + Delete this Profile... + start + + + + + + + + + + + + Effect Settings + 0 + start center - burn-my-windows-symbolic - 128 + 1 - - Welcome to Burn-My-Windows! - 8 - 6 + If multiple are selected, one is chosen randomly. + 0 + start + center + 1 - - - If you like this extension, recommend it to your friends :) - 36 - - - - + none 1 - - - - 0 - - - - - vertical - 3 - - - Enabled Effects - 0 - start - center - 1 - - - - - If multiple are selected, one is chosen randomly. - 0 - start - center - 1 - - - - - - - - Choose Effects - enabled-effects-menu - - - - - - - - - - 0 - - - - - Also Add Effects to Dialogs - 0 - start - center - 1 - - - - - end - center - - - - - edit-clear-symbolic - Reset to Default Value - - - - - - - - - - - 0 - - - - - Disable on Battery Power - 0 - start - center - 1 - - - - - end - center - - - - - edit-clear-symbolic - Reset to Default Value - - - - - - - - - - - 0 - - - - - Disable in Power-Save Mode - 0 - start - center - 1 - - - - - end - center - - - - - edit-clear-symbolic - Reset to Default Value - - - - - - - -