Skip to content

Commit

Permalink
Library: Add settings page and sidebar (#281)
Browse files Browse the repository at this point in the history
  • Loading branch information
danirabbit authored Jan 24, 2024
1 parent ccac16d commit 62403e8
Show file tree
Hide file tree
Showing 6 changed files with 485 additions and 0 deletions.
86 changes: 86 additions & 0 deletions lib/AbstractSettingsPage.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2017–2021 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

/**
* AbstractSettingsPage is a {@link Gtk.ScrolledWindow} subclass with properties used
* by other Granite settings widgets.
*/
public abstract class Switchboard.SettingsPage : Gtk.Box {
protected string _icon_name;
protected string _title;
private Gtk.ScrolledWindow scrolled;

/**
* Used to display a status icon overlayed on the display_widget in a Granite.SettingsSidebar
*/
public enum StatusType {
ERROR,
OFFLINE,
SUCCESS,
WARNING,
NONE
}

/**
* Selects a colored icon to be displayed in a Granite.SettingsSidebar
*/
public StatusType status_type { get; set; default = StatusType.NONE; }

/**
* A widget to display in place of an icon in a Granite.SettingsSidebar
*/
public Gtk.Widget? display_widget { get; construct; }

/**
* A header to be sorted under in a Granite.SettingsSidebar
*/
public string? header { get; construct; }

/**
* A status string to be displayed underneath the title in a Granite.SettingsSidebar
*/
public string status { get; set construct; }

/**
* An icon name to be displayed in a Granite.SettingsSidebar
*/
public string? icon_name {
get {
return _icon_name;
}
construct set {
_icon_name = value;
}
}

/**
* A title to be displayed in a Granite.SettingsSidebar
*/
public string title {
get {
return _title;
}
construct set {
_title = value;
}
}

public new Gtk.Widget child {
get {
return scrolled.child;
}
set {
scrolled.child = value;
}
}

construct {
scrolled = new Gtk.ScrolledWindow () {
hscrollbar_policy = Gtk.PolicyType.NEVER
};

append (scrolled);
}
}
132 changes: 132 additions & 0 deletions lib/AbstractSimpleSettingsPage.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright 2017–2022 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-2.0-or-later
*/

/**
* SimpleSettingsPage is a widget divided into three sections: a predefined header,
* a content area, and an action area.
*/

public abstract class Switchboard.SimpleSettingsPage : Switchboard.SettingsPage {
private Gtk.Label description_label;
private string _description;

/**
* A {@link Gtk.Box} used as the action area for #this
*/
public Gtk.Box action_area { get; construct; }

/**
* A {@link Gtk.Grid} used as the content area for #this
*/
public Gtk.Grid content_area { get; construct; }

/**
* A {@link Gtk.Switch} that appears in the header area when #this.activatable is #true. #status_switch will be #null when #this.activatable is #false
*/
public Gtk.Switch? status_switch { get; construct; }

/**
* Creates a {@link Gtk.Switch} #status_switch in the header of #this
*/
public bool activatable { get; construct; }

/**
* Creates a {@link Gtk.Label} with a page description in the header of #this
*/
public string description {
get {
return _description;
}
construct set {
if (description_label != null) {
description_label.label = value;
}
_description = value;
}
}

/**
* Creates a new SimpleSettingsPage
* Deprecated: Subclass this instead.
*/
protected SimpleSettingsPage () {

}

class construct {
set_css_name ("simplesettingspage");
}

construct {
var header_icon = new Gtk.Image.from_icon_name (icon_name) {
icon_size = Gtk.IconSize.LARGE,
valign = Gtk.Align.START
};

var title_label = new Gtk.Label (title) {
hexpand = true,
selectable = true,
wrap = true,
xalign = 0
};
title_label.add_css_class (Granite.STYLE_CLASS_H2_LABEL);

var header_area = new Gtk.Grid ();
header_area.add_css_class ("header-area");
header_area.attach (title_label, 1, 0);

if (description != null) {
description_label = new Gtk.Label (description) {
selectable = true,
use_markup = true,
wrap = true,
xalign = 0
};

header_area.attach (header_icon, 0, 0, 1, 2);
header_area.attach (description_label, 1, 1, 2);
} else {
header_area.attach (header_icon, 0, 0);
}

if (activatable) {
status_switch = new Gtk.Switch () {
valign = Gtk.Align.START
};
header_area.attach (status_switch, 2, 0);
}

content_area = new Gtk.Grid () {
column_spacing = 12,
row_spacing = 12,
vexpand = true
};
content_area.add_css_class ("content-area");

action_area = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) {
halign = Gtk.Align.END
};
action_area.add_css_class ("buttonbox");

var grid = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
grid.append (header_area);
grid.append (content_area);
grid.append (action_area);

child = grid;

notify["icon-name"].connect (() => {
if (header_icon != null) {
header_icon.icon_name = icon_name;
}
});

notify["title"].connect (() => {
if (title_label != null) {
title_label.label = title;
}
});
}
}
127 changes: 127 additions & 0 deletions lib/SettingsSidebar.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2017-2022 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: LGPL-2.1-or-later
*/

