[gnome-games/wip/exalm/libhandy2: 21/22] ui: Add PreferencesSidebar
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/wip/exalm/libhandy2: 21/22] ui: Add PreferencesSidebar
- Date: Sun, 16 Sep 2018 08:58:39 +0000 (UTC)
commit 5cbc3ec5015eecc1f1fdce088732fa8c440e476e
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date: Wed Sep 12 15:02:49 2018 +0500
ui: Add PreferencesSidebar
src/meson.build | 1 +
src/ui/preferences-sidebar.vala | 227 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 228 insertions(+)
---
diff --git a/src/meson.build b/src/meson.build
index 9a886051..fcd62b54 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -157,6 +157,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-subpage.vala',
'ui/preferences-subpage-gamepad.vala',
'ui/preferences-subpage-keyboard.vala',
diff --git a/src/ui/preferences-sidebar.vala b/src/ui/preferences-sidebar.vala
new file mode 100644
index 00000000..130fe98b
--- /dev/null
+++ b/src/ui/preferences-sidebar.vala
@@ -0,0 +1,227 @@
+// 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.set_margin_top (4);
+ list.set_margin_bottom (4);
+ 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);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]