[gnome-games/wip/exalm/libhandy2: 7/9] ui: Add PreferencesSidebar



commit b5b0d7fe721ee575d318edbb276f70dc3bf34bb0
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 | 225 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 226 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..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);
+       }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]