[gnome-contacts] Scroll reveal the search toolbar



commit 9f6eee599948942f329e66eba6f4f7088ed3ad85
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Jan 19 14:10:02 2012 +0100

    Scroll reveal the search toolbar

 src/Makefile.am             |    1 +
 src/contacts-list-pane.vala |   17 +++---
 src/contacts-revealer.vala  |  114 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+), 8 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index a6dd734..503a95a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,7 @@ vala_sources = \
 	contacts-new-contact-dialog.vala \
 	contacts-avatar-menu.vala \
 	contacts-contact-frame.vala \
+	contacts-revealer.vala \
 	contacts-window.vala \
 	main.vala \
 	$(NULL)
diff --git a/src/contacts-list-pane.vala b/src/contacts-list-pane.vala
index 93b2761..eb3238b 100644
--- a/src/contacts-list-pane.vala
+++ b/src/contacts-list-pane.vala
@@ -28,7 +28,7 @@ public class Contacts.ListPane : Frame {
   private ulong non_empty_id;
   private EventBox empty_box;
   private bool ignore_selection_change;
-  private Toolbar search_toolbar;
+  private Revealer search_revealer;
   private bool search_visible;
 
   public signal void selection_changed (Contact? contact);
@@ -60,12 +60,11 @@ public class Contacts.ListPane : Frame {
   public void set_search_visible (bool visible) {
     search_visible = visible;
     if (visible) {
-      search_toolbar.show_all ();
-      search_toolbar.show ();
+      search_revealer.reveal ();
       filter_entry.grab_focus ();
     } else {
+      search_revealer.unreveal ();
       filter_entry.set_text ("");
-      search_toolbar.hide ();
     }
   }
 
@@ -90,12 +89,14 @@ public class Contacts.ListPane : Frame {
     this.contacts_store = contacts_store;
     this.contacts_view = new View (contacts_store);
     var toolbar = new Toolbar ();
-    search_toolbar = toolbar;
     toolbar.get_style_context ().add_class (STYLE_CLASS_PRIMARY_TOOLBAR);
     toolbar.set_icon_size (IconSize.MENU);
     toolbar.set_vexpand (false);
     toolbar.set_hexpand (true);
 
+    search_revealer = new Revealer ();
+    search_revealer.add (toolbar);
+
     contacts_view.set_show_subset (View.Subset.MAIN);
 
     filter_entry = new Entry ();
@@ -182,13 +183,13 @@ public class Contacts.ListPane : Frame {
     empty_box.show_all ();
     empty_box.set_no_show_all (true);
 
-    grid.add (toolbar);
+    grid.add (search_revealer);
     grid.add (scrolled);
     grid.add (empty_box);
 
     this.show_all ();
-    toolbar.set_no_show_all (true);
-    toolbar.hide ();
+    search_revealer.set_no_show_all (true);
+    search_revealer.hide ();
 
     if (contacts_store.is_empty ()) {
       empty_box.show ();
diff --git a/src/contacts-revealer.vala b/src/contacts-revealer.vala
new file mode 100644
index 0000000..db3022e
--- /dev/null
+++ b/src/contacts-revealer.vala
@@ -0,0 +1,114 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 8 -*- */
+/*
+ * Copyright (C) 2011 Alexander Larsson <alexl redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using Gtk;
+
+public class Contacts.Revealer : Viewport {
+  protected Gdk.Window bin_window;
+  protected Gdk.Window view_window;
+  protected Adjustment vadjustment;
+  protected double amount_visible;
+  protected double target_amount;
+  const int animation_time = 200;
+  const int animation_n_steps = 8;
+  private uint timeout;
+
+  public Revealer () {
+    this.set_shadow_type (ShadowType.NONE);
+    target_amount = amount_visible = 0.0;
+    vadjustment = get_vadjustment ();
+  }
+
+  private void ensure_timer () {
+    if (timeout == 0) {
+      if (amount_visible == target_amount)
+	return;
+      
+      timeout = Gdk.threads_add_timeout (animation_time /  animation_n_steps,
+					 animate_cb);
+    }
+  }
+
+  public override void show () {
+    base.show ();
+    if (target_amount != 1.0)
+      reveal ();
+  }
+
+  public override void hide () {
+    base.hide ();
+    target_amount = 0;
+    amount_visible = 0;
+    if (timeout != 0) {
+      Source.remove (timeout);
+      timeout = 0;
+    }
+  }
+  
+  
+  public void reveal () {
+    target_amount = 1.0;
+    this.show ();
+    ensure_timer ();
+  }
+
+  public void unreveal () {
+    target_amount = 0.0;
+    ensure_timer ();
+  }
+
+  private  bool animate_cb () {
+    double delta = 1.0 /  animation_n_steps;
+    if (amount_visible < target_amount) {
+      amount_visible = double.min (target_amount, amount_visible + delta);
+    } else {
+      amount_visible = double.max (target_amount, amount_visible - delta);
+    }
+
+    queue_resize ();
+
+    if (amount_visible == target_amount) {
+      timeout = 0;
+
+      if (amount_visible == 0)
+	this.hide ();
+      
+      return false;
+    }
+    
+    return true;
+  }
+
+  public override void get_preferred_height (out int minimum_height, out int natural_height) {
+    base.get_preferred_height (out minimum_height, out natural_height);
+    minimum_height = (int) (minimum_height * amount_visible);
+    natural_height = (int) (natural_height * amount_visible);
+  }
+
+  public override void get_preferred_height_for_width (int width, out int minimum_height, out int natural_height) {
+    base.get_preferred_height_for_width (width, out minimum_height, out natural_height);
+    minimum_height = (int) (minimum_height * amount_visible);
+    natural_height = (int) (natural_height * amount_visible);
+  }
+
+  public override void size_allocate (Gtk.Allocation allocation) {
+    base.size_allocate (allocation);
+    var upper = vadjustment.get_upper ();
+    vadjustment.set_value (upper - allocation.height);
+  }
+}



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