/**
* SettingsSidebar acts as a controller for a Gtk.Stack; it shows a row of buttons
* to switch between the various pages of the associated stack widget.
*
* All the content for the rows comes from the child properties of a Granite.SettingsPage
* inside of the Gtk.Stack
*/
public class Switchboard.SettingsSidebar : Gtk.Widget {
private Gtk.ListBox listbox;

/**
* The Gtk.Stack to control
*/
public Gtk.Stack stack { get; construct; }

/**
* The name of the currently visible Granite.SettingsPage
*/
public string? visible_child_name {
get {
var selected_row = listbox.get_selected_row ();

if (selected_row == null) {
return null;
} else {
return ((SettingsSidebarRow) selected_row).page.title;
}
}
set {
weak Gtk.Widget listbox_child = listbox.get_first_child ();
while (listbox_child != null) {
if (!(listbox_child is SettingsSidebarRow)) {
listbox_child = listbox_child.get_next_sibling ();
continue;
}

if (((SettingsSidebarRow) listbox_child).page.title == value) {
listbox.select_row ((Gtk.ListBoxRow) listbox_child);
break;
}

listbox_child = listbox_child.get_next_sibling ();
}
}
}

/**
* Create a new SettingsSidebar
*/
public SettingsSidebar (Gtk.Stack stack) {
Object (stack: stack);
}

static construct {
set_layout_manager_type (typeof (Gtk.BinLayout));
}

class construct {
set_css_name ("settingssidebar");
}

construct {
listbox = new Gtk.ListBox () {
hexpand = true,
activate_on_single_click = true,
selection_mode = Gtk.SelectionMode.SINGLE
};

var scrolled = new Gtk.ScrolledWindow () {
hscrollbar_policy = Gtk.PolicyType.NEVER,
child = listbox
};
scrolled.set_parent (this);

on_sidebar_changed ();
stack.pages.items_changed.connect (on_sidebar_changed);

listbox.row_selected.connect ((row) => {
stack.visible_child = ((SettingsSidebarRow) row).page;
});

listbox.set_header_func ((row, before) => {
var header = ((SettingsSidebarRow) row).header;
if (header != null) {
var label = new Gtk.Label (header) {
halign = Gtk.Align.START,
xalign = 0
};

label.add_css_class (Granite.STYLE_CLASS_H4_LABEL);
row.set_header (label);
}
});

stack.notify["visible-child-name"].connect (() => {
visible_child_name = stack.visible_child_name;
});
}

~SettingsSidebar () {
get_first_child ().unparent ();
}

private void on_sidebar_changed () {
weak Gtk.Widget listbox_child = listbox.get_first_child ();
while (listbox_child != null) {
weak Gtk.Widget next_child = listbox_child.get_next_sibling ();
listbox.remove (listbox_child);
listbox_child = next_child;
}

weak Gtk.Widget child = stack.get_first_child ();
while (child != null) {
if (child is SettingsPage) {
var row = new SettingsSidebarRow ((SettingsPage) child);
listbox.append (row);
}

child = child.get_next_sibling ();
}
}
}
Loading

0 comments on commit 62403e8

Please sign in to comment.