[gnome-contacts] Clean up revealer code
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-contacts] Clean up revealer code
- Date: Thu, 7 Feb 2013 19:51:09 +0000 (UTC)
commit 15915bd3e7155f16567737153689d1eb7e224e20
Author: Alexander Larsson <alexl redhat com>
Date: Thu Feb 7 20:55:26 2013 +0100
Clean up revealer code
src/contacts-revealer.vala | 310 +++++++++++++++++++++++++++++++++++---------
1 files changed, 251 insertions(+), 59 deletions(-)
---
diff --git a/src/contacts-revealer.vala b/src/contacts-revealer.vala
index db3022e..f415ffc 100644
--- a/src/contacts-revealer.vala
+++ b/src/contacts-revealer.vala
@@ -18,97 +18,289 @@
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 double transition_ease_out_quad (double t,
+ double d) {
+ double p = t / d;
+ return -1.0 * p * (p - 2);
+}
+
+public class Contacts.Revealer : Bin {
+ public Gtk.Orientation orientation { get; set; default = Gtk.Orientation.HORIZONTAL; }
+ public int duration { get; set; default = 250;}
+
+ private Gdk.Window? bin_window;
+ private Gdk.Window? view_window;
+
+ private double current_pos;
+ private double source_pos;
+ private double target_pos;
+
+ private const int frame_time = 17; /* 17 msec ~= 60fps */
private uint timeout;
+ private int64 start_time;
+ private int64 end_time;
public Revealer () {
- this.set_shadow_type (ShadowType.NONE);
- target_amount = amount_visible = 0.0;
- vadjustment = get_vadjustment ();
+ target_pos = current_pos = 0.0;
+ set_has_window (true);
+ set_redraw_on_allocate (false);
}
- 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);
+ private void get_child_allocation (Gtk.Allocation allocation, out Gtk.Allocation child_allocation) {
+ child_allocation = { 0, 0, allocation.width, allocation.height };
+
+ var child = get_child ();
+ if (child != null && child.get_visible ()) {
+ if (orientation == Gtk.Orientation.HORIZONTAL)
+ child.get_preferred_height_for_width (child_allocation.width, null,
+ out child_allocation.height);
+ else
+ child.get_preferred_width_for_height (child_allocation.height, null,
+ out child_allocation.width);
}
}
- public override void show () {
- base.show ();
- if (target_amount != 1.0)
- reveal ();
+ public override void realize () {
+ set_realized (true);
+
+ Gtk.Allocation allocation;
+ get_allocation (out allocation);
+
+ Gdk.WindowAttr attributes = {};
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+ attributes.window_type = Gdk.WindowType.CHILD;
+ attributes.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT;
+ attributes.visual = get_visual ();
+ attributes.event_mask = get_events () | Gdk.EventMask.EXPOSURE_MASK;
+
+ var attributes_mask = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.VISUAL;
+ view_window = new Gdk.Window (get_parent_window (),
+ attributes, attributes_mask);
+
+ set_window (view_window);
+ view_window.set_user_data (this);
+
+ Gtk.Allocation child_allocation = { };
+ get_child_allocation (allocation, out child_allocation);
+
+ attributes.x = 0;
+ attributes.y = 0;
+ attributes.width = child_allocation.width;
+ attributes.height = child_allocation.height;
+
+ if (orientation == Gtk.Orientation.HORIZONTAL)
+ attributes.y = allocation.height - child_allocation.height;
+ else
+ attributes.x = allocation.width - child_allocation.width;
+
+ bin_window = new Gdk.Window (view_window, attributes, attributes_mask);
+ bin_window.set_user_data (this);
+
+ var child = get_child ();
+ if (child != null)
+ child.set_parent_window (bin_window);
+
+ var context = get_style_context ();
+ context.set_background (view_window);
+ context.set_background (bin_window);
+
+ bin_window.show ();
}
- public override void hide () {
- base.hide ();
- target_amount = 0;
- amount_visible = 0;
- if (timeout != 0) {
- Source.remove (timeout);
- timeout = 0;
+ public override void unrealize () {
+ view_window.set_user_data (this);
+ view_window.destroy ();
+ view_window = null;
+
+ base.unrealize ();
+ }
+
+ public override void add (Gtk.Widget child) {
+ child.set_parent_window (bin_window);
+ child.set_child_visible (current_pos != 0.0);
+ base.add (child);
+ }
+
+ public override void style_updated () {
+ base.style_updated ();
+
+ if (get_realized ()) {
+ var context = get_style_context ();
+ context.set_background (bin_window);
+ context.set_background (view_window);
}
}
-
- public void reveal () {
- target_amount = 1.0;
- this.show ();
- ensure_timer ();
+ public override void size_allocate (Gtk.Allocation allocation) {
+ set_allocation (allocation);
+
+ Gtk.Allocation child_allocation = { };
+ get_child_allocation (allocation, out child_allocation);
+
+ var child = get_child ();
+ if (child != null && child.get_visible ())
+ child.size_allocate (child_allocation);
+
+ if (get_realized ()) {
+ if (get_mapped ()) {
+ var window_visible = allocation.width > 0 && allocation.height > 0;
+
+ if (!window_visible && view_window.is_visible ())
+ view_window.hide ();
+ if (window_visible && !view_window.is_visible ())
+ view_window.show ();
+ }
+ view_window.move_resize (allocation.x, allocation.y,
+ allocation.width, allocation.height);
+ int bin_x = 0;
+ int bin_y = 0;
+ if (orientation == Gtk.Orientation.HORIZONTAL)
+ bin_y = allocation.height - child_allocation.height;
+ else
+ bin_x = allocation.width - child_allocation.width;
+
+ bin_window.move_resize (bin_x, bin_y,
+ child_allocation.width, child_allocation.height);
+ }
}
- public void unreveal () {
- target_amount = 0.0;
- ensure_timer ();
+ private void set_amount (double amount) {
+ current_pos = amount;
+ // We check target_pos here too, because we want to ensure we set
+ // child_visible immediately when starting a reveal operation
+ // otherwise the child widgets will not be properly realized
+ // after the reveal returns.
+ bool new_visible = amount != 0.0 || target_pos != 0.0;
+ var child = get_child ();
+ if (child != null && new_visible != child.get_child_visible ())
+ child.set_child_visible (new_visible);
+ queue_resize ();
}
- 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);
+ private void animate_step (int64 now) {
+ double t = 1.0;
+ if (now < end_time)
+ t = (now - start_time) / (double) (end_time - start_time);
+
+ t = transition_ease_out_quad (t, 1.0);
+
+ set_amount (source_pos + t * (target_pos - source_pos));
+ }
+
+ private bool animate_cb () {
+ int64 now = get_monotonic_time ();
+
+ animate_step (now);
+
+ if (current_pos == target_pos) {
+ timeout = 0;
+ return false;
}
+ return true;
+ }
- queue_resize ();
+ private void start_animation (double target) {
+ if (target_pos == target)
+ return;
+
+ target_pos = target;
- if (amount_visible == target_amount) {
+ if (get_mapped ()) {
+ source_pos = current_pos;
+ start_time = get_monotonic_time ();
+ end_time = start_time + duration * 1000;
+ if (timeout == 0)
+ timeout = Gdk.threads_add_timeout (frame_time, animate_cb);
+
+ animate_step (start_time);
+ } else {
+ set_amount (target);
+ }
+ }
+
+ private void stop_animation () {
+ current_pos = target_pos;
+ if (timeout != 0) {
+ Source.remove (timeout);
timeout = 0;
+ }
+ }
- if (amount_visible == 0)
- this.hide ();
+ public override void map () {
+ if (!get_mapped ()) {
+ Gtk.Allocation allocation;
+ get_allocation (out allocation);
- return false;
+ if (allocation.width > 0 && allocation.height > 0)
+ view_window.show ();
+
+ start_animation (target_pos);
+ }
+
+ base.map ();
+ }
+
+ public override void unmap () {
+ base.unmap ();
+ stop_animation ();
+ }
+
+ public override bool draw (Cairo.Context cr) {
+ if (Gtk.cairo_should_draw_window (cr, bin_window)) {
+ base.draw (cr);
}
-
return true;
}
- public override void get_preferred_height (out int minimum_height, out int natural_height) {
+ public void reveal () {
+ start_animation (1.0);
+ }
+
+ public void unreveal () {
+ start_animation (0.0);
+ }
+
+ // These all report only the natural height, because its not really
+ // possible to allocate the right size during animation if the child
+ // size can change
+ 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);
+ if (orientation == Gtk.Orientation.HORIZONTAL) {
+ natural_height = (int) (natural_height * current_pos);
+ }
+ minimum_height = natural_height;
}
- public override void get_preferred_height_for_width (int width, out int minimum_height, out int natural_height) {
+ 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);
+ if (orientation == Gtk.Orientation.HORIZONTAL) {
+ natural_height = (int) (natural_height * current_pos);
+ }
+ minimum_height = natural_height;
}
- public override void size_allocate (Gtk.Allocation allocation) {
- base.size_allocate (allocation);
- var upper = vadjustment.get_upper ();
- vadjustment.set_value (upper - allocation.height);
+ public override void get_preferred_width (out int minimum_width,
+ out int natural_width) {
+ base.get_preferred_width (out minimum_width, out natural_width);
+ if (orientation == Gtk.Orientation.VERTICAL) {
+ natural_width = (int) (natural_width * current_pos);
+ }
+ minimum_width = natural_width;
+ }
+
+ public override void get_preferred_width_for_height (int height,
+ out int minimum_width,
+ out int natural_width) {
+ base.get_preferred_width_for_height (height, out minimum_width, out natural_width);
+ if (orientation == Gtk.Orientation.VERTICAL) {
+ natural_width = (int) (natural_width * current_pos);
+ }
+ minimum_width = natural_width;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]