[gnome-games/wip/exalm/libhandy: 58/58] ui: Switch to custom sidebar
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/wip/exalm/libhandy: 58/58] ui: Switch to custom sidebar
- Date: Wed, 12 Sep 2018 11:55:16 +0000 (UTC)
commit f4ed309059a2b8c7c6987a27dea799c27ae4bb82
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date: Wed Sep 5 18:14:14 2018 +0500
ui: Switch to custom sidebar
data/gtk-style.css | 9 ++
data/ui/preferences-window.ui | 9 +-
src/meson.build | 1 +
src/ui/preferences-sidebar.vala | 225 ++++++++++++++++++++++++++++++++++++++++
src/ui/preferences-window.vala | 6 +-
5 files changed, 247 insertions(+), 3 deletions(-)
---
diff --git a/data/gtk-style.css b/data/gtk-style.css
index 83ae1888..9bfe4bb3 100644
--- a/data/gtk-style.css
+++ b/data/gtk-style.css
@@ -30,3 +30,12 @@ gamesgamethumbnail {
@theme_unfocused_bg_color;
border-color: @unfocused_borders;
}
+
+stacksidebar * {
+ border-left: none;
+ border-right: none;
+}
+
+separator.sidebar {
+ min-width: 0;
+}
diff --git a/data/ui/preferences-window.ui b/data/ui/preferences-window.ui
index 6cdec08c..a18319c2 100644
--- a/data/ui/preferences-window.ui
+++ b/data/ui/preferences-window.ui
@@ -25,6 +25,9 @@
<object class="GtkSeparator" id="header_separator">
<property name="orientation">vertical</property>
<property name="visible">True</property>
+ <style>
+ <class name="sidebar"/>
+ </style>
</object>
</child>
</object>
@@ -41,8 +44,7 @@
<property name="orientation">vertical</property>
<property name="visible">True</property>
<child>
- <object class="GtkStackSidebar" id="sidebar">
- <property name="margin-top">4</property>
+ <object class="GamesPreferencesSidebar" id="sidebar">
<property name="stack">stack</property>
<property name="vexpand">True</property>
<property name="visible">True</property>
@@ -58,6 +60,9 @@
<object class="GtkSeparator" id="separator">
<property name="orientation">vertical</property>
<property name="visible">True</property>
+ <style>
+ <class name="sidebar"/>
+ </style>
</object>
</child>
<child>
diff --git a/src/meson.build b/src/meson.build
index 26b2ec3e..3a3ade7f 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -160,6 +160,7 @@ vala_sources = [
'ui/preferences-page-plugins.vala',
'ui/preferences-page-plugins-item.vala',
'ui/preferences-page-video.vala',
+ 'ui/preferences-sidebar.vala',
'ui/preferences-window.vala',
'ui/quit-dialog.vala',
'ui/remote-display.vala',
diff --git a/src/ui/preferences-sidebar.vala b/src/ui/preferences-sidebar.vala
new file mode 100644
index 00000000..27d5fda9
--- /dev/null
+++ b/src/ui/preferences-sidebar.vala
@@ -0,0 +1,225 @@
+// This file is part of GNOME Games. License: GPL-3.0+.
+
+private class Games.PreferencesSidebar: Gtk.Bin {
+ private Gtk.Stack _stack;
+ public Gtk.Stack stack {
+ get {
+ return _stack;
+ }
+ set {
+ if (_stack != null) {
+ disconnect_stack_signals ();
+ clear_sidebar ();
+ _stack = null;
+ }
+
+ _stack = value;
+
+ if (_stack != null) {
+ populate_sidebar ();
+ connect_stack_signals ();
+ }
+
+ queue_resize ();
+ }
+ }
+
+ private bool _folded;
+ public bool folded {
+ get { return _folded; }
+ set {
+ _folded = value;
+
+ if (_folded)
+ list.selection_mode = Gtk.SelectionMode.NONE;
+ else {
+ list.selection_mode = Gtk.SelectionMode.SINGLE;
+ on_child_changed ();
+ }
+ }
+ }
+
+ public signal void row_selected ();
+
+ private Gtk.ListBox list;
+ private HashTable<Gtk.Widget, Gtk.ListBoxRow> rows;
+ private bool in_child_changed;
+
+ private ulong on_stack_child_added_id;
+ private ulong on_stack_child_removed_id;
+ private ulong on_child_changed_id;
+
+ static construct {
+ set_css_name ("stacksidebar");
+ }
+
+ construct {
+ var sw = new Gtk.ScrolledWindow (null, null);
+ sw.show ();
+ sw.set_no_show_all (true);
+ sw.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+
+ add (sw);
+
+ list = new Gtk.ListBox ();
+ list.show ();
+
+ sw.add (list);
+
+ list.set_sort_func (sort_list);
+
+ list.row_activated.connect (row_activated);
+
+ get_style_context ().add_class ("sidebar");
+
+ rows = new HashTable<Gtk.Widget, Gtk.ListBoxRow> (null, null);
+ }
+
+ private int sort_list (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
+ int left = 0;
+ int right = 0;
+
+ if (row1 != null) {
+ var item = row1.get_child ();
+ Gtk.Widget widget = item.get_data ("stack-child");
+ stack.child_get (widget, "position", out left, null);
+ }
+
+ if (row2 != null) {
+ var item = row2.get_child ();
+ Gtk.Widget widget = item.get_data ("stack-child");
+ stack.child_get (widget, "position", out right, null);
+ }
+
+ if (left < right)
+ return -1;
+
+ if (left > right)
+ return 1;
+
+ return 0;
+ }
+
+ private void row_activated (Gtk.ListBox box, Gtk.ListBoxRow? row) {
+ if (in_child_changed)
+ return;
+
+ if (row == null)
+ return;
+
+ var bin = row as Gtk.Bin;
+ var item = bin.get_child ();
+ Gtk.Widget widget = item.get_data ("stack-child");
+ stack.visible_child = widget;
+
+ row_selected ();
+ }
+
+ private void update_row (Gtk.Widget widget, Gtk.Widget row) {
+ var title = "";
+ var needs_attention = false;
+
+ stack.child_get (widget, "title", out title, null);
+ stack.child_get (widget, "needs-attention", out needs_attention, null);
+
+ var bin = row as Gtk.Bin;
+ var item = bin.get_child () as Gtk.Label;
+ item.set_text (title);
+
+ row.visible = widget.visible && title != null;
+
+ if (needs_attention)
+ row.get_style_context ().add_class (Gtk.STYLE_CLASS_NEEDS_ATTENTION);
+ else
+ row.get_style_context ().remove_class (Gtk.STYLE_CLASS_NEEDS_ATTENTION);
+ }
+
+ private void on_position_updated (Object object, ParamSpec param) {
+ list.invalidate_sort ();
+ }
+
+ private void on_child_updated (Object object, ParamSpec param) {
+ var widget = object as Gtk.Widget;
+ var row = rows[widget];
+ update_row (widget, row);
+ }
+
+ private void add_child (Gtk.Widget widget) {
+ /* Check we don't actually already know about this widget */
+ if (widget in rows)
+ return;
+
+ /* Make a pretty item when we add kids */
+ var item = new Gtk.Label ("");
+ item.set_halign (Gtk.Align.START);
+ item.set_valign (Gtk.Align.START);
+ var row = new Gtk.ListBoxRow ();
+ row.add (item);
+ item.show ();
+
+ update_row (widget, row);
+
+ /* Hook up for events */
+ widget.child_notify["title"].connect (on_child_updated);
+ widget.child_notify["needs-attention"].connect (on_child_updated);
+ widget.notify["visible"].connect (on_child_updated);
+ widget.child_notify["position"].connect (on_position_updated);
+
+ item.set_data ("stack-child", widget);
+ rows[widget] = row;
+ list.add (row);
+ }
+
+ private void remove_child (Gtk.Widget widget) {
+ var row = rows[widget];
+ if (row == null)
+ return;
+
+ list.remove (row);
+ rows.remove (widget);
+}
+
+ private void populate_sidebar () {
+ stack.foreach (add_child);
+
+ var widget = stack.get_visible_child ();
+ if (widget != null) {
+ var row = rows[widget];
+ list.select_row (row);
+ }
+ }
+
+ private void clear_sidebar () {
+ stack.foreach (remove_child);
+ }
+
+ private void on_child_changed () {
+ var child = stack.get_visible_child ();
+ var row = rows[child];
+ if (row != null) {
+ in_child_changed = true;
+ list.select_row (row);
+ in_child_changed = false;
+ }
+ }
+
+ private void on_stack_child_added (Gtk.Widget widget) {
+ add_child (widget);
+ }
+
+ private void on_stack_child_removed (Gtk.Widget widget) {
+ remove_child (widget);
+ }
+
+ private void disconnect_stack_signals () {
+ stack.disconnect (on_stack_child_added_id);
+ stack.disconnect (on_stack_child_removed_id);
+ stack.disconnect (on_child_changed_id);
+ }
+
+ private void connect_stack_signals () {
+ on_stack_child_added_id = stack.add.connect (on_stack_child_added);
+ on_stack_child_removed_id = stack.remove.connect (on_stack_child_removed);
+ on_child_changed_id = stack.notify["visible-child"].connect (on_child_changed);
+ }
+}
diff --git a/src/ui/preferences-window.vala b/src/ui/preferences-window.vala
index cac46cb2..a0a3a738 100644
--- a/src/ui/preferences-window.vala
+++ b/src/ui/preferences-window.vala
@@ -13,6 +13,8 @@ private class Games.PreferencesWindow : Gtk.Window {
[GtkChild]
private Gtk.Box sidebar_vbox;
[GtkChild]
+ private PreferencesSidebar sidebar;
+ [GtkChild]
private Gtk.Separator separator;
[GtkChild]
private Gtk.Stack stack;
@@ -72,7 +74,8 @@ private class Games.PreferencesWindow : Gtk.Window {
var page = child as PreferencesPage;
stack.notify["visible-child-name"].connect (page.visible_page_changed);
});
- stack.notify["visible-child-name"].connect (visible_child_changed);
+ sidebar.row_selected.connect (visible_child_changed);
+ //stack.notify["visible-child-name"].connect (visible_child_changed);
visible_child_changed ();
}
@@ -101,6 +104,7 @@ private class Games.PreferencesWindow : Gtk.Window {
var folded = main_box.get_fold () == Hdy.Fold.FOLDED;
left_header_bar.show_close_button = folded;
+ sidebar.folded = folded;
back_button.visible = folded;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